diff --git a/common/include/dscreen_constants.h b/common/include/dscreen_constants.h index 9e37aa03a5497814f37b813ca86b704d5ed3da48..b684ff584308e728243ea229a7823cc813a6728c 100644 --- a/common/include/dscreen_constants.h +++ b/common/include/dscreen_constants.h @@ -74,12 +74,25 @@ enum DScreenEventType : uint32_t { TRANS_CHANNEL_CLOSED = 1, }; +struct VideoData { + uint8_t *data; + size_t size; + uint32_t width; + uint32_t height; + int64_t timestamp; + std::string format; +}; + /* Screen package name */ const std::string PKG_NAME = "ohos.dhardware.dscreen"; /* Screen data session name */ const std::string DATA_SESSION_NAME = "ohos.dhardware.dscreen.data"; const std::string JPEG_SESSION_NAME = "ohos.dhardware.dscreen.jpeg"; + +/* Screen dump data file path name */ +const std::string DUMP_FILE_PATH = "/data/data/dscreen"; + /*YUV*/ constexpr int32_t YR_PARAM = 66; constexpr int32_t YG_PARAM = 129; @@ -123,6 +136,9 @@ constexpr uint32_t DSCREEN_MAX_SCREEN_DATA_WIDTH = 2560; /* Screen max screen data height */ constexpr uint32_t DSCREEN_MAX_SCREEN_DATA_HEIGHT = 2772; +/* Screen dump data max file size */ +constexpr uint32_t DUMP_FILE_MAX_SIZE = 295 * 1024 * 1024; + /* YUV420 buffer size max size */ constexpr int64_t MAX_YUV420_BUFFER_SIZE = 2560 * 1600 * (3 / 2) * 2; constexpr int32_t DSCREEN_MAX_LEN = 4096; diff --git a/services/screenservice/sinkservice/BUILD.gn b/services/screenservice/sinkservice/BUILD.gn index aca0540e82b45e15746129321fb44a86fde3444f..d50e14102b4393e9861465990427caf87d1c320a 100644 --- a/services/screenservice/sinkservice/BUILD.gn +++ b/services/screenservice/sinkservice/BUILD.gn @@ -46,6 +46,7 @@ ohos_shared_library("distributed_screen_sink") { "${services_path}/common/utils/src/dscreen_fwkkit.cpp", "${services_path}/common/utils/src/dscreen_maprelation.cpp", "${services_path}/common/utils/src/video_param.cpp", + "./dscreenservice/src/dscreen_sink_hidumper.cpp", "./dscreenservice/src/dscreen_sink_service.cpp", "./dscreenservice/src/dscreen_sink_stub.cpp", "./screenregionmgr/1.0/src/screenregion.cpp", @@ -67,6 +68,10 @@ ohos_shared_library("distributed_screen_sink") { "LOG_DOMAIN=0xD004100", ] + if (build_variant == "root") { + defines += [ "DUMP_DSCREENREGION_FILE" ] + } + external_deps = [ "c_utils:utils", "distributed_hardware_fwk:distributed_av_receiver", diff --git a/services/screenservice/sinkservice/dscreenservice/include/dscreen_sink_hidumper.h b/services/screenservice/sinkservice/dscreenservice/include/dscreen_sink_hidumper.h new file mode 100644 index 0000000000000000000000000000000000000000..0cd16e013c55c038560579f58c7a17658df7227d --- /dev/null +++ b/services/screenservice/sinkservice/dscreenservice/include/dscreen_sink_hidumper.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_SCREEN_SINK_HIDUMPER_H +#define OHOS_DISTRIBUTED_SCREEN_SINK_HIDUMPER_H + +#include +#include +#include + +#include +#include +#include + +#include "single_instance.h" + +namespace OHOS { +namespace DistributedHardware { +enum class HidumpFlag { + UNKNOWN = 0, + GET_HELP, + DUMP_SINK_SCREEN_DATA, + DUMP_SINK_SCREEN_DATA_RESTART, +}; + +class DscreenSinkHidumper { + DECLARE_SINGLE_INSTANCE_BASE(DscreenSinkHidumper); + +public: + bool Dump(const std::vector &args, std::string &result); + bool GetFlagStatus(); + void SetFlagFalse(); + bool GetFileFlag(); + bool GetReDumpFlag(); + void SetFileFlagFalse(); + void SetFileFlagTrue(); + void SetReDumpFlagFalse(); + void SetReDumpFlagTrue(); + DscreenSinkHidumper(); + ~DscreenSinkHidumper(); + +private: + void ShowHelp(std::string &result); + int32_t ShowIllegalInfomation(std::string &result); + int32_t ProcessDump(const std::string &args, std::string &result); + + int32_t DumpScreenData(std::string &result); + int32_t ReDumpScreenData(std::string &result); + +private: + bool HidumperFlag_ = false; + bool FileFullFlag_ = false; + bool ReDumpFlag_ = false; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_SCREEN_SINK_HIDUMPER_H \ No newline at end of file diff --git a/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_hidumper.cpp b/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_hidumper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..796cb0e81e3078f89cf32b7634b1eec45eebdf0a --- /dev/null +++ b/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_hidumper.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dscreen_sink_hidumper.h" + +#include "dscreen_constants.h" +#include "dscreen_errcode.h" +#include "dscreen_log.h" +#include "dscreen_util.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DscreenSinkHidumper" + +namespace OHOS { +namespace DistributedHardware { +IMPLEMENT_SINGLE_INSTANCE(DscreenSinkHidumper); +namespace { +const std::string ARGS_HELP = "-h"; +const std::string ARGS_DUMP_SINK_SCREEN_DATA = "--dump"; +const std::string ARGS_DUMP_SINK_SCREEN_DATA_RESTART = "--redump"; + +const std::map ARGS_MAP = { + { ARGS_HELP, HidumpFlag::GET_HELP }, + { ARGS_DUMP_SINK_SCREEN_DATA, HidumpFlag::DUMP_SINK_SCREEN_DATA }, + { ARGS_DUMP_SINK_SCREEN_DATA_RESTART, HidumpFlag::DUMP_SINK_SCREEN_DATA_RESTART }, +}; +} + +DscreenSinkHidumper::DscreenSinkHidumper() +{ + DHLOGI("Distributed screen hidumper constructed."); +} + +DscreenSinkHidumper::~DscreenSinkHidumper() +{ + DHLOGI("Distributed screen hidumper deconstructed."); +} + +bool DscreenSinkHidumper::Dump(const std::vector &args, std::string &result) +{ + DHLOGI("Distributed screen hidumper dump args.size():%d.", args.size()); + result.clear(); + int32_t argsSize = static_cast(args.size()); + for (int32_t i = 0; i < argsSize; i++) { + DHLOGI("Distributed screen hidumper dump args[%d]: %s.", i, args.at(i).c_str()); + } + + if (args.empty()) { + ShowHelp(result); + return true; + } else if (args.size() > 1) { + ShowIllegalInfomation(result); + return true; + } + + return ProcessDump(args[0], result) == DH_SUCCESS; +} + +int32_t DscreenSinkHidumper::ProcessDump(const std::string &args, std::string &result) +{ + DHLOGI("Process dump."); + HidumpFlag hf = HidumpFlag::UNKNOWN; + auto operatorIter = ARGS_MAP.find(args); + if (operatorIter != ARGS_MAP.end()) { + hf = operatorIter->second; + } + + if (hf == HidumpFlag::GET_HELP) { + ShowHelp(result); + return DH_SUCCESS; + } + result.clear(); + switch (hf) { + case HidumpFlag::DUMP_SINK_SCREEN_DATA: { + return DumpScreenData(result); + } + case HidumpFlag::DUMP_SINK_SCREEN_DATA_RESTART: { + return ReDumpScreenData(result); + } + default: { + return ShowIllegalInfomation(result); + } + } +} + +int32_t DscreenSinkHidumper::DumpScreenData(std::string &result) +{ + DHLOGI("Dump screen data."); + + if (access(DUMP_FILE_PATH.c_str(), 0) < 0) { + if (mkdir(DUMP_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { + DHLOGI("Create dir err."); + DHLOGI("dir path : %s", DUMP_FILE_PATH.c_str()); + return DSCREEN_BAD_VALUE; + } + } + + if (FileFullFlag_ == false) { + result.append("Dump..."); + HidumperFlag_ = true; + } else { + result.append("File oversize 300M : stop dump, use parameter \"--redump\" to clear dumpfile and redump"); + } + return DH_SUCCESS; +} + +int32_t DscreenSinkHidumper::ReDumpScreenData(std::string &result) +{ + DHLOGI("Redump screen data."); + + if (access(DUMP_FILE_PATH.c_str(), 0) < 0) { + if (mkdir(DUMP_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { + DHLOGI("Create dir err."); + DHLOGI("dir path : %s", DUMP_FILE_PATH.c_str()); + return DSCREEN_BAD_VALUE; + } + } + SetFileFlagFalse(); + SetReDumpFlagTrue(); + result.append("ReDumpStart..."); + HidumperFlag_ = true; + return DH_SUCCESS; +} + +bool DscreenSinkHidumper::GetFlagStatus() +{ + return HidumperFlag_; +} + +void DscreenSinkHidumper::SetFlagFalse() +{ + HidumperFlag_ = false; +} + +bool DscreenSinkHidumper::GetFileFlag() +{ + return FileFullFlag_; +} + +void DscreenSinkHidumper::SetFileFlagFalse() +{ + FileFullFlag_ = false; +} + +void DscreenSinkHidumper::SetFileFlagTrue() +{ + FileFullFlag_ = true; +} + +bool DscreenSinkHidumper::GetReDumpFlag() +{ + return ReDumpFlag_; +} + +void DscreenSinkHidumper::SetReDumpFlagFalse() +{ + ReDumpFlag_ = false; +} + +void DscreenSinkHidumper::SetReDumpFlagTrue() +{ + ReDumpFlag_ = true; +} + +void DscreenSinkHidumper::ShowHelp(std::string &result) +{ + DHLOGI("Show help."); + result.append("Usage:dump [options]\n") + .append("Description:\n") + .append("-h ") + .append(": show help\n") + .append("--dump ") + .append(": dump sink screen data in /data/data/dscreen\n") + .append("--redump ") + .append(": clear file and restart dump sink screen data\n"); +} + +int32_t DscreenSinkHidumper::ShowIllegalInfomation(std::string &result) +{ + DHLOGI("Show illegal information."); + result.append("unknown command, -h for help."); + return DH_SUCCESS; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_service.cpp b/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_service.cpp index 95daa9f601faa895107adeb64d16121e12d84fc6..3a79d3b60674759f26f06022f565adf1a3bfc481 100644 --- a/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_service.cpp +++ b/services/screenservice/sinkservice/dscreenservice/src/dscreen_sink_service.cpp @@ -21,6 +21,7 @@ #include "string_ex.h" #include "system_ability_definition.h" +#include "dscreen_sink_hidumper.h" #include "dscreen_constants.h" #include "dscreen_errcode.h" #include "dscreen_log.h" @@ -133,6 +134,22 @@ int32_t DScreenSinkService::Dump(int32_t fd, const std::vector& return ERR_DH_SCREEN_SA_HIDUMPER_ERROR; } + std::string result; + std::vector argsStr; + + std::transform(args.cbegin(), args.cend(), std::back_inserter(argsStr), + [](const std::u16string &item) { return Str16ToStr8(item); }); + + if (!DscreenSinkHidumper::GetInstance().Dump(argsStr, result)) { + DHLOGE("Hidump error"); + return ERR_DH_SCREEN_SA_HIDUMPER_ERROR; + } + + ret = dprintf(fd, "%s\n", result.c_str()); + if (ret < 0) { + DHLOGE("Dprintf error"); + return DSCREEN_BAD_VALUE; + } return ERR_OK; } } // namespace DistributedHardware diff --git a/services/screenservice/sinkservice/screenregionmgr/2.0/include/av_receiver_engine_adapter.h b/services/screenservice/sinkservice/screenregionmgr/2.0/include/av_receiver_engine_adapter.h index a8bd2351ef8b4bcdf976729ccdde3fceb22bbe4c..c2628cc4ac24de98a3264b7d565d07554b98c86b 100644 --- a/services/screenservice/sinkservice/screenregionmgr/2.0/include/av_receiver_engine_adapter.h +++ b/services/screenservice/sinkservice/screenregionmgr/2.0/include/av_receiver_engine_adapter.h @@ -23,6 +23,7 @@ #include #include +#include "dscreen_constants.h" #include "i_av_engine_provider.h" #include "video_param.h" diff --git a/services/screenservice/sinkservice/screenregionmgr/2.0/include/screenregion.h b/services/screenservice/sinkservice/screenregionmgr/2.0/include/screenregion.h index fba417d2a11cad802c5735e6857c8edfc05addb6..e7f3447fe9243f82afd1854f6c3489f87a8e9764 100644 --- a/services/screenservice/sinkservice/screenregionmgr/2.0/include/screenregion.h +++ b/services/screenservice/sinkservice/screenregionmgr/2.0/include/screenregion.h @@ -16,7 +16,10 @@ #ifndef OHOS_DSCREEN_SCREEN_REGION_V2_0_H #define OHOS_DSCREEN_SCREEN_REGION_V2_0_H +#include +#include #include +#include #include "surface.h" @@ -39,6 +42,7 @@ public: void OnEngineMessage(const std::shared_ptr &message) override; void OnEngineDataDone(const std::shared_ptr &buffer) override; void GetWSBuffer(sptr &wsBuffer, const std::shared_ptr &buffer); + void SaveFile(std::string file, const VideoData &video); int32_t Release(); int32_t InitReceiverEngine(IAVEngineProvider *providerPtr); diff --git a/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp b/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp index 139bf2001c9e19fd994e37c627adb9a31f13493d..922c362d5e097e0d3bc3c0ede1e7de390d94d176 100644 --- a/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp +++ b/services/screenservice/sinkservice/screenregionmgr/2.0/src/screenregion.cpp @@ -22,6 +22,7 @@ #include "dscreen_fwkkit.h" #include "dscreen_hisysevent.h" #include "dscreen_log.h" +#include "dscreen_sink_hidumper.h" #include "dscreen_json_util.h" #include "dscreen_util.h" #include "screen.h" @@ -337,6 +338,17 @@ void ScreenRegion::OnEngineDataDone(const std::shared_ptr &buffer return; } GetWSBuffer(wsBuffer, buffer); +#ifdef DUMP_DSCREENREGION_FILE + uint32_t surBufSize = wsBuffer->GetSize(); + auto surBufAddr = static_cast(wsBuffer->GetVirAddr()); + int64_t timestamp = 0; + VideoData data = {surBufAddr, surBufSize, requestConfig.width, requestConfig.height, timestamp, "ycbcr_sp420"}; + if (DscreenSinkHidumper::GetInstance().GetFlagStatus() == true) { + DHLOGE("HidumperFlag_ = true, exec SaveFile"); + SaveFile("Screen_AfterEncoding_width(", data); + DscreenSinkHidumper::GetInstance().SetFlagFalse(); + } +#endif BufferFlushConfig flushConfig = { {0, 0, wsBuffer->GetWidth(), wsBuffer->GetHeight()}, 0}; surfaceErr = windowSurface_->FlushBuffer(wsBuffer, -1, flushConfig); if (surfaceErr != SURFACE_ERROR_OK) { @@ -347,6 +359,36 @@ void ScreenRegion::OnEngineDataDone(const std::shared_ptr &buffer DHLOGI("Fill video buffer data to window surface success. frameNumber: %zu", frameNumber_.load()); } +void ScreenRegion::SaveFile(std::string file, const VideoData &video) +{ + DHLOGE("Saving File."); + std::string fileName = DUMP_FILE_PATH + "/" + file + std::to_string(video.width) + ")_height(" + + std::to_string(video.height) + ")_" + video.format + ".jpg"; + DHLOGE("fileName = %s", fileName.c_str()); + if (DscreenSinkHidumper::GetInstance().GetReDumpFlag() == true) { + std::remove(fileName.c_str()); + DscreenSinkHidumper::GetInstance().SetReDumpFlagFalse(); + } + std::ofstream ofs(fileName, std::ios::binary | std::ios::out | std::ios::app); + + if (!ofs.is_open()) { + DHLOGE("open file failed."); + return; + } + DHLOGE("open Hidumper SaveFile file success."); + ofs.seekp(0, std::ios::end); + uint32_t fileSize = ofs.tellp(); + DHLOGE("fileSize = %d, video.size = %d, maxsize = %d", fileSize, video.size, + DUMP_FILE_MAX_SIZE); + if ((fileSize + video.size) < DUMP_FILE_MAX_SIZE) { + DscreenSinkHidumper::GetInstance().SetFileFlagFalse(); + ofs.write((const char *)(video.data), video.size); + } else { + DscreenSinkHidumper::GetInstance().SetFileFlagTrue(); + } + ofs.close(); +} + uint64_t ScreenRegion::GetScreenId() { return screenId_; diff --git a/services/screenservice/sourceservice/BUILD.gn b/services/screenservice/sourceservice/BUILD.gn index 92469d0feace83de8711c954311ebb54fe782015..a0c2218322cc07cbdfb4166a3ef6a3d6d737efca 100644 --- a/services/screenservice/sourceservice/BUILD.gn +++ b/services/screenservice/sourceservice/BUILD.gn @@ -58,6 +58,7 @@ ohos_shared_library("distributed_screen_source") { "./dscreenmgr/2.0/src/dscreen_manager.cpp", "./dscreenmgr/common/src/screen_manager_adapter.cpp", "./dscreenservice/src/callback/dscreen_source_callback_proxy.cpp", + "./dscreenservice/src/dscreen_source_hidumper.cpp", "./dscreenservice/src/dscreen_source_service.cpp", "./dscreenservice/src/dscreen_source_stub.cpp", ] @@ -73,6 +74,10 @@ ohos_shared_library("distributed_screen_source") { "LOG_DOMAIN=0xD004100", ] + if (build_variant == "root") { + defines += [ "DUMP_DSCREEN_FILE" ] + } + external_deps = [ "c_utils:utils", "distributed_hardware_fwk:distributed_av_sender", diff --git a/services/screenservice/sourceservice/dscreenmgr/2.0/include/av_sender_engine_adapter.h b/services/screenservice/sourceservice/dscreenmgr/2.0/include/av_sender_engine_adapter.h index 51a92ef80d1ba9b4edb346f43dcdd871951a6b60..18fe7fc008c6a947cf5343fe2d4c6113564fd35f 100644 --- a/services/screenservice/sourceservice/dscreenmgr/2.0/include/av_sender_engine_adapter.h +++ b/services/screenservice/sourceservice/dscreenmgr/2.0/include/av_sender_engine_adapter.h @@ -23,19 +23,12 @@ #include #include +#include "dscreen_constants.h" #include "i_av_engine_provider.h" #include "video_param.h" namespace OHOS { namespace DistributedHardware { -struct VideoData { - uint8_t *data; - size_t size; - uint32_t width; - uint32_t height; - int64_t timestamp; - std::string format; -}; class AVSenderAdapterCallback { public: AVSenderAdapterCallback() {}; diff --git a/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h b/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h index 5cf6aecf080b973dbecf6dc963230554bd8e6e72..23621c4400b3d773161b6ad3c6699ae44efcad83 100644 --- a/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h +++ b/services/screenservice/sourceservice/dscreenmgr/2.0/include/dscreen.h @@ -17,9 +17,12 @@ #define OHOS_DSCREEN_V2_0_H #include +#include +#include #include #include #include +#include #include "sync_fence.h" #include "surface.h" @@ -93,6 +96,7 @@ public: int32_t AddTask(const std::shared_ptr &task); int32_t InitSenderEngine(IAVEngineProvider *providerPtr, const std::string &peerDevId); void ConsumeSurface(); + void SaveFile(std::string file, const VideoData &video); std::string GetDHId() const; std::string GetDevId() const; uint64_t GetScreenId() const; diff --git a/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp b/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp index ce9557a0c0ac8972afc862f20b9a5f74c9eeb693..afca2ca3cbb6ac7fc79103a3f0780e6f8ed5c422 100644 --- a/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp +++ b/services/screenservice/sourceservice/dscreenmgr/2.0/src/dscreen.cpp @@ -27,6 +27,7 @@ #include "dscreen_hisysevent.h" #include "dscreen_json_util.h" #include "dscreen_log.h" +#include "dscreen_source_hidumper.h" #include "dscreen_util.h" #include "common/include/screen_manager_adapter.h" @@ -319,6 +320,13 @@ void DScreen::ConsumeSurface() uint32_t videoWidth = videoParam_->GetVideoWidth(); uint32_t videoHeight = videoParam_->GetVideoHeight(); VideoData data = { surBufAddr, surBufSize, videoWidth, videoHeight, timestamp, VIDEO_FORMAT_RGBA8888 }; +#ifdef DUMP_DSCREEN_FILE + if (DscreenSourceHidumper::GetInstance().GetFlagStatus() == true) { + DHLOGE("HidumperFlag_ = true, exec SaveFile"); + SaveFile("Screen_BeforeCoding_width(", data); + DscreenSourceHidumper::GetInstance().SetFlagFalse(); + } +#endif int32_t ret = senderAdapter_->PushData(data); if (ret != DH_SUCCESS) { DHLOGE("feed buffer to av transport sender failed."); @@ -327,6 +335,36 @@ void DScreen::ConsumeSurface() DHLOGI("ConsumeSurface success. timestamp=%lld", (long long)timestamp); } +void DScreen::SaveFile(std::string file, const VideoData &video) +{ + DHLOGE("Saving File."); + std::string fileName = DUMP_FILE_PATH + "/" + file + std::to_string(video.width) + ")_height(" + + std::to_string(video.height) + ")_" + video.format + ".jpg"; + DHLOGE("fileName = %s", fileName.c_str()); + if (DscreenSourceHidumper::GetInstance().GetReDumpFlag() == true) { + std::remove(fileName.c_str()); + DscreenSourceHidumper::GetInstance().SetReDumpFlagFalse(); + } + std::ofstream ofs(fileName, std::ios::binary | std::ios::out | std::ios::app); + + if (!ofs.is_open()) { + DHLOGE("open file failed."); + return; + } + DHLOGE("open Hidumper SaveFile file success."); + ofs.seekp(0, std::ios::end); + uint32_t fileSize = ofs.tellp(); + DHLOGE("fileSize = %d, video.size = %d, maxsize = %d", fileSize, video.size, + DUMP_FILE_MAX_SIZE); + if ((fileSize + video.size) < DUMP_FILE_MAX_SIZE) { + DscreenSourceHidumper::GetInstance().SetFileFlagFalse(); + ofs.write((const char *)(video.data), video.size); + } else { + DscreenSourceHidumper::GetInstance().SetFileFlagTrue(); + } + ofs.close(); +} + int32_t DScreen::InitSenderEngine(IAVEngineProvider *providerPtr, const std::string &peerDevId) { DHLOGI("InitSenderEngine enter."); diff --git a/services/screenservice/sourceservice/dscreenservice/include/dscreen_source_hidumper.h b/services/screenservice/sourceservice/dscreenservice/include/dscreen_source_hidumper.h new file mode 100644 index 0000000000000000000000000000000000000000..e5c28d554de3d5d9bffe0f47b8f1131b8112bedd --- /dev/null +++ b/services/screenservice/sourceservice/dscreenservice/include/dscreen_source_hidumper.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_SCREEN_SOURCE_HIDUMPER_H +#define OHOS_DISTRIBUTED_SCREEN_SOURCE_HIDUMPER_H + +#include +#include +#include + +#include +#include +#include + +#include "single_instance.h" + +namespace OHOS { +namespace DistributedHardware { +enum class HidumpFlag { + UNKNOWN = 0, + GET_HELP, + DUMP_SOURCE_SCREEN_DATA, + DUMP_SOURCE_SCREEN_DATA_RESTART, +}; + +class DscreenSourceHidumper { + DECLARE_SINGLE_INSTANCE_BASE(DscreenSourceHidumper); + +public: + bool Dump(const std::vector &args, std::string &result); + bool GetFlagStatus(); + void SetFlagFalse(); + bool GetFileFlag(); + bool GetReDumpFlag(); + void SetFileFlagFalse(); + void SetFileFlagTrue(); + void SetReDumpFlagFalse(); + void SetReDumpFlagTrue(); + DscreenSourceHidumper(); + ~DscreenSourceHidumper(); + +private: + void ShowHelp(std::string &result); + int32_t ShowIllegalInfomation(std::string &result); + int32_t ProcessDump(const std::string &args, std::string &result); + + int32_t DumpScreenData(std::string &result); + int32_t ReDumpScreenData(std::string &result); + +private: + bool HidumperFlag_ = false; + bool FileFullFlag_ = false; + bool ReDumpFlag_ = false; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_SCREEN_SOURCE_HIDUMPER_H \ No newline at end of file diff --git a/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_hidumper.cpp b/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_hidumper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77d60ec1fec7affc0e32f08ee3919f6014b0cafe --- /dev/null +++ b/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_hidumper.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dscreen_source_hidumper.h" + +#include "dscreen_constants.h" +#include "dscreen_errcode.h" +#include "dscreen_log.h" +#include "dscreen_util.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DscreenSourceHidumper" + +namespace OHOS { +namespace DistributedHardware { +IMPLEMENT_SINGLE_INSTANCE(DscreenSourceHidumper); + +namespace { +const std::string ARGS_HELP = "-h"; +const std::string ARGS_DUMP_SOURCE_SCREEN_DATA = "--dump"; +const std::string ARGS_DUMP_SOURCE_SCREEN_DATA_RESTART = "--redump"; + +const std::map ARGS_MAP = { + { ARGS_HELP, HidumpFlag::GET_HELP }, + { ARGS_DUMP_SOURCE_SCREEN_DATA, HidumpFlag::DUMP_SOURCE_SCREEN_DATA }, + { ARGS_DUMP_SOURCE_SCREEN_DATA_RESTART, HidumpFlag::DUMP_SOURCE_SCREEN_DATA_RESTART }, +}; +} + +DscreenSourceHidumper::DscreenSourceHidumper() +{ + DHLOGI("Distributed screen hidumper constructed."); +} + +DscreenSourceHidumper::~DscreenSourceHidumper() +{ + DHLOGI("Distributed screen hidumper deconstructed."); +} + +bool DscreenSourceHidumper::Dump(const std::vector &args, std::string &result) +{ + DHLOGI("Distributed screen hidumper dump args.size():%d.", args.size()); + result.clear(); + int32_t argsSize = static_cast(args.size()); + for (int32_t i = 0; i < argsSize; i++) { + DHLOGI("Distributed screen hidumper dump args[%d]: %s.", i, args.at(i).c_str()); + } + + if (args.empty()) { + ShowHelp(result); + return true; + } else if (args.size() > 1) { + ShowIllegalInfomation(result); + return true; + } + + return ProcessDump(args[0], result) == DH_SUCCESS; +} + +int32_t DscreenSourceHidumper::ProcessDump(const std::string &args, std::string &result) +{ + DHLOGI("Process dump."); + HidumpFlag hf = HidumpFlag::UNKNOWN; + auto operatorIter = ARGS_MAP.find(args); + if (operatorIter != ARGS_MAP.end()) { + hf = operatorIter->second; + } + + if (hf == HidumpFlag::GET_HELP) { + ShowHelp(result); + return DH_SUCCESS; + } + result.clear(); + switch (hf) { + case HidumpFlag::DUMP_SOURCE_SCREEN_DATA: { + return DumpScreenData(result); + } + case HidumpFlag::DUMP_SOURCE_SCREEN_DATA_RESTART: { + return ReDumpScreenData(result); + } + default: { + return ShowIllegalInfomation(result); + } + } +} + +int32_t DscreenSourceHidumper::DumpScreenData(std::string &result) +{ + DHLOGI("Dump screen data."); + + if (access(DUMP_FILE_PATH.c_str(), 0) < 0) { + if (mkdir(DUMP_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { + DHLOGI("Create dir err."); + DHLOGI("dir path : %s", DUMP_FILE_PATH.c_str()); + return DSCREEN_BAD_VALUE; + } + } + + if (FileFullFlag_ == false) { + result.append("Dump..."); + HidumperFlag_ = true; + } else { + result.append("File oversize 300M : stop dump, use parameter \"--redump\" to clear dumpfile and redump"); + } + return DH_SUCCESS; +} + +int32_t DscreenSourceHidumper::ReDumpScreenData(std::string &result) +{ + DHLOGI("Redump screen data."); + + if (access(DUMP_FILE_PATH.c_str(), 0) < 0) { + if (mkdir(DUMP_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) { + DHLOGI("Create dir err."); + DHLOGI("dir path : %s", DUMP_FILE_PATH.c_str()); + return DSCREEN_BAD_VALUE; + } + } + SetFileFlagFalse(); + SetReDumpFlagTrue(); + result.append("ReDumpStart..."); + HidumperFlag_ = true; + return DH_SUCCESS; +} + +bool DscreenSourceHidumper::GetFlagStatus() +{ + return HidumperFlag_; +} + +void DscreenSourceHidumper::SetFlagFalse() +{ + HidumperFlag_ = false; +} + +bool DscreenSourceHidumper::GetFileFlag() +{ + return FileFullFlag_; +} + +void DscreenSourceHidumper::SetFileFlagFalse() +{ + FileFullFlag_ = false; +} + +void DscreenSourceHidumper::SetFileFlagTrue() +{ + FileFullFlag_ = true; +} + +bool DscreenSourceHidumper::GetReDumpFlag() +{ + return ReDumpFlag_; +} + +void DscreenSourceHidumper::SetReDumpFlagFalse() +{ + ReDumpFlag_ = false; +} + +void DscreenSourceHidumper::SetReDumpFlagTrue() +{ + ReDumpFlag_ = true; +} + +void DscreenSourceHidumper::ShowHelp(std::string &result) +{ + DHLOGI("Show help."); + result.append("Usage:dump [options]\n") + .append("Description:\n") + .append("-h ") + .append(": show help\n") + .append("--dump ") + .append(": dump source screen data in /data/data/dscreen\n") + .append("--redump ") + .append(": clear file and restart dump source screen data\n"); +} + +int32_t DscreenSourceHidumper::ShowIllegalInfomation(std::string &result) +{ + DHLOGI("Show illegal information."); + result.append("unknown command, -h for help."); + return DH_SUCCESS; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_service.cpp b/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_service.cpp index e924a45618bf2f5f9f3b71ea10c49632ca5388c8..a42d21a2690c3023ab3e47fe2b81a78fa603445d 100644 --- a/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_service.cpp +++ b/services/screenservice/sourceservice/dscreenservice/src/dscreen_source_service.cpp @@ -22,6 +22,7 @@ #include "string_ex.h" #include "system_ability_definition.h" +#include "dscreen_source_hidumper.h" #include "dscreen_constants.h" #include "dscreen_errcode.h" #include "dscreen_hisysevent.h" @@ -194,7 +195,22 @@ int32_t DScreenSourceService::Dump(int32_t fd, const std::vector DHLOGE("dprintf error"); return ERR_DH_SCREEN_SA_HIDUMPER_ERROR; } + std::string result; + std::vector argsStr; + std::transform(args.cbegin(), args.cend(), std::back_inserter(argsStr), + [](const std::u16string &item) { return Str16ToStr8(item); }); + + if (!DscreenSourceHidumper::GetInstance().Dump(argsStr, result)) { + DHLOGE("Hidump error"); + return ERR_DH_SCREEN_SA_HIDUMPER_ERROR; + } + + ret = dprintf(fd, "%s\n", result.c_str()); + if (ret < 0) { + DHLOGE("Dprintf error"); + return DSCREEN_BAD_VALUE; + } return ERR_OK; } } // namespace DistributedHardware