From 6dfcfada689a2da25bb46d962c7d0141b3f5ab40 Mon Sep 17 00:00:00 2001 From: frank-huangran Date: Fri, 1 Aug 2025 15:38:39 +0800 Subject: [PATCH] add smartperf collector src Signed-off-by: frank-huangran --- .../colltector/src/AI_schedule.cpp | 56 +++++ .../device_command/colltector/src/ByTrace.cpp | 94 ++++++++ .../device_command/colltector/src/CPU.cpp | 211 ++++++++++++++++++ .../device_command/colltector/src/Capture.cpp | 195 ++++++++++++++++ 4 files changed, 556 insertions(+) create mode 100644 smartperf_device/device_command/colltector/src/AI_schedule.cpp create mode 100644 smartperf_device/device_command/colltector/src/ByTrace.cpp create mode 100644 smartperf_device/device_command/colltector/src/CPU.cpp create mode 100644 smartperf_device/device_command/colltector/src/Capture.cpp diff --git a/smartperf_device/device_command/colltector/src/AI_schedule.cpp b/smartperf_device/device_command/colltector/src/AI_schedule.cpp new file mode 100644 index 000000000..92bfee3de --- /dev/null +++ b/smartperf_device/device_command/colltector/src/AI_schedule.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025 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 "AI_schedule.h" +#include "interface/GameServicePlugin.h" +#include +#include +#include +#include +#include + + +namespace OHOS { +namespace SmartPerf { +std::map AISchedule::ItemData() +{ + if (processId.empty()) { + WLOGE("AISchedule need processId."); + return std::map(); + } + aiScheduleParams[aiScheduleParamPid] = processId; + aiScheduleParams[aiScheduleParamType] = "1"; + ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); + + void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); + if (handle == nullptr) { + WLOGE("Get service plugin handler failed."); + return std::map(); + } + + typedef GameServicePlugin *(*GetServicePlugin)(); + GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); + if (!servicePlugin) { + WLOGE("GameServicePlugin Error loading symbol"); + return std::map(); + } + return servicePlugin()->GetSystemFunctionStatus(aiScheduleParams); +} + +void AISchedule::SetProcessId(const std::string &pid) +{ + processId = pid; +} +} // namespace SmartPerf +} // namespace OHOS \ No newline at end of file diff --git a/smartperf_device/device_command/colltector/src/ByTrace.cpp b/smartperf_device/device_command/colltector/src/ByTrace.cpp new file mode 100644 index 000000000..daf59a860 --- /dev/null +++ b/smartperf_device/device_command/colltector/src/ByTrace.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 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 +#include +#include +#include "unistd.h" +#include "include/sp_utils.h" +#include "include/ByTrace.h" +#include "include/sp_log.h" +#include "include/common.h" +namespace OHOS { +namespace SmartPerf { +void ByTrace::SetTraceConfig(int mSum, int mInterval, long long mThreshold, int mLowfps, int mCurNum) const +{ + sum = mSum; + interval = mInterval; + threshold = mThreshold; + lowfps = mLowfps; + curNum = mCurNum; + LOGD("ByTrace::SetTraceConfig mSum(%d) mInterval(%d) mThreshold(%lld) mLowfps(%d) mCurNum(%d)", + mSum, mInterval, mThreshold, mLowfps, mCurNum); +} +void ByTrace::ThreadGetTrace() const +{ + std::string result; + std::string cmdString; + if (SPUtils::IsHmKernel()) { + cmdString = CMD_COMMAND_MAP.at(CmdCommand::HITRACE_1024); + } else { + cmdString = CMD_COMMAND_MAP.at(CmdCommand::HITRACE_2048); + } + std::string time = std::to_string(SPUtils::GetCurTime()); + std::string traceFile = "/data/local/tmp/sptrace_" + time + ".ftrace"; + std::string traceCmdExe = cmdString + traceFile; + SPUtils::LoadCmd(traceCmdExe, result); + LOGD("TRACE threadGetTrace CMD(%s)", traceCmdExe.c_str()); +} +TraceStatus ByTrace::CheckFpsJitters(std::vector& jitters, int cfps) const +{ + times++; + int two = 2; + long long curTime = SPUtils::GetCurTime(); + LOGD("Bytrace get curTime : %lld", curTime); + if (curNum <= sum && currentTrigger < 0 && times > two) { + for (const long long& jitter : jitters) { + long long normalJitter = jitter / 1e6; + if (normalJitter > threshold || cfps < lowfps) { + TriggerCatch(curTime); + } + } + } + if ((curTime - lastTriggerTime) / 1e3 > interval && currentTrigger == 1) { + currentTrigger = -1; + } + return TraceStatus::TRACE_FINISH; +} +void ByTrace::TriggerCatch(long long curTime) const +{ + if ((curTime - lastTriggerTime) / 1e3 > interval && !CheckHitraceId()) { + std::thread tStart([this] { this->ThreadGetTrace(); }); + currentTrigger = 1; + lastTriggerTime = curTime; + curNum++; + tStart.detach(); + } +} + +bool ByTrace::CheckHitraceId() const +{ + std::string result; + std::string hitrace = CMD_COMMAND_MAP.at(CmdCommand::HITRACE_CMD); + SPUtils::LoadCmd(hitrace, result); + if (result.empty()) { + return false; + } + if (result.find("-t") != std::string::npos) { + return true; + } + return false; +} +} +} diff --git a/smartperf_device/device_command/colltector/src/CPU.cpp b/smartperf_device/device_command/colltector/src/CPU.cpp new file mode 100644 index 000000000..b05dd8ea9 --- /dev/null +++ b/smartperf_device/device_command/colltector/src/CPU.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2021 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 "include/CPU.h" +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "include/sp_utils.h" +#include "cpu_collector.h" +#include "collect_result.h" +#include "include/startup_delay.h" +#include "include/sp_log.h" + +using namespace OHOS::HiviewDFX; +using namespace OHOS::HiviewDFX::UCollectUtil; +using namespace OHOS::HiviewDFX::UCollect; + +namespace OHOS { +namespace SmartPerf { +std::map CPU::ItemData() +{ + usleep(twenty * thousand); + std::map result; + std::vector cpuFreqInfo = GetCpuFreq(); + for (size_t i = 0; i < cpuFreqInfo.size(); i++) { + std::string cpuFreqStr = std::to_string(cpuFreqInfo[i].curFreq); + std::string cpuId = std::to_string(cpuFreqInfo[i].cpuId); + result["cpu" + cpuId + "Frequency"] = cpuFreqStr; + } + std::vector workLoads = GetCpuUsage(); + const size_t oneHundred = 100; + if (workLoads.empty()) { + return result; + } + for (size_t i = 0; i < workLoads.size(); i++) { + std::string cpuIdStr = workLoads[i].cpuId; + std::string userUsageStr = std::to_string(workLoads[i].userUsage * oneHundred); + std::string niceUsageStr = std::to_string(workLoads[i].niceUsage * oneHundred); + std::string systemUsageStr = std::to_string(workLoads[i].systemUsage * oneHundred); + std::string idleUsageStr = std::to_string(workLoads[i].idleUsage * oneHundred); + std::string ioWaitUsageStr = std::to_string(workLoads[i].ioWaitUsage * oneHundred); + std::string irqUsageStr = std::to_string(workLoads[i].irqUsage * oneHundred); + std::string softIrqUsageStr = std::to_string(workLoads[i].softIrqUsage * oneHundred); + std::string totalUsageStr = std::to_string((workLoads[i].userUsage + workLoads[i].niceUsage + + workLoads[i].systemUsage + workLoads[i].ioWaitUsage + workLoads[i].irqUsage + workLoads[i].softIrqUsage) * + oneHundred); + if (cpuIdStr == cpustr) { + cpuIdStr = totalcpu; + } + result[cpuIdStr + "userUsage"] = userUsageStr; + result[cpuIdStr + "niceUsage"] = niceUsageStr; + result[cpuIdStr + "systemUsage"] = systemUsageStr; + result[cpuIdStr + "idleUsage"] = idleUsageStr; + result[cpuIdStr + "ioWaitUsage"] = ioWaitUsageStr; + result[cpuIdStr + "irqUsage"] = irqUsageStr; + result[cpuIdStr + "softIrqUsage"] = softIrqUsageStr; + result[cpuIdStr + "Usage"] = totalUsageStr; + } + if ((!packageName.empty() || !processId.empty())) { + std::map processCpuInfo = CPU::GetSysProcessCpuLoad(); + if (!processCpuInfo.empty()) { + for (const auto& item : processCpuInfo) { + result.insert(item); + } + } + } + LOGI("CPU:ItemData map size(%u)", result.size()); + return result; +} + +void CPU::SetPackageName(const std::string &pName) +{ + packageName = pName; + LOGD("CPU SetPackageName name(%s)", pName.c_str()); +} + +void CPU::SetProcessId(const std::string &pid) +{ + LOGD("CPU SetProcessId (%s)", pid.c_str()); + processId.clear(); + SPUtils::StrSplit(pid, " ", processId); +} + +std::vector CPU::GetCpuFreq() +{ + OHOS::SmartPerf::CpuFreqs cpuFreqs; + std::vector cpuFrequency; + std::shared_ptr collector = CpuCollector::Create(); + CollectResult> result = collector->CollectCpuFrequency(); + std::vector &cpufreq = result.data; + for (size_t i = 0; i < cpufreq.size(); i++) { + cpuFreqs.cpuId = cpufreq[i].cpuId; + cpuFreqs.curFreq = cpufreq[i].curFreq; + cpuFrequency.push_back(cpuFreqs); + } + return cpuFrequency; +} + +std::vector CPU::GetCpuUsage() +{ + OHOS::SmartPerf::CpuUsageInfos cpuUsageInfos; + std::vector workload; + std::shared_ptr collector = CpuCollector::Create(); + CollectResult result = collector->CollectSysCpuUsage(true); + SysCpuUsage &sysCpuUsage = result.data; + if (sysCpuUsage.cpuInfos.empty()) { + return workload; + } + for (auto &cpuInfo : sysCpuUsage.cpuInfos) { + cpuUsageInfos.cpuId = cpuInfo.cpuId; + cpuUsageInfos.userUsage = cpuInfo.userUsage; + cpuUsageInfos.niceUsage = cpuInfo.niceUsage; + cpuUsageInfos.systemUsage = cpuInfo.systemUsage; + cpuUsageInfos.idleUsage = cpuInfo.idleUsage; + cpuUsageInfos.ioWaitUsage = cpuInfo.ioWaitUsage; + cpuUsageInfos.irqUsage = cpuInfo.irqUsage; + cpuUsageInfos.softIrqUsage = cpuInfo.softIrqUsage; + workload.push_back(cpuUsageInfos); + } + return workload; +} + +std::map CPU::GetSysProcessCpuLoad() const +{ + std::map processCpuInfo; + const size_t oneHundred = 100; + if (!processId.empty()) { + std::shared_ptr collector = CpuCollector::Create(); + for (size_t i = 0; i < processId.size(); i++) { + int32_t procId = SPUtilesTye::StringToSometype(processId[i]); + auto collectResult = collector->CollectProcessCpuStatInfo(procId, true); + auto data = collectResult.data; + if (i == 0) { + processCpuInfo["ProcId"] = std::to_string(data.pid); + processCpuInfo["ProcAppName"] = data.procName; + processCpuInfo["ProcCpuLoad"] = std::to_string(data.cpuLoad * oneHundred); + processCpuInfo["ProcCpuUsage"] = std::to_string(data.cpuUsage * oneHundred); + processCpuInfo["ProcUCpuUsage"] = std::to_string(data.uCpuUsage * oneHundred); + processCpuInfo["ProcSCpuUsage"] = std::to_string(data.sCpuUsage * oneHundred); + GetSysChildProcessCpuLoad(processId.size(), processCpuInfo); + } else { + processCpuInfo["ChildProcId"].append(std::to_string(data.pid)).append("|"); + processCpuInfo["ChildProcCpuLoad"].append(std::to_string(data.cpuLoad * oneHundred)).append("|"); + processCpuInfo["ChildProcCpuUsage"].append(std::to_string(data.cpuUsage * oneHundred)).append("|"); + processCpuInfo["ChildProcUCpuUsage"].append(std::to_string(data.uCpuUsage * oneHundred)).append("|"); + processCpuInfo["ChildProcSCpuUsage"].append(std::to_string(data.sCpuUsage * oneHundred)).append("|"); + } + } + } else { + processCpuInfo["ProcId"] = "NA"; + processCpuInfo["ProcAppName"] = packageName; + processCpuInfo["ProcCpuLoad"] = "NA"; + processCpuInfo["ProcCpuUsage"] = "NA"; + processCpuInfo["ProcUCpuUsage"] = "NA"; + processCpuInfo["ProcSCpuUsage"] = "NA"; + processCpuInfo["ChildProcId"] = "NA"; + processCpuInfo["ChildProcCpuLoad"] = "NA"; + processCpuInfo["ChildProcCpuUsage"] = "NA"; + processCpuInfo["ChildProcUCpuUsage"] = "NA"; + processCpuInfo["ChildProcSCpuUsage"] = "NA"; + } + GetSysProcessCpuLoadContinue(processCpuInfo); + return processCpuInfo; +} + +void CPU::GetSysProcessCpuLoadContinue(std::map &processCpuInfo) const +{ + if (processCpuInfo.find("ProcAppName") != processCpuInfo.end() && processCpuInfo["ProcAppName"].empty()) { + processCpuInfo["ProcId"] = "0"; + processCpuInfo["ProcAppName"] = packageName; + processCpuInfo["ProcCpuLoad"] = "0"; + processCpuInfo["ProcCpuUsage"] = "0"; + processCpuInfo["ProcUCpuUsage"] = "0"; + processCpuInfo["ProcSCpuUsage"] = "0"; + processCpuInfo["ChildProcId"] = "0"; + processCpuInfo["ChildProcCpuLoad"] = "0"; + processCpuInfo["ChildProcCpuUsage"] = "0"; + processCpuInfo["ChildProcUCpuUsage"] = "0"; + processCpuInfo["ChildProcSCpuUsage"] = "0"; + } +} + +void CPU::GetSysChildProcessCpuLoad(size_t processIdSize, std::map &processCpuInfo) const +{ + if (processIdSize == 1) { + processCpuInfo["ChildProcId"] = "NA"; + processCpuInfo["ChildProcCpuLoad"] = "NA"; + processCpuInfo["ChildProcCpuUsage"] = "NA"; + processCpuInfo["ChildProcUCpuUsage"] = "NA"; + processCpuInfo["ChildProcSCpuUsage"] = "NA"; + } +} +} +} diff --git a/smartperf_device/device_command/colltector/src/Capture.cpp b/smartperf_device/device_command/colltector/src/Capture.cpp new file mode 100644 index 000000000..e4090aa53 --- /dev/null +++ b/smartperf_device/device_command/colltector/src/Capture.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2021 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 +#include +#include +#include +#include +#include +#include "include/sp_utils.h" +#include "include/Capture.h" +#include "include/sp_log.h" +#include "display_manager.h" +#include "wm_common.h" +#include "png.h" +#include +#include "include/common.h" +namespace OHOS { +namespace SmartPerf { +using namespace OHOS::Media; +using namespace OHOS::Rosen; +std::map Capture::ItemData() +{ + std::map result; + const int two = 2; + const int modResult = callNum % two; + callNum++; + curTime = GetCurTimes(); + std::string screenCapPath = "data/local/tmp/capture/screenCap_" + std::to_string(curTime); + std::string path = "NA"; + if (isSocketMessage) { + if (modResult == 0) { + path = screenCapPath + ".jpeg"; + result["capture"] = path; + TriggerGetCatchSocket(); + } + } else { + if (modResult == 0) { + path = screenCapPath + ".png"; + result["capture"] = path; + TriggerGetCatch(); + } + } + result["capture"] = path; + LOGI("Capture:ItemData map size(%u)", result.size()); + return result; +} + +long long Capture::GetCurTimes() +{ + return SPUtils::GetCurTime(); +} + +void Capture::SocketMessage() +{ + isSocketMessage = true; +} +void Capture::ThreadGetCatch() +{ + const std::string captureDir = "/data/local/tmp/capture"; + const std::string savePath = captureDir + "/screenCap_" + std::to_string(curTime) + ".png"; + std::string cmdResult; + if (!SPUtils::FileAccess(captureDir)) { + std::string capturePath = CMD_COMMAND_MAP.at(CmdCommand::CREAT_DIR) + captureDir; + if (!SPUtils::LoadCmd(capturePath, cmdResult)) { + LOGE("%s capture not be created!", captureDir.c_str()); + return; + } else { + LOGD("%s created successfully!", captureDir.c_str()); + } + }; + std::ostringstream errorRecv; + auto fd = open(savePath.c_str(), O_RDWR | O_CREAT, 0666); + if (fd == -1) { + LOGE("Failed to open file: %s", savePath.c_str()); + return; + } + if (!TakeScreenCap(savePath)) { + LOGE("Screen Capture Failed!"); + close(fd); + return; + } + close(fd); +} + + +void Capture::ThreadGetCatchSocket() +{ + std::string captureTime = std::to_string(curTime); + std::string captureDir = "/data/local/tmp/capture"; + std::string savePath = captureDir + "/screenCap_" + captureTime + ".jpeg"; + std::string cmdResult; + if (!SPUtils::FileAccess(captureDir)) { + std::string capturePath = CMD_COMMAND_MAP.at(CmdCommand::CREAT_DIR) + captureDir; + if (!SPUtils::LoadCmd(capturePath, cmdResult)) { + LOGE("%s capture not be created!", captureDir.c_str()); + return; + } else { + LOGD("%s created successfully!", captureDir.c_str()); + } + }; + + auto fd = open(savePath.c_str(), O_RDWR | O_CREAT, 0644); + if (fd == -1) { + LOGE("Capture::ThreadGetCatchSocket Failed to open file"); + return; + } + std::string snapshot = CMD_COMMAND_MAP.at(CmdCommand::SNAPSHOT); + if (!SPUtils::LoadCmd(snapshot + savePath, cmdResult)) { + LOGE("snapshot_display command failed!"); + close(fd); + return; + } + close(fd); +} + +void Capture::TriggerGetCatch() +{ + std::thread([this]() { + this->ThreadGetCatch(); + }).detach(); +} + +void Capture::TriggerGetCatchSocket() +{ + std::thread([this]() { + this->ThreadGetCatchSocket(); + }).detach(); +} + +bool Capture::TakeScreenCap(const std::string &savePath) const +{ + Rosen::DisplayManager &displayMgr = Rosen::DisplayManager::GetInstance(); + std::shared_ptr pixelMap = displayMgr.GetScreenshot(displayMgr.GetDefaultDisplayId()); + static constexpr int bitmapDepth = 8; + if (pixelMap == nullptr) { + LOGE("Failed to get display pixelMap"); + return false; + } + auto width = static_cast(pixelMap->GetWidth()); + auto height = static_cast(pixelMap->GetHeight()); + auto data = pixelMap->GetPixels(); + auto stride = static_cast(pixelMap->GetRowBytes()); + png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (pngStruct == nullptr) { + LOGE("png_create_write_struct nullptr!"); + return false; + } + png_infop pngInfo = png_create_info_struct(pngStruct); + if (pngInfo == nullptr) { + LOGE("png_create_info_struct error nullptr!"); + png_destroy_write_struct(&pngStruct, nullptr); + return false; + } + char realPath[PATH_MAX] = {0x00}; + if (realpath(savePath.c_str(), realPath) == nullptr) { + std::cout << "" << std::endl; + } + FILE *fp = fopen(realPath, "wb"); + if (fp == nullptr) { + LOGE("open file error!"); + png_destroy_write_struct(&pngStruct, &pngInfo); + return false; + } + png_init_io(pngStruct, fp); + png_set_IHDR(pngStruct, pngInfo, width, height, bitmapDepth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_packing(pngStruct); // set packing info + png_write_info(pngStruct, pngInfo); // write to header + for (uint32_t i = 0; i < height; i++) { + png_write_row(pngStruct, data + (i * stride)); + } + png_write_end(pngStruct, pngInfo); + // free + png_destroy_write_struct(&pngStruct, &pngInfo); + (void)fclose(fp); + return true; +} +void Capture::SetCollectionNum() +{ + callNum = 0; +} +} +} -- Gitee