From 7879be93a7893f62b565029956b7119c7f08f68f Mon Sep 17 00:00:00 2001 From: gongguilin Date: Mon, 10 Feb 2025 15:02:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EFFRT=E8=B4=9F=E8=BD=BD?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=A1=8C=E9=9C=80=E6=B1=82=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: gongguilin --- .../include/if_local_ability_manager.h | 8 + .../include/local_ability_manager_proxy.h | 1 + .../include/safwk_ipc_interface_code.h | 1 + .../src/local_ability_manager_proxy.cpp | 42 +++ .../include/system_ability_manager_dumper.h | 24 +- .../source/system_ability_manager_dumper.cpp | 277 ++++++++++++++++-- .../samgrdumper_fuzzer/samgrdumper_fuzzer.cpp | 2 - 7 files changed, 330 insertions(+), 25 deletions(-) diff --git a/interfaces/innerkits/samgr_proxy/include/if_local_ability_manager.h b/interfaces/innerkits/samgr_proxy/include/if_local_ability_manager.h index 2f9dccfa..1a4f5332 100755 --- a/interfaces/innerkits/samgr_proxy/include/if_local_ability_manager.h +++ b/interfaces/innerkits/samgr_proxy/include/if_local_ability_manager.h @@ -33,6 +33,13 @@ enum { IPC_STAT_CMD_MAX = 3 }; +enum { + FFRT_STAT_CMD_START = 0, + FFRT_STAT_CMD_STOP = 1, + FFRT_STAT_CMD_GET = 2, + FFRT_STAT_CMD_MAX = 3 +}; + class SystemAbilityExtensionPara { public: SystemAbilityExtensionPara() @@ -66,6 +73,7 @@ public: const nlohmann::json& idleReason, int32_t& delayTime) = 0; virtual bool SendStrategyToSA(int32_t type, int32_t systemAbilityId, int32_t level, std::string& action) = 0; virtual bool IpcStatCmdProc(int32_t fd, int32_t cmd) = 0; + virtual bool FfrtStatCmdProc(int32_t fd, int32_t cmd) = 0; virtual bool FfrtDumperProc(std::string& result) = 0; virtual int32_t SystemAbilityExtProc(const std::string& extension, int32_t said, SystemAbilityExtensionPara* callback, bool isAsync = false) = 0; diff --git a/interfaces/innerkits/samgr_proxy/include/local_ability_manager_proxy.h b/interfaces/innerkits/samgr_proxy/include/local_ability_manager_proxy.h index 7fb3a630..f4f9d6b9 100755 --- a/interfaces/innerkits/samgr_proxy/include/local_ability_manager_proxy.h +++ b/interfaces/innerkits/samgr_proxy/include/local_ability_manager_proxy.h @@ -38,6 +38,7 @@ public: const nlohmann::json& idleReason, int32_t& delayTime); bool SendStrategyToSA(int32_t type, int32_t systemAbilityId, int32_t level, std::string& action); bool IpcStatCmdProc(int32_t fd, int32_t cmd); + bool FfrtStatCmdProc(int32_t fd, int32_t cmd); bool FfrtDumperProc(std::string& ffrtDumperInfo); int32_t SystemAbilityExtProc(const std::string& extension, int32_t said, SystemAbilityExtensionPara* callback, bool isAsync = false); diff --git a/interfaces/innerkits/samgr_proxy/include/safwk_ipc_interface_code.h b/interfaces/innerkits/samgr_proxy/include/safwk_ipc_interface_code.h index 708df087..8d3dff42 100755 --- a/interfaces/innerkits/samgr_proxy/include/safwk_ipc_interface_code.h +++ b/interfaces/innerkits/samgr_proxy/include/safwk_ipc_interface_code.h @@ -27,6 +27,7 @@ enum SafwkInterfaceCode : uint32_t { IPC_STAT_CMD_TRANSACTION = 6, FFRT_DUMPER_TRANSACTION = 7, SYSTEM_ABILITY_EXT_TRANSACTION = 8, + FFRT_STAT_CMD_TRANSACTION = 9, }; } #endif // !defined(SAFWK_IPC_INTERFACE_CODE_H) \ No newline at end of file diff --git a/services/lsamgr/src/local_ability_manager_proxy.cpp b/services/lsamgr/src/local_ability_manager_proxy.cpp index 8ae8dee6..efc62102 100644 --- a/services/lsamgr/src/local_ability_manager_proxy.cpp +++ b/services/lsamgr/src/local_ability_manager_proxy.cpp @@ -305,6 +305,48 @@ bool LocalAbilityManagerProxy::IpcStatCmdProc(int32_t fd, int32_t cmd) return result; } +bool LocalAbilityManagerProxy::FfrtStatCmdProc(int32_t fd, int32_t cmd) +{ + sptr iro = Remote(); + if (iro == nullptr) { + HILOG_ERROR(LOG_CORE, "FfrtStatCmdProc Remote null"); + return false; + } + + MessageParcel data; + if (!data.WriteInterfaceToken(LOCAL_ABILITY_MANAGER_INTERFACE_TOKEN)) { + HILOG_WARN(LOG_CORE, "FfrtStatCmdProc interface token check failed"); + return false; + } + + if (!data.WriteFileDescriptor(fd)) { + HILOG_WARN(LOG_CORE, "FfrtStatCmdProc write fd failed"); + return false; + } + + if (!data.WriteInt32(cmd)) { + HILOG_WARN(LOG_CORE, "FfrtStatCmdProc write cmd faild"); + return false; + } + + MessageParcel reply; + MessageOption option; + int32_t status = iro->SendRequest( + static_cast(SafwkInterfaceCode::FFRT_STAT_CMD_TRANSACTION), data, reply, option); + if (status != NO_ERROR) { + HILOG_ERROR(LOG_CORE, "FfrtStatCmdProc SendRequest failed, return value : %{public}d", status); + return false; + } + + bool result = false; + if (!reply.ReadBool(result)) { + HILOG_WARN(LOG_CORE, "FfrtStatCmdProc read bool faild"); + return false; + } + + return result; +} + bool LocalAbilityManagerProxy::FfrtDumperProc(std::string& ffrtDumperInfo) { sptr iro = Remote(); diff --git a/services/samgr/native/include/system_ability_manager_dumper.h b/services/samgr/native/include/system_ability_manager_dumper.h index 33295c48..333d8f94 100644 --- a/services/samgr/native/include/system_ability_manager_dumper.h +++ b/services/samgr/native/include/system_ability_manager_dumper.h @@ -21,6 +21,7 @@ #include "schedule/system_ability_state_scheduler.h" #include "system_ability_manager.h" +#include "if_local_ability_manager.h" namespace OHOS { enum { @@ -29,6 +30,11 @@ enum { IPC_STAT_CMD_INDEX = 2 }; +enum { + FFRT_STAT_PREFIX_INDEX = 0, + FFRT_STAT_PROCESS_INDEX = 1, + FFRT_STAT_CMD_INDEX = 2 +}; constexpr int32_t IPC_STAT_CMD_LEN = 3; class SystemAbilityManagerDumper { @@ -44,6 +50,13 @@ public: static bool FfrtDumpParser(std::vector& processIds, const std::string& processIdsStr); static int32_t FfrtDumpProc(std::shared_ptr abilityStateScheduler, int32_t fd, const std::vector& args); + static void GetFfrtLoadMetrics(std::shared_ptr abilityStateScheduler, + int32_t fd, const std::vector& args, std::string& result); + static bool FfrtStatCmdParser(int32_t& cmd, const std::vector& args); + static void CollectFfrtMetricInfoInProcs(int32_t fd, const std::vector& processIds, + std::shared_ptr abilityStateScheduler, int32_t cmd, std::string& result); + static sptr GetProcByProcessId( + std::shared_ptr abilityStateScheduler, int32_t processId); static bool GetFfrtDumpInfoProc(std::shared_ptr abilityStateScheduler, const std::vector& args, std::string& result); static int32_t ListenerDumpProc(std::map>& listeners, @@ -52,6 +65,13 @@ public: private: SystemAbilityManagerDumper() = default; ~SystemAbilityManagerDumper() = default; + static bool CollectFfrtStatistics(int32_t cmd, std::string& result); + static bool StartFfrtStatistics(std::string& result); + static bool StopFfrtStatistics(std::string& result); + static bool GetFfrtStatistics(std::string& result); + static void FfrtStatisticsParser(std::string& result); + static void ClearFfrtStatisticsBufferLocked(); + static void ClearFfrtStatistics(); static bool CanDump(); static void ShowHelp(std::string& result); static void ShowAllSystemAbilityInfo(std::shared_ptr abilityStateScheduler, @@ -63,7 +83,8 @@ private: static void ShowAllSystemAbilityInfoInState(const std::string& state, std::shared_ptr abilityStateScheduler, std::string& result); static void IllegalInput(std::string& result); - static void DumpFfrtInfoByProcName(int32_t processId, const std::u16string processName, std::string& result); + static void DumpFfrtInfoInProc( + std::shared_ptr abilityStateScheduler, int32_t pid, std::string& result); static int32_t SaveDumpResultToFd(int32_t fd, const std::string& result); static void GetSAMgrFfrtInfo(std::string& result); static void GetListenerDumpProc(std::map>& listeners, @@ -76,6 +97,7 @@ private: static void ShowSAByCallingPid(std::map>& listeners, int32_t pid, std::string& result); static void ShowListenerHelp(std::string& result); + static std::shared_ptr handler_; }; } // namespace OHOS #endif // SERVICES_SAMGR_NATIVE_INCLUDE_SYSTEM_ABILITY_MANAGER_DUMPER_H \ No newline at end of file diff --git a/services/samgr/native/source/system_ability_manager_dumper.cpp b/services/samgr/native/source/system_ability_manager_dumper.cpp index 1dfcd431..878dea0c 100644 --- a/services/samgr/native/source/system_ability_manager_dumper.cpp +++ b/services/samgr/native/source/system_ability_manager_dumper.cpp @@ -40,7 +40,18 @@ constexpr int32_t FFRT_DUMP_PROC_LEN = 2; constexpr int32_t FFRT_DUMP_PIDS_INDEX = 1; constexpr int FFRT_BUFFER_SIZE = 512 * 1024; constexpr int LISTENER_BASE_INDEX = 1; - +constexpr int32_t FFRT_METRIC_CMD_INDEX = 2; +constexpr int32_t FFRT_DUMP_METRIC_LEN = 3; +constexpr int32_t COLLECT_FFRT_METRIC_MAX_SIZE = 5000; +constexpr int32_t FFRT_STAT_SIZE = sizeof(ffrt_stat); +constexpr int32_t BUFFER_SIZE = FFRT_STAT_SIZE * COLLECT_FFRT_METRIC_MAX_SIZE; +char* g_ffrtMetricBuffer = nullptr; +bool g_collectEnable = false; +std::mutex ffrtMetricLock_; +constexpr int32_t DELAY_TIME = 60 * 1000; +constexpr const char* FFRT_STAT_STR_START = "--start-stat"; +constexpr const char* FFRT_STAT_STR_STOP = "--stop-stat"; +constexpr const char* FFRT_STAT_STR_GET = "--stat"; constexpr const char* IPC_STAT_STR_START = "--start-stat"; constexpr const char* IPC_STAT_STR_STOP = "--stop-stat"; constexpr const char* IPC_STAT_STR_GET = "--stat"; @@ -51,6 +62,8 @@ constexpr const char* IPC_DUMP_FAIL = " fail\n"; } +std::shared_ptr SystemAbilityManagerDumper::handler_ = nullptr; + void SystemAbilityManagerDumper::ShowListenerHelp(string& result) { result.append("SystemAbilityManager Listener Dump options:\n") @@ -256,21 +269,244 @@ int32_t SystemAbilityManagerDumper::FfrtDumpProc(std::shared_ptr abilityStateScheduler, - const std::vector& args, std::string& result) +void SystemAbilityManagerDumper::GetFfrtLoadMetrics(std::shared_ptr abilityStateScheduler, + int32_t fd, const std::vector& args, std::string& result) { - if (args.size() < FFRT_DUMP_PROC_LEN || args[FFRT_DUMP_PIDS_INDEX].empty()) { - HILOGE("FfrtDump param pid not exist"); + std::string pidStr = args[FFRT_DUMP_PIDS_INDEX]; + std::vector processIds; + FfrtDumpParser(processIds, pidStr); + if (processIds.empty()) { + HILOGE("FfrtDumpParser parse failed, illegal input processIdsStr %{public}s ", pidStr.c_str()); IllegalInput(result); + return; + } + int32_t cmd = -1; + if (!FfrtStatCmdParser(cmd, args)) { + IllegalInput(result); + return; + } + CollectFfrtMetricInfoInProcs(fd, processIds, abilityStateScheduler, cmd, result); +} + +bool SystemAbilityManagerDumper::FfrtStatCmdParser(int32_t& cmd, const std::vector& args) +{ + if (args[FFRT_METRIC_CMD_INDEX] == FFRT_STAT_STR_START) { + cmd = FFRT_STAT_CMD_START; + } else if (args[FFRT_METRIC_CMD_INDEX] == FFRT_STAT_STR_STOP) { + cmd = FFRT_STAT_CMD_STOP; + } else if (args[FFRT_METRIC_CMD_INDEX] == FFRT_STAT_STR_GET) { + cmd = FFRT_STAT_CMD_GET; + } else { + return false; + } + return true; +} + +void SystemAbilityManagerDumper::CollectFfrtMetricInfoInProcs(int32_t fd, const std::vector& processIds, + std::shared_ptr abilityStateScheduler, int32_t cmd, std::string& result) +{ + for (const int32_t pid : processIds) { + if (pid == getpid()) { + CollectFfrtStatistics(cmd, result); + continue; + } + sptr obj = GetProcByProcessId(abilityStateScheduler, pid); + if (obj == nullptr) { + HILOGE("CollectFfrtMetricInfoInProcs GetSystemProcess failed"); + result.append("process " + std::to_string(pid) + " not found!\n"); + continue; + } + obj->FfrtStatCmdProc(fd, cmd); + } +} +bool SystemAbilityManagerDumper::StartFfrtStatistics(std::string& result) +{ + if (g_collectEnable) { + result.append("collect has been started\n"); + return false; + } + ClearFfrtStatisticsBufferLocked(); + g_ffrtMetricBuffer = new char[BUFFER_SIZE](); + auto ret = ffrt_dump(ffrt_dump_cmd_t::DUMP_START_STAT, g_ffrtMetricBuffer, BUFFER_SIZE); + if (ret != ERR_OK) { + ClearFfrtStatisticsBufferLocked(); + result.append("collect start failed\n"); + return false; + } + g_collectEnable= true; + result.append("collect start success\n"); + if (handler_ == nullptr) { + handler_ = std::make_shared("ffrtDumpHandler"); + } + HILOGI("StartFfrtStatistics PostTask delayTime:%{public}dms", DELAY_TIME); + handler_->PostTask(ClearFfrtStatistics, "ClearFfrtStatistics", DELAY_TIME); + return true; +} + +bool SystemAbilityManagerDumper::StopFfrtStatistics(std::string& result) +{ + if (!g_collectEnable) { + result.append("collect has not been started\n"); + return false; + } + g_collectEnable= false; + auto ret = ffrt_dump(ffrt_dump_cmd_t::DUMP_STOP_STAT, g_ffrtMetricBuffer, BUFFER_SIZE); + if (ret != ERR_OK) { + ClearFfrtStatisticsBufferLocked(); + result.append("collect stop failed\n"); + return false; + } + result.append("collect stop success\n"); + return true; +} + +bool SystemAbilityManagerDumper::GetFfrtStatistics(std::string& result) +{ + if (g_collectEnable) { + result.append("collect has not been stopped\n"); return false; } + if (g_ffrtMetricBuffer == nullptr) { + result.append("info not collected\n"); + return false; + } + FfrtStatisticsParser(result); + ClearFfrtStatisticsBufferLocked(); + handler_ = nullptr; + return true; +} + +void SystemAbilityManagerDumper::FfrtStatisticsParser(std::string& result) +{ + ffrt_stat* currentStat = (ffrt_stat*)g_ffrtMetricBuffer; + char* lastStat = g_ffrtMetricBuffer + BUFFER_SIZE; + std::string taskInfo; + uint64_t maxTime = 0; + uint64_t minTime = std::numeric_limits::max(); + uint64_t sumTime = 0; + uint64_t avgTime = 0; + int count = 0; + while ((char*)currentStat < lastStat && std::strcmp(currentStat->taskName, "") != 0) { + if (currentStat->startTime > currentStat->endTime) { + currentStat = (ffrt_stat*)((char*)currentStat + FFRT_STAT_SIZE); + continue; + } + auto duration = currentStat->endTime - currentStat->startTime; + sumTime += duration; + maxTime = std::max(maxTime, duration); + minTime = std::min(minTime, duration); + ++count; + taskInfo.append(currentStat->taskName); + taskInfo.append(" " + ToString(currentStat->startTime)); + taskInfo.append(" " + ToString(currentStat->endTime) + "\n"); + currentStat = (ffrt_stat*)((char*)currentStat + FFRT_STAT_SIZE); + } + if (count == 0) { + minTime = 0; + } else { + avgTime = sumTime / count; + } + result.append("sumTime:" + ToString(sumTime) + " maxTime:" + ToString(maxTime)); + result.append(" minTime:" + ToString(minTime) + " avgTime:" + ToString(avgTime)); + result.append(" cntTime:" + ToString(count) + "\n"); + result.append("-------------------------------------------------------------------------------------------\n"); + result.append("taskName startTime(us) endTime(us)\n"); + result.append("-------------------------------------------------------------------------------------------\n"); + result.append(taskInfo); + result.append("-------------------------------------------------------------------------------------------\n"); +} + +void SystemAbilityManagerDumper::ClearFfrtStatisticsBufferLocked() +{ + if (g_ffrtMetricBuffer != nullptr) { + delete[] g_ffrtMetricBuffer; + g_ffrtMetricBuffer = nullptr; + HILOGI("ClearFfrtStatisticsBuffer success"); + } + if (handler_ != nullptr) { + handler_->RemoveTask("ClearFfrtStatistics"); + } +} + +void SystemAbilityManagerDumper::ClearFfrtStatistics() +{ + HILOGW("ClearFfrtStatistics start"); + std::lock_guard autoLock(ffrtMetricLock_); + if (g_collectEnable) { + auto ret = ffrt_dump(ffrt_dump_cmd_t::DUMP_STOP_STAT, g_ffrtMetricBuffer, BUFFER_SIZE); + if (ret != ERR_OK) { + HILOGE("ClearFfrtStatistics stop ffrt_dump err:%{public}d", ret); + } + g_collectEnable= false; + } + ClearFfrtStatisticsBufferLocked(); +} + +bool SystemAbilityManagerDumper::CollectFfrtStatistics(int32_t cmd, std::string& result) +{ + std::lock_guard autoLock(ffrtMetricLock_); + result.append("pid:" + ToString(getpid()) + " "); + auto ret = false; + switch (cmd) { + case FFRT_STAT_CMD_START: { + ret = StartFfrtStatistics(result); + break; + } + case FFRT_STAT_CMD_STOP: { + ret = StopFfrtStatistics(result); + break; + } + case FFRT_STAT_CMD_GET: { + ret = GetFfrtStatistics(result); + break; + } + default: + break; + } + return ret; +} + +sptr SystemAbilityManagerDumper::GetProcByProcessId( + std::shared_ptr abilityStateScheduler, int32_t processId) +{ + std::u16string processName; + int32_t queryResult = abilityStateScheduler->GetProcessNameByProcessId(processId, processName); + if (queryResult != ERR_OK) { + HILOGE("GetProcessNameByProcessId failed, pid %{public}d not exist", processId); + return nullptr; + } + sptr obj = + iface_cast(SystemAbilityManager::GetInstance()->GetSystemProcess(processName)); + if (obj == nullptr) { + HILOGE("GetSystemProcess failed, pid:%{public}d processName:%{public}s not exist", + processId, Str16ToStr8(processName).c_str()); + } + return obj; +} + +bool SystemAbilityManagerDumper::GetFfrtDumpInfoProc(std::shared_ptr abilityStateScheduler, + const std::vector& args, std::string& result) +{ std::string pidStr = args[FFRT_DUMP_PIDS_INDEX]; std::vector processIds; - SystemAbilityManagerDumper::FfrtDumpParser(processIds, pidStr); + FfrtDumpParser(processIds, pidStr); if (processIds.empty()) { HILOGE("FfrtDumpParser parse failed, illegal input processIdsStr %{public}s ", pidStr.c_str()); IllegalInput(result); @@ -282,14 +518,7 @@ bool SystemAbilityManagerDumper::GetFfrtDumpInfoProc(std::shared_ptrGetProcessNameByProcessId(pid, processName); - if (queryResult != ERR_OK) { - HILOGE("GetProcessNameByProcessId failed, pid %{public}d not exist", pid); - result.append("process " + std::to_string(pid) + " not found!\n"); - continue; - } - DumpFfrtInfoByProcName(pid, processName, result); + DumpFfrtInfoInProc(abilityStateScheduler, pid, result); } return true; } @@ -329,14 +558,12 @@ void SystemAbilityManagerDumper::GetSAMgrFfrtInfo(std::string& result) delete[] buffer; } -void SystemAbilityManagerDumper::DumpFfrtInfoByProcName(int32_t pid, const std::u16string processName, - std::string& result) +void SystemAbilityManagerDumper::DumpFfrtInfoInProc( + std::shared_ptr abilityStateScheduler, int32_t pid, std::string& result) { - sptr obj = - iface_cast(SystemAbilityManager::GetInstance()->GetSystemProcess(processName)); + sptr obj = GetProcByProcessId(abilityStateScheduler, pid); if (obj == nullptr) { - HILOGE("GetSystemProcess failed, pid:%{public}d processName:%{public}s not exist", - pid, Str16ToStr8(processName).c_str()); + HILOGE("DumpFfrtInfoInProc GetSystemProcess failed"); result.append("process " + std::to_string(pid) + " not found!\n"); return; } @@ -517,7 +744,13 @@ void SystemAbilityManagerDumper::ShowHelp(std::string& result) .append(" -sa said: query sa state infos.\n") .append(" -p processname: query process state infos.\n") .append(" -sm state: query all sa based on state infos.\n") - .append(" -l: query all sa state infos.\n"); + .append(" -l: query all sa state infos.\n") + .append(" --listener -h: help text for listener.\n") + .append(" --ffrt [pid1|pid2] --start-stat/--stop-stat/--stat: start/stop/get") + .append(" the FFRT load statistics of a process.\n") + .append(" --ffrt [pid1|pid2]: query the FFRT dump infos of a process.\n") + .append(" --ipc procname/all --start-stat/--stop-stat/--stat: start/stop/get") + .append(" the IPC load statistics of a process.\n"); } void SystemAbilityManagerDumper::ShowAllSystemAbilityInfo( diff --git a/test/fuzztest/samgrdumper_fuzzer/samgrdumper_fuzzer.cpp b/test/fuzztest/samgrdumper_fuzzer/samgrdumper_fuzzer.cpp index 6f20faca..8e86b84b 100644 --- a/test/fuzztest/samgrdumper_fuzzer/samgrdumper_fuzzer.cpp +++ b/test/fuzztest/samgrdumper_fuzzer/samgrdumper_fuzzer.cpp @@ -92,8 +92,6 @@ void SamgrDumperFuzzTest(const uint8_t* data, size_t size) SystemAbilityManagerDumper::StartSamgrIpcStatistics(result); SystemAbilityManagerDumper::GetFfrtDumpInfoProc(scheduler, args, result); SystemAbilityManagerDumper::GetSAMgrFfrtInfo(result); - int32_t pid = BuildInt32FromData(data, size); - SystemAbilityManagerDumper::DumpFfrtInfoByProcName(pid, Str8ToStr16(processName), result); std::shared_ptr manager = std::make_shared(); manager->abilityStateScheduler_ = std::make_shared(); -- Gitee