* 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 "appfreeze_cpu_freq_manager.h"
#include <fcntl.h>
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <cstdint>
#include <dlfcn.h>
#include <cstdio>
#include <unistd.h>
#include <cerrno>
#include "file_ex.h"
#include "directory_ex.h"
#include "string_ex.h"
#include "hilog_tag_wrapper.h"
#include "time_util.h"
#include "dfx_define.h"
#include "appfreeze_util.h"
#include "cpu_sys_config.h"
namespace OHOS {
namespace AppExecFwk {
namespace {
constexpr int64_t DEFAULT_CLOCK_TICKS = 100;
constexpr int64_t HZ_TO_MHZ = 1000;
constexpr size_t CPU_FREQ_AND_TIME_NUM = 5;
constexpr int CPU_FREQ_DECIMAL_BASE = 10;
constexpr float CPU_PERCENTAGE = 100.0f;
constexpr uint32_t TIME_IN_STATE_FIRST_INDEX = 0;
constexpr uint32_t TIME_IN_STATE_SECOND_INDEX = 1;
constexpr uint32_t START_TIME_FIRST_INDEX = 13;
constexpr uint32_t START_TIME_SECOND_INDEX = 14;
constexpr const char* const LOG_FILE_HEAD = "Generated by HiviewDFX @OpenHarmony";
constexpr const char* const LOG_FILE_SEP = "===============================================================";
constexpr const char* const LIB_THREAD_CPU_LOAD_PATH = "libucollection_utility.z.so";
constexpr uint32_t DEFAULT_CPU_SIZE = 1;
constexpr const char* const CPU_INFO_PREFIX = "cpu-info-";
constexpr double INVALID_DMIPS = -1.0;
}
ffrt::mutex AppfreezeCpuFreqManager::freezeInfoMutex_;
int AppfreezeCpuFreqManager::cpuCount_ = 0;
std::map<std::string, CpuDataProcessor> AppfreezeCpuFreqManager::cpuInfoMap_;
AppfreezeCpuFreqManager::AppfreezeCpuFreqManager()
{
cpuCount_ = AppfreezeUtil::GetCpuCount();
}
AppfreezeCpuFreqManager::~AppfreezeCpuFreqManager()
{
}
AppfreezeCpuFreqManager &AppfreezeCpuFreqManager::GetInstance()
{
static AppfreezeCpuFreqManager instance;
return instance;
}
bool AppfreezeCpuFreqManager::RemoveOldInfo()
{
if (cpuInfoMap_.size() < AppfreezeUtil::MAX_MAP_SIZE) {
return true;
}
int removeCount = 0;
uint64_t curTime = AppfreezeUtil::GetMilliseconds();
for (auto it = cpuInfoMap_.begin(); it != cpuInfoMap_.end();) {
auto interval = curTime - it->second.GetCpuConsumeTime().cpuFaultTime;
if (interval > AppfreezeUtil::TIME_LIMIT || interval < 0) {
it = cpuInfoMap_.erase(it);
removeCount++;
} else {
++it;
}
}
TAG_LOGI(AAFwkTag::APPDFR, "remove old tasks count: %{public}d, "
"current tasks count: %{public}zu", removeCount, cpuInfoMap_.size());
return removeCount != 0;
}
bool AppfreezeCpuFreqManager::InsertCpuDetailInfo(const std::string &type, int32_t pid)
{
std::lock_guard<ffrt::mutex> lock(freezeInfoMutex_);
auto it = cpuInfoMap_.find(type);
if (it == cpuInfoMap_.end() && !RemoveOldInfo()) {
return false;
}
cpuInfoMap_[type] = std::move(GetCpuDetailInfo(pid));
return true;
}
CpuDataProcessor AppfreezeCpuFreqManager::GetCpuDetailInfo(int32_t pid)
{
std::vector<std::vector<CpuFreqData>> cpuDetailInfo{};
std::vector<TotalTime> totalTimeCpuLists{};
for (int32_t i = 0; i < cpuCount_; ++i) {
std::vector<CpuFreqData> datas{};
TotalTime totalCpuTime{};
if (GetInfoByCpuCount(i, datas, totalCpuTime)) {
cpuDetailInfo.push_back(datas);
totalTimeCpuLists.push_back(totalCpuTime);
}
}
CpuConsumeTime cpuConsumeTime = {
.cpuFaultTime = AppfreezeUtil::GetMilliseconds(),
.processCpuTime = GetProcessCpuTime(pid),
.deviceRunTime = GetDeviceRuntime(),
.cpuTime = GetAppCpuTime(pid),
.optimalCpuTime = GetOptimalCpuTime(pid),
};
CpuDataProcessor data(cpuDetailInfo, totalTimeCpuLists, cpuConsumeTime, pid);
return data;
}
bool AppfreezeCpuFreqManager::GetInfoByCpuCount(int32_t cpu, std::vector<CpuFreqData>& parseDatas,
TotalTime& totalTime)
{
std::string cpuFreqFile = CpuSysConfig::GetFreqTimePath(cpu);
std::string realPath = AppfreezeUtil::FreezePathToRealPath(cpuFreqFile);
std::ifstream fin(realPath);
if (!fin.is_open()) {
TAG_LOGE(AAFwkTag::APPDFR, "Read cpu time failed, cpuFreqFile:%{public}s, errno:%{public}d",
cpuFreqFile.c_str(), errno);
return false;
}
std::string line;
while (getline(fin, line)) {
if (line.empty()) {
continue;
}
std::vector<std::string> tokens;
SplitStr(line, " ", tokens);
if (tokens.size() != CPU_FREQ_AND_TIME_NUM) {
continue;
}
CpuFreqData cpuFreqData{};
cpuFreqData.frequency = static_cast<uint64_t>(strtoull(tokens[TIME_IN_STATE_FIRST_INDEX].c_str(),
nullptr, CPU_FREQ_DECIMAL_BASE));
cpuFreqData.runningTime = static_cast<uint64_t>(strtoull(tokens[TIME_IN_STATE_SECOND_INDEX].c_str(),
nullptr, CPU_FREQ_DECIMAL_BASE));
totalTime.totalRunningTime += cpuFreqData.runningTime;
for (size_t i = 1; i < tokens.size(); ++i) {
totalTime.totalCpuTime += static_cast<uint64_t>(strtoull(tokens[i].c_str(), nullptr,
CPU_FREQ_DECIMAL_BASE));
}
parseDatas.push_back(cpuFreqData);
}
return true;
}
std::string AppfreezeCpuFreqManager::GetCpuStr(int code, std::vector<FrequencyPair>& freqPairs,
float percentage)
{
std::sort(freqPairs.begin(), freqPairs.end(),
[] (const auto& pairOne, const auto& pairTwo) { return pairOne.percentage > pairTwo.percentage; });
std::stringstream ss;
ss << "cpu" << std::to_string(code) << " Usage " << AppfreezeUtil::RoundToTwoDecimals(percentage) << "%, ";
bool isEnd = true;
for (const auto& pair : freqPairs) {
if (!isEnd) {
ss << ", ";
}
isEnd = false;
ss << pair.frequency << "MHZ " << AppfreezeUtil::RoundToTwoDecimals(pair.percentage) << "%";
}
ss << std::endl;
return ss.str();
}
bool AppfreezeCpuFreqManager::GetCpuTotalValue(size_t i, const std::vector<TotalTime>& totalTimeList,
const std::vector<TotalTime>& blockTotalTimeList, TotalTime& totalTime)
{
if (totalTimeList.size() <= 0 || totalTimeList.size() <= i || totalTimeList.size() != blockTotalTimeList.size()) {
TAG_LOGE(AAFwkTag::APPDFR, "index:%{public}zu, halfTotal size:%{public}zu, "
"blockTotal size:%{public}zu.", i, totalTimeList.size(), blockTotalTimeList.size());
return false;
}
totalTime.totalCpuTime = totalTimeList[i].totalCpuTime > blockTotalTimeList[i].totalCpuTime ?
(totalTimeList[i].totalCpuTime - blockTotalTimeList[i].totalCpuTime) :
(blockTotalTimeList[i].totalCpuTime - totalTimeList[i].totalCpuTime);
if (totalTime.totalCpuTime <= 0) {
TAG_LOGE(AAFwkTag::APPDFR, "totalCpuTime:%{public}" PRIu64"less than zero.", totalTime.totalCpuTime);
return false;
}
totalTime.totalRunningTime = totalTimeList[i].totalRunningTime > blockTotalTimeList[i].totalRunningTime ?
(totalTimeList[i].totalRunningTime - blockTotalTimeList[i].totalRunningTime) :
(blockTotalTimeList[i].totalRunningTime - totalTimeList[i].totalRunningTime);
return true;
}
std::string AppfreezeCpuFreqManager::GetCpuInfoContent(const std::vector<TotalTime> &warnTotalTimeList,
const std::vector<std::vector<CpuFreqData>> &warnCpuDetailInfo,
const std::vector<TotalTime> &blockTotalTimeList, const std::vector<std::vector<CpuFreqData>> &blockCpuDetailInfo)
{
size_t warnTotalSize = warnTotalTimeList.size();
size_t warnCpuSize = warnCpuDetailInfo.size();
if (warnTotalSize == 0 || warnTotalSize != warnCpuSize ||
warnTotalSize != blockTotalTimeList.size() || warnCpuSize != blockCpuDetailInfo.size()) {
TAG_LOGE(AAFwkTag::APPDFR, "warning total size:%{public}zu, warning cpu size:%{public}zu",
warnTotalSize, warnCpuSize);
return "";
}
std::stringstream ss;
ss << "start time:" << AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() << std::endl;
for (size_t i = 0; i < warnCpuSize; ++i) {
auto warnningData = warnCpuDetailInfo[i];
auto blockData = blockCpuDetailInfo[i];
if (warnningData.size() != blockData.size()) {
TAG_LOGE(AAFwkTag::APPDFR, "Warning and block have different sizes, warning size:%{public}zu,"
" block size:%{public}zu", warnningData.size(), blockData.size());
return "";
}
TotalTime totalTime{};
if (!GetCpuTotalValue(i, warnTotalTimeList, blockTotalTimeList, totalTime)) {
return "";
}
float percentage = (static_cast<float>(totalTime.totalRunningTime) /
static_cast<float>(totalTime.totalCpuTime)) * CPU_PERCENTAGE;;
std::vector<FrequencyPair> freqPairs;
for (size_t j = 0; j < warnningData.size(); ++j) {
FrequencyPair pair{};
uint64_t runningTime = warnningData[j].runningTime > blockData[j].runningTime ?
(warnningData[j].runningTime - blockData[j].runningTime) :
(blockData[j].runningTime - warnningData[j].runningTime);
pair.percentage = (static_cast<float>(runningTime) /
static_cast<float>(totalTime.totalCpuTime)) * CPU_PERCENTAGE;
if (pair.percentage < 1 || warnningData[j].frequency != blockData[j].frequency) {
continue;
}
pair.frequency = warnningData[j].frequency / HZ_TO_MHZ;
freqPairs.push_back(pair);
}
ss << GetCpuStr(i, freqPairs, percentage);
}
ss << "end time:" << AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() << std::endl;
return ss.str();
}
uint64_t AppfreezeCpuFreqManager::GetAppCpuTime(int32_t pid)
{
std::string cpuFile = CpuSysConfig::GetMainThreadRunningTimePath(pid);
std::string realPath = AppfreezeUtil::FreezePathToRealPath(cpuFile);
std::ifstream fin(realPath);
if (!fin.is_open()) {
TAG_LOGE(AAFwkTag::APPDFR, "Read cpu info failed, cpuFile:%{public}s, errno:%{public}d",
cpuFile.c_str(), errno);
return 0;
}
std::string content;
uint64_t cpuTime = 0;
if (getline(fin, content) && !content.empty()) {
std::vector<std::string> tokens;
SplitStr(content, " ", tokens);
if (tokens.size() <= START_TIME_SECOND_INDEX) {
TAG_LOGE(AAFwkTag::APPDFR, "GetAppCpuTime failed, content size: %{public}zu.", tokens.size());
return cpuTime;
}
cpuTime = static_cast<uint64_t>(strtoull(tokens[START_TIME_FIRST_INDEX].c_str(),
nullptr, CPU_FREQ_DECIMAL_BASE));
cpuTime += static_cast<uint64_t>(strtoull(tokens[START_TIME_SECOND_INDEX].c_str(),
nullptr, CPU_FREQ_DECIMAL_BASE));
}
return cpuTime;
}
uint64_t AppfreezeCpuFreqManager::GetProcessCpuTime(int32_t pid)
{
std::string processFile = CpuSysConfig::GetProcRunningTimePath(pid);
std::string realPath = AppfreezeUtil::FreezePathToRealPath(processFile);
std::ifstream fin(realPath);
if (!fin.is_open()) {
TAG_LOGE(AAFwkTag::APPDFR, "Read cpu info failed, processFile:%{public}s", processFile.c_str());
return 0;
}
std::string content;
uint64_t processCpuTime = 0;
if (getline(fin, content) && !content.empty()) {
std::vector<std::string> tokens;
SplitStr(content, " ", tokens);
if (tokens.size() <= START_TIME_SECOND_INDEX) {
TAG_LOGE(AAFwkTag::APPDFR, "GetAppCpuTime failed, content size: %{public}zu.", tokens.size());
return processCpuTime;
}
processCpuTime = static_cast<uint64_t>(strtoull(tokens[START_TIME_FIRST_INDEX].c_str(),
nullptr, CPU_FREQ_DECIMAL_BASE));
processCpuTime += static_cast<uint64_t>(strtoull(tokens[START_TIME_SECOND_INDEX].c_str(),
nullptr, CPU_FREQ_DECIMAL_BASE));
}
return processCpuTime;
}
uint64_t AppfreezeCpuFreqManager::GetDeviceRuntime()
{
std::ifstream fin(AppfreezeUtil::PROC_STAT_PATH);
if (!fin.is_open()) {
TAG_LOGE(AAFwkTag::APPDFR, "Read device run time failed, path:%{public}s, errno:%{public}d",
AppfreezeUtil::PROC_STAT_PATH, errno);
return 0;
}
uint64_t deviceRuntime = 0;
std::string line;
if (getline(fin, line) && !line.empty()) {
std::vector<std::string> strings;
SplitStr(line, " ", strings);
if (strings.size() <= DEFAULT_CPU_SIZE) {
TAG_LOGE(AAFwkTag::APPDFR, "GetDeviceRuntime failed, string size: %{public}zu.", strings.size());
return deviceRuntime;
}
for (size_t i = 1; i < strings.size(); ++i) {
deviceRuntime += static_cast<uint64_t>(strtoull(strings[i].c_str(), nullptr,
CPU_FREQ_DECIMAL_BASE));
}
}
return deviceRuntime;
}
GetThreadCpuLoad AppfreezeCpuFreqManager::GetThreadCpuLoadFunc()
{
static std::once_flag onceFlag;
static void* threadFuncHandler = nullptr;
static GetThreadCpuLoad getThreadCpuLoadFunc = nullptr;
std::call_once(onceFlag, []() {
threadFuncHandler = dlopen(LIB_THREAD_CPU_LOAD_PATH, RTLD_LAZY);
if (threadFuncHandler == nullptr) {
TAG_LOGE(AAFwkTag::APPDFR, "dlopen failed %{public}s, %{public}s",
LIB_THREAD_CPU_LOAD_PATH, dlerror());
return;
}
getThreadCpuLoadFunc = reinterpret_cast<GetThreadCpuLoad>(dlsym(threadFuncHandler, "GetThreadCpuLoad"));
char* err = dlerror();
if (err != nullptr) {
TAG_LOGE(AAFwkTag::APPDFR, "dlsym GetThreadCpuLoad failed: %{public}s", err);
dlclose(threadFuncHandler);
threadFuncHandler = nullptr;
getThreadCpuLoadFunc = nullptr;
}
});
return getThreadCpuLoadFunc;
}
double AppfreezeCpuFreqManager::GetDimps()
{
static double cachedDmips = INVALID_DMIPS;
if (cachedDmips > 0) {
return cachedDmips;
}
if (cpuCount_ < AppfreezeUtil::CPU_COUNT_SUBTRACT) {
return 0;
}
int maxCpuCount = cpuCount_ - AppfreezeUtil::CPU_COUNT_SUBTRACT;
std::string cpuFile = CpuSysConfig::GetMaxCoreDimpsPath(maxCpuCount);
std::string realPath = AppfreezeUtil::FreezePathToRealPath(cpuFile);
std::ifstream fin(realPath);
if (!fin.is_open()) {
TAG_LOGE(AAFwkTag::APPDFR, "Read cpu info failed, cpuFile:%{public}s, errno:%{public}d",
cpuFile.c_str(), errno);
return 0;
}
std::string content;
if (!getline(fin, content) || content.empty()) {
TAG_LOGE(AAFwkTag::APPDFR, "Read info failed, path:%{public}s", cpuFile.c_str());
return 0;
}
errno = 0;
uint64_t dimpsValue = strtoull(content.c_str(), nullptr, CPU_FREQ_DECIMAL_BASE);
if (errno != 0 || dimpsValue == 0) {
TAG_LOGE(AAFwkTag::APPDFR, "get dmips failed, errno:%{public}d dimpsValue %{public}" PRIu64 " .",
errno, dimpsValue);
return 0;
}
cachedDmips = static_cast<double>(dimpsValue);
return cachedDmips;
}
double AppfreezeCpuFreqManager::GetOptimalCpuTime(int32_t pid)
{
double dmips = GetDimps();
if (dmips <= 0) {
TAG_LOGE(AAFwkTag::APPDFR, "GetDimps failed, dmips=%{public}lf", dmips);
return 0;
}
GetThreadCpuLoad getThreadCpuLoad = GetThreadCpuLoadFunc();
if (getThreadCpuLoad == nullptr) {
TAG_LOGE(AAFwkTag::APPDFR, "GetThreadCpuLoad function not available");
return 0;
}
double optimalCpuTime = getThreadCpuLoad(pid);
if (optimalCpuTime < 0) {
TAG_LOGE(AAFwkTag::APPDFR, "getThreadCpuLoad failed for pid=%{public}d", pid);
return 0;
}
double ret = optimalCpuTime / dmips;
TAG_LOGI(AAFwkTag::APPDFR, "dmips=%{public}lf optimalCpuTime=%{public}lf ratio=%{public}lf",
dmips, optimalCpuTime, ret);
return ret;
}
std::string AppfreezeCpuFreqManager::GetTimeStampStr(uint64_t start)
{
const uint32_t placeholder = 3;
uint64_t startTime = start / AppfreezeUtil::SEC_TO_MILLISEC;
std::ostringstream startTimeStr;
startTimeStr << AppfreezeUtil::TimestampFormatToDate(startTime, "%Y-%m-%d %H:%M:%S");
startTimeStr << ":" << std::setw(placeholder) << std::setfill('0') <<
std::to_string(start % AppfreezeUtil::SEC_TO_MILLISEC);
return startTimeStr.str();
}
std::string AppfreezeCpuFreqManager::GetStaticInfoHead()
{
std::ostringstream timeInfo;
timeInfo << "#Basic Concepts" << std::endl;
timeInfo << "T1: StaticsDuration, EndTime - StartTime." << std::endl;
timeInfo << "T2: CpuTime --Time that spend on CPU." << std::endl;
timeInfo << "T3: SyncWaitTime --SleepingTime + Runnable Time, etc." << std::endl;
timeInfo << "T4: OptimalCpuTime --run the thread at the max Core's max cpu capacity." << std::endl;
timeInfo << "T5: SupplyAvailableTime --T2 - T4. Time can be optimized by scheduling." << std::endl;
timeInfo << "Equation: T1 = T2 + T3. T2 = T4 + T5." << std::endl;
timeInfo <<
"|-----------------------------------StaticsDuration-----------------------------------|." << std::endl;
timeInfo <<
"|-------------------------CpuTime----------------------|--------SyncWaitTime----------|." << std::endl;
timeInfo <<
"|----OptimalCpuTime----|------SupplyAvailableTime------|--------SyncWaitTime----------|." << std::endl;
return timeInfo.str();
}
uint64_t AppfreezeCpuFreqManager::GetInterval(uint64_t warnTime, uint64_t blockTime)
{
return blockTime >= warnTime ? (blockTime - warnTime) : (warnTime - blockTime);
}
uint64_t AppfreezeCpuFreqManager::ClockTicksToMs(uint64_t cpuTime)
{
auto clockTicks = sysconf(_SC_CLK_TCK);
if (clockTicks <= 0) {
TAG_LOGE(AAFwkTag::APPDFR, "Get _SC_CLK_TCK fail. errno %{public}d", errno);
clockTicks = DEFAULT_CLOCK_TICKS;
}
auto result = cpuTime * static_cast<uint64_t>(AppfreezeUtil::SEC_TO_MILLISEC / clockTicks);
return result;
}
std::string AppfreezeCpuFreqManager::GetConsumeTimeInfo(int32_t pid, CpuConsumeTime warnTimes,
CpuConsumeTime blockTimes)
{
double optimalCpuTime = GetInterval(warnTimes.optimalCpuTime, blockTimes.optimalCpuTime);
uint64_t processCpuTime = GetInterval(warnTimes.processCpuTime, blockTimes.processCpuTime);
processCpuTime = ClockTicksToMs(processCpuTime);
uint64_t deviceRunTime = GetInterval(warnTimes.deviceRunTime, blockTimes.deviceRunTime);
deviceRunTime = ClockTicksToMs(deviceRunTime);
uint64_t cpuTime = GetInterval(warnTimes.cpuTime, blockTimes.cpuTime);
cpuTime = ClockTicksToMs(cpuTime);
uint64_t duration = GetInterval(warnTimes.cpuFaultTime, blockTimes.cpuFaultTime);
uint64_t syncWaitTime = duration > cpuTime ? (duration - cpuTime) : 0;
double supplyAvailableTime = cpuTime - optimalCpuTime;
std::ostringstream timeInfo;
timeInfo << GetStaticInfoHead() << std::endl;
timeInfo << "#Basic Statistical Infomation " << std::endl;
timeInfo << "ProcessCpuTime: " << processCpuTime << " ms" << std::endl;
timeInfo << "DeviceRuntime: " << deviceRunTime << " ms" << std::endl;
timeInfo << "Tid: " << pid << std::endl;
timeInfo << "StartTime: " << GetTimeStampStr(warnTimes.cpuFaultTime) << std::endl;
timeInfo << "EndTime: " << GetTimeStampStr(blockTimes.cpuFaultTime) << std::endl;
timeInfo << "StaticsDuration: " << duration << " ms" << std::endl;
timeInfo << "CpuTime: " << cpuTime << " ms" << std::endl;
timeInfo << "SyncWaitTime: " << syncWaitTime << " ms" << std::endl;
timeInfo << "OptimalCpuTime: " << optimalCpuTime << " ms" << std::endl;
timeInfo << "SupplyAvailableTime: " << supplyAvailableTime << " ms" << std::endl;
return timeInfo.str();
}
std::string AppfreezeCpuFreqManager::GetFreezeLogHead(const std::string &bundleName)
{
std::stringstream ss;
ss << LOG_FILE_HEAD << std::endl;
ss << LOG_FILE_SEP << std::endl;
ss << "TimeStamp: " << AbilityRuntime::TimeUtil::DefaultCurrentTimeStr() << std::endl;
ss << "Module name: " << bundleName << std::endl;
return ss.str();
}
bool AppfreezeCpuFreqManager::IsContainHalfData(const std::string &key, CpuDataProcessor &cpuData, int32_t pid)
{
std::lock_guard<ffrt::mutex> lock(freezeInfoMutex_);
auto it = cpuInfoMap_.find(key);
if (it == cpuInfoMap_.end()) {
TAG_LOGI(AAFwkTag::APPDFR, "Not find warning fault, pid:%{public}d", pid);
return false;
}
int warningPid = it->second.GetPid();
if (warningPid != pid) {
TAG_LOGI(AAFwkTag::APPDFR, "Not find current pid:%{public}d, warning pid:%{public}d.", pid, warningPid);
return false;
}
cpuData = it->second;
return true;
}
std::string AppfreezeCpuFreqManager::GetCpuInfoPath(const std::string &type,
const std::string &bundleName, int32_t uid, int32_t pid)
{
CpuDataProcessor warnCpuInfo;
if (!IsContainHalfData(type, warnCpuInfo, pid)) {
return "";
}
CpuDataProcessor blockCpuInfo = std::move(GetCpuDetailInfo(pid));
std::string fileName = CPU_INFO_PREFIX + std::to_string(uid) +
AbilityRuntime::TimeUtil::FormatTime("%Y%m%d%H%M%S");
std::string logFile = AppfreezeUtil::CreateFile(AppfreezeUtil::EVENTLOG_PATH, fileName);
std::ostringstream str;
str << GetFreezeLogHead(bundleName) << std::endl;
str << GetConsumeTimeInfo(pid, warnCpuInfo.GetCpuConsumeTime(), blockCpuInfo.GetCpuConsumeTime()) << std::endl;
str << "#CpuFreq Usage (usage >=1%)" << std::endl << GetCpuInfoContent(
warnCpuInfo.GetTotalTimeList(), warnCpuInfo.GetCpuDetailData(),
blockCpuInfo.GetTotalTimeList(), blockCpuInfo.GetCpuDetailData()) << std::endl;
if (!OHOS::SaveStringToFile(logFile, str.str(), false)) {
TAG_LOGE(AAFwkTag::APPDFR, "save to cpu info to file failed, logFile: %{public}s", logFile.c_str());
} else {
TAG_LOGW(AAFwkTag::APPDFR, "write cpu info success, logFile: %{public}s", logFile.c_str());
}
{
std::lock_guard<ffrt::mutex> lock(freezeInfoMutex_);
cpuInfoMap_.erase(type);
}
return logFile;
}
}
}