13c3173acSopenharmony_ci/*
23c3173acSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
33c3173acSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43c3173acSopenharmony_ci * you may not use this file except in compliance with the License.
53c3173acSopenharmony_ci * You may obtain a copy of the License at
63c3173acSopenharmony_ci *
73c3173acSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83c3173acSopenharmony_ci *
93c3173acSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103c3173acSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113c3173acSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123c3173acSopenharmony_ci * See the License for the specific language governing permissions and
133c3173acSopenharmony_ci * limitations under the License.
143c3173acSopenharmony_ci */
153c3173acSopenharmony_ci#include <cstdlib>
163c3173acSopenharmony_ci#include <string>
173c3173acSopenharmony_ci#include <climits>
183c3173acSopenharmony_ci
193c3173acSopenharmony_ci#include "config_reader.h"
203c3173acSopenharmony_ci#include "config_policy_utils.h"
213c3173acSopenharmony_ci#include "concurrent_task_log.h"
223c3173acSopenharmony_ci#include "parameters.h"
233c3173acSopenharmony_ci
243c3173acSopenharmony_ciusing namespace std;
253c3173acSopenharmony_ci
263c3173acSopenharmony_cinamespace OHOS {
273c3173acSopenharmony_cinamespace ConcurrentTask {
283c3173acSopenharmony_cinamespace {
293c3173acSopenharmony_ci    const std::string XML_TAG_QOS_CONFIG = "qosconfig";
303c3173acSopenharmony_ci    const std::string XML_TAG_QOS_AUTH = "auth";
313c3173acSopenharmony_ci    const std::string XML_TAG_UIDLIST = "uidlist";
323c3173acSopenharmony_ci    const std::string XML_TAG_UID = "uid";
333c3173acSopenharmony_ci    const std::string XML_TAG_BUNDLENAMELIST = "bundlenamelist";
343c3173acSopenharmony_ci    const std::string XML_TAG_BUNDLENAME = "bundlename";
353c3173acSopenharmony_ci    const std::string XML_TAG_POWER_MODE = "powermode";
363c3173acSopenharmony_ci    const std::string XML_TAG_SWITCH = "switch";
373c3173acSopenharmony_ci    const std::string XML_TAG_FPS = "fps";
383c3173acSopenharmony_ci    const std::string XML_TAG_DEGRADATION_FPS = "degradationfps";
393c3173acSopenharmony_ci    const std::string XML_TAG_FPS_HIGH = "120";
403c3173acSopenharmony_ci    const std::string XML_TAG_FPS_MEDIUM = "90";
413c3173acSopenharmony_ci    const std::string XML_TAG_FPS_STANDARD = "60";
423c3173acSopenharmony_ci    constexpr int FPS_OFFSET = 10000;
433c3173acSopenharmony_ci}
443c3173acSopenharmony_ci
453c3173acSopenharmony_cibool ConfigReader::IsValidNode(const xmlNode* currNode)
463c3173acSopenharmony_ci{
473c3173acSopenharmony_ci    if (!currNode) {
483c3173acSopenharmony_ci        return false;
493c3173acSopenharmony_ci    }
503c3173acSopenharmony_ci    if (!currNode->name || currNode->type == XML_COMMENT_NODE) {
513c3173acSopenharmony_ci        return false;
523c3173acSopenharmony_ci    }
533c3173acSopenharmony_ci    return true;
543c3173acSopenharmony_ci}
553c3173acSopenharmony_ci
563c3173acSopenharmony_cibool ConfigReader::FillinUidInfo(const xmlNode* currNode)
573c3173acSopenharmony_ci{
583c3173acSopenharmony_ci    if (!IsValidNode(currNode)) {
593c3173acSopenharmony_ci        CONCUR_LOGE("FillinUidInfo:: currNode is nullptr!");
603c3173acSopenharmony_ci        return false;
613c3173acSopenharmony_ci    }
623c3173acSopenharmony_ci    xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
633c3173acSopenharmony_ci    for (; currNodePtr; currNodePtr = currNodePtr->next) {
643c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_UID.c_str())) == 0) {
653c3173acSopenharmony_ci            xmlChar *attrValue = xmlGetProp(currNodePtr, reinterpret_cast<const xmlChar*>(XML_TAG_UID.c_str()));
663c3173acSopenharmony_ci            if (!attrValue) {
673c3173acSopenharmony_ci                CONCUR_LOGE("FillinUidInfo:: uid null!");
683c3173acSopenharmony_ci                return false;
693c3173acSopenharmony_ci            }
703c3173acSopenharmony_ci            int64_t uid = atoi(reinterpret_cast<const char*>(attrValue));
713c3173acSopenharmony_ci            authProcUidConfigs_.insert(uid);
723c3173acSopenharmony_ci            xmlFree(attrValue);
733c3173acSopenharmony_ci        }
743c3173acSopenharmony_ci    }
753c3173acSopenharmony_ci    return true;
763c3173acSopenharmony_ci}
773c3173acSopenharmony_ci
783c3173acSopenharmony_cibool ConfigReader::FillinBundleNameInfo(const xmlNode* currNode)
793c3173acSopenharmony_ci{
803c3173acSopenharmony_ci    if (!IsValidNode(currNode)) {
813c3173acSopenharmony_ci        CONCUR_LOGE("FillinBundleNameInfo:: currNode is nullptr!");
823c3173acSopenharmony_ci        return false;
833c3173acSopenharmony_ci    }
843c3173acSopenharmony_ci    xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
853c3173acSopenharmony_ci    for (; currNodePtr; currNodePtr = currNodePtr->next) {
863c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_BUNDLENAME.c_str())) == 0) {
873c3173acSopenharmony_ci            xmlChar *attrValue = xmlGetProp(currNodePtr, reinterpret_cast<const xmlChar*>(XML_TAG_BUNDLENAME.c_str()));
883c3173acSopenharmony_ci            if (!attrValue) {
893c3173acSopenharmony_ci                CONCUR_LOGE("FillinBundleNameInfo:: bundleName null!");
903c3173acSopenharmony_ci                return false;
913c3173acSopenharmony_ci            }
923c3173acSopenharmony_ci            std::string bundleName = reinterpret_cast<const char*>(attrValue);
933c3173acSopenharmony_ci            authProcBundleNameConfigs_.insert(bundleName);
943c3173acSopenharmony_ci            xmlFree(attrValue);
953c3173acSopenharmony_ci        }
963c3173acSopenharmony_ci    }
973c3173acSopenharmony_ci    return true;
983c3173acSopenharmony_ci}
993c3173acSopenharmony_ci
1003c3173acSopenharmony_civoid ConfigReader::ParseAuth(const xmlNode* currNode)
1013c3173acSopenharmony_ci{
1023c3173acSopenharmony_ci    xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
1033c3173acSopenharmony_ci    for (; currNodePtr; currNodePtr = currNodePtr->next) {
1043c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_UIDLIST.c_str())) == 0) {
1053c3173acSopenharmony_ci            if (!FillinUidInfo(currNodePtr)) {
1063c3173acSopenharmony_ci                CONCUR_LOGE("ParseAuth:: uid fill in authProcUidConfigs_ error!");
1073c3173acSopenharmony_ci                continue;
1083c3173acSopenharmony_ci            }
1093c3173acSopenharmony_ci        }
1103c3173acSopenharmony_ci
1113c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_BUNDLENAMELIST.c_str())) == 0) {
1123c3173acSopenharmony_ci            if (!FillinBundleNameInfo(currNodePtr)) {
1133c3173acSopenharmony_ci                CONCUR_LOGE("ParseAuth:: bundleName fill in authProcBundleNameConfigs_ error!");
1143c3173acSopenharmony_ci                continue;
1153c3173acSopenharmony_ci            }
1163c3173acSopenharmony_ci        }
1173c3173acSopenharmony_ci    }
1183c3173acSopenharmony_ci}
1193c3173acSopenharmony_ci
1203c3173acSopenharmony_civoid ConfigReader::ParsePowerMode(const xmlNode* currNode)
1213c3173acSopenharmony_ci{
1223c3173acSopenharmony_ci    if (!IsValidNode(currNode)) {
1233c3173acSopenharmony_ci        CONCUR_LOGE("ParsePowerMode:: currNode is nullptr!");
1243c3173acSopenharmony_ci        return;
1253c3173acSopenharmony_ci    }
1263c3173acSopenharmony_ci    xmlNodePtr currNodePtr = currNode->xmlChildrenNode;
1273c3173acSopenharmony_ci    for (; currNodePtr; currNodePtr = currNodePtr->next) {
1283c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_SWITCH.c_str())) == 0) {
1293c3173acSopenharmony_ci            char* switchValue = reinterpret_cast<char*>(xmlNodeGetContent(currNodePtr));
1303c3173acSopenharmony_ci            if (!switchValue) {
1313c3173acSopenharmony_ci                CONCUR_LOGE("ParsePowerMode:: switch is null!");
1323c3173acSopenharmony_ci                continue;
1333c3173acSopenharmony_ci            }
1343c3173acSopenharmony_ci            if (strncmp(switchValue, "1", 1) == 0) {
1353c3173acSopenharmony_ci                powerModeSchedSwitch_ = true;
1363c3173acSopenharmony_ci            } else if (strncmp(switchValue, "0", 1) == 0) {
1373c3173acSopenharmony_ci                powerModeSchedSwitch_ = false;
1383c3173acSopenharmony_ci            } else {
1393c3173acSopenharmony_ci                CONCUR_LOGE("ParsePowerMode:: invalid switch value!");
1403c3173acSopenharmony_ci            }
1413c3173acSopenharmony_ci            xmlFree(switchValue);
1423c3173acSopenharmony_ci        }
1433c3173acSopenharmony_ci
1443c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_DEGRADATION_FPS.c_str())) == 0) {
1453c3173acSopenharmony_ci            char* fpsValue = reinterpret_cast<char*>(xmlGetProp(currNodePtr,
1463c3173acSopenharmony_ci                reinterpret_cast<const xmlChar*>(XML_TAG_FPS.c_str())));
1473c3173acSopenharmony_ci            char* deFpsValue = reinterpret_cast<char*>(xmlNodeGetContent(currNodePtr));
1483c3173acSopenharmony_ci            if (fpsValue && deFpsValue && IsValidFps(fpsValue) && IsPositiveInt(deFpsValue)) {
1493c3173acSopenharmony_ci                degradationFpsMap_.insert(std::make_pair(atoi(fpsValue), atoi(deFpsValue)));
1503c3173acSopenharmony_ci            } else {
1513c3173acSopenharmony_ci                CONCUR_LOGE("ParsePowerMode:: fps is null or invalid!");
1523c3173acSopenharmony_ci            }
1533c3173acSopenharmony_ci            if (fpsValue) {
1543c3173acSopenharmony_ci                xmlFree(fpsValue);
1553c3173acSopenharmony_ci            }
1563c3173acSopenharmony_ci            if (deFpsValue) {
1573c3173acSopenharmony_ci                xmlFree(deFpsValue);
1583c3173acSopenharmony_ci            }
1593c3173acSopenharmony_ci        }
1603c3173acSopenharmony_ci    }
1613c3173acSopenharmony_ci}
1623c3173acSopenharmony_ci
1633c3173acSopenharmony_cibool ConfigReader::LoadFromConfigFile(const std::string& configFile)
1643c3173acSopenharmony_ci{
1653c3173acSopenharmony_ci    // skip the empty string, else you will get empty node
1663c3173acSopenharmony_ci    xmlDocPtr xmlDocPtr = xmlReadFile(configFile.c_str(), nullptr,
1673c3173acSopenharmony_ci        XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
1683c3173acSopenharmony_ci    if (!xmlDocPtr) {
1693c3173acSopenharmony_ci        CONCUR_LOGE("LoadFromConfigFile:: xmlReadFile error!");
1703c3173acSopenharmony_ci        return false;
1713c3173acSopenharmony_ci    }
1723c3173acSopenharmony_ci    xmlNodePtr rootNodePtr = xmlDocGetRootElement(xmlDocPtr);
1733c3173acSopenharmony_ci    if (!rootNodePtr || !rootNodePtr->name ||
1743c3173acSopenharmony_ci        xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_QOS_CONFIG.c_str())) != 0) {
1753c3173acSopenharmony_ci        CONCUR_LOGE("LoadFromConfigFile:: root element tag error!");
1763c3173acSopenharmony_ci        xmlFreeDoc(xmlDocPtr);
1773c3173acSopenharmony_ci        return false;
1783c3173acSopenharmony_ci    }
1793c3173acSopenharmony_ci    xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
1803c3173acSopenharmony_ci    for (; currNodePtr; currNodePtr = currNodePtr->next) {
1813c3173acSopenharmony_ci        if (!IsValidNode(currNodePtr)) {
1823c3173acSopenharmony_ci            CONCUR_LOGE("LoadFromConfigFile:: IsInvalidNode!");
1833c3173acSopenharmony_ci            continue;
1843c3173acSopenharmony_ci        }
1853c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_QOS_AUTH.c_str())) == 0) {
1863c3173acSopenharmony_ci            ParseAuth(currNodePtr);
1873c3173acSopenharmony_ci        }
1883c3173acSopenharmony_ci        if (xmlStrcmp(currNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_POWER_MODE.c_str())) == 0) {
1893c3173acSopenharmony_ci            ParsePowerMode(currNodePtr);
1903c3173acSopenharmony_ci        }
1913c3173acSopenharmony_ci    }
1923c3173acSopenharmony_ci    ConfigHilog();
1933c3173acSopenharmony_ci    xmlFreeDoc(xmlDocPtr);
1943c3173acSopenharmony_ci    return true;
1953c3173acSopenharmony_ci}
1963c3173acSopenharmony_ci
1973c3173acSopenharmony_civoid ConfigReader::GetRealConfigPath(const char* configName, std::string& configPath)
1983c3173acSopenharmony_ci{
1993c3173acSopenharmony_ci    if (!configName) {
2003c3173acSopenharmony_ci        CONCUR_LOGE("GetRealConfigPath:: configName is nullptr!");
2013c3173acSopenharmony_ci        return;
2023c3173acSopenharmony_ci    }
2033c3173acSopenharmony_ci    char buf[PATH_MAX] = {0};
2043c3173acSopenharmony_ci    char* configFilePath = GetOneCfgFile(configName, buf, PATH_MAX);
2053c3173acSopenharmony_ci    char tmpPath[PATH_MAX] = {0};
2063c3173acSopenharmony_ci    if (!configFilePath || strlen(configFilePath) == 0 || strlen(configFilePath) > PATH_MAX ||
2073c3173acSopenharmony_ci        !realpath(configFilePath, tmpPath)) {
2083c3173acSopenharmony_ci        CONCUR_LOGE("GetRealConfigPath:: get config file path error!");
2093c3173acSopenharmony_ci        configPath = "";
2103c3173acSopenharmony_ci        return;
2113c3173acSopenharmony_ci    }
2123c3173acSopenharmony_ci    configPath = tmpPath;
2133c3173acSopenharmony_ci}
2143c3173acSopenharmony_ci
2153c3173acSopenharmony_cibool ConfigReader::IsUidAuth(pid_t uid)
2163c3173acSopenharmony_ci{
2173c3173acSopenharmony_ci    if (authProcUidConfigs_.find(uid) != authProcUidConfigs_.end()) {
2183c3173acSopenharmony_ci        return true;
2193c3173acSopenharmony_ci    }
2203c3173acSopenharmony_ci    return false;
2213c3173acSopenharmony_ci}
2223c3173acSopenharmony_ci
2233c3173acSopenharmony_cibool ConfigReader::IsBundleNameAuth(std::string& bundleName)
2243c3173acSopenharmony_ci{
2253c3173acSopenharmony_ci    if (authProcBundleNameConfigs_.find(bundleName) != authProcBundleNameConfigs_.end()) {
2263c3173acSopenharmony_ci        return true;
2273c3173acSopenharmony_ci    }
2283c3173acSopenharmony_ci    return false;
2293c3173acSopenharmony_ci}
2303c3173acSopenharmony_ci
2313c3173acSopenharmony_cibool ConfigReader::GetPowerModeSchedSwitch()
2323c3173acSopenharmony_ci{
2333c3173acSopenharmony_ci    return powerModeSchedSwitch_;
2343c3173acSopenharmony_ci}
2353c3173acSopenharmony_ci
2363c3173acSopenharmony_ciint ConfigReader::GetDegratationFps(int fps)
2373c3173acSopenharmony_ci{
2383c3173acSopenharmony_ci    if (degradationFpsMap_.find(fps) == degradationFpsMap_.end()) {
2393c3173acSopenharmony_ci        return fps + FPS_OFFSET;
2403c3173acSopenharmony_ci    }
2413c3173acSopenharmony_ci    return degradationFpsMap_[fps] + FPS_OFFSET;
2423c3173acSopenharmony_ci}
2433c3173acSopenharmony_ci
2443c3173acSopenharmony_cibool ConfigReader::IsValidFps(const std::string& fps)
2453c3173acSopenharmony_ci{
2463c3173acSopenharmony_ci    if (fps == XML_TAG_FPS_HIGH || fps == XML_TAG_FPS_MEDIUM || fps == XML_TAG_FPS_STANDARD) {
2473c3173acSopenharmony_ci        return true;
2483c3173acSopenharmony_ci    }
2493c3173acSopenharmony_ci    return false;
2503c3173acSopenharmony_ci}
2513c3173acSopenharmony_ci
2523c3173acSopenharmony_cibool ConfigReader::IsPositiveInt(const std::string& intStr)
2533c3173acSopenharmony_ci{
2543c3173acSopenharmony_ci    int num = 0;
2553c3173acSopenharmony_ci    try {
2563c3173acSopenharmony_ci        num = stoi(intStr);
2573c3173acSopenharmony_ci    } catch (...) {
2583c3173acSopenharmony_ci        CONCUR_LOGE("Unexpected number format!");
2593c3173acSopenharmony_ci        return false;
2603c3173acSopenharmony_ci    }
2613c3173acSopenharmony_ci    return num > 0;
2623c3173acSopenharmony_ci}
2633c3173acSopenharmony_ci
2643c3173acSopenharmony_civoid ConfigReader::ConfigHilog()
2653c3173acSopenharmony_ci{
2663c3173acSopenharmony_ci    bool getConfigRead = OHOS::system::GetBoolParameter("persist.qos.configreadlog", false);
2673c3173acSopenharmony_ci    if (getConfigRead) {
2683c3173acSopenharmony_ci        for (auto iter : authProcUidConfigs_) {
2693c3173acSopenharmony_ci            CONCUR_LOGI("authProcUidConfigs_ contain uid = %{public}d", (int32_t)iter);
2703c3173acSopenharmony_ci        }
2713c3173acSopenharmony_ci        for (auto iter : authProcBundleNameConfigs_) {
2723c3173acSopenharmony_ci            CONCUR_LOGI("authProcBundleNameConfigs_ contain bundleName = %{public}s", iter.c_str());
2733c3173acSopenharmony_ci        }
2743c3173acSopenharmony_ci        CONCUR_LOGI("powerModeSchedSwitch_ = %{public}d", powerModeSchedSwitch_);
2753c3173acSopenharmony_ci        for (auto iter : degradationFpsMap_) {
2763c3173acSopenharmony_ci            CONCUR_LOGI("fps = %{public}d degradationFps = %{public}d", iter.first, iter.second);
2773c3173acSopenharmony_ci        }
2783c3173acSopenharmony_ci    }
2793c3173acSopenharmony_ci}
2803c3173acSopenharmony_ci}
2813c3173acSopenharmony_ci}