/*
 * 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;
}
}  // namespace AppExecFwk
}  // namespace OHOS