diff --git a/common/include/config_reader.h b/common/include/config_reader.h index 94629b09054e2f21a324af19a4ee96a8d2a3520e..fb78112562198955b11e6b6acc4b57ebce7ab433 100644 --- a/common/include/config_reader.h +++ b/common/include/config_reader.h @@ -15,6 +15,7 @@ #ifndef CONCURRENT_TASK_SERVICES_COMMON_INCLUDE_CONFIG_READER_H #define CONCURRENT_TASK_SERVICES_COMMON_INCLUDE_CONFIG_READER_H +#include #include #include #include "libxml/parser.h" @@ -28,14 +29,21 @@ public: void GetRealConfigPath(const char* configName, std::string& configPath); bool IsUidAuth(pid_t uid); bool IsBundleNameAuth(std::string& bundleName); + bool GetPowerModeSchedSwitch(); + int GetDegratationFps(int fps); private: bool IsValidNode(const xmlNode* currNode); + bool IsValidFps(const std::string& fps); + bool IsPositiveInt(const std::string& intStr); bool FillinUidInfo(const xmlNode* currNode); bool FillinBundleNameInfo(const xmlNode* currNode); void ParseAuth(const xmlNode* currNode); + void ParsePowerMode(const xmlNode* currNode); void ConfigHilog(); + bool powerModeSchedSwitch_ = false; std::unordered_set authProcUidConfigs_; std::unordered_set authProcBundleNameConfigs_; + std::map degradationFpsMap_; }; } // namespace ConcurrentTask } // namespace OHOS diff --git a/common/src/config_reader.cpp b/common/src/config_reader.cpp index 5374fa232f16c4d9da0aa673f08e5f9d345f4811..26c46a662c24a4ecc834f07632fe413dc3391bc4 100644 --- a/common/src/config_reader.cpp +++ b/common/src/config_reader.cpp @@ -32,6 +32,10 @@ namespace { const std::string XML_TAG_UID = "uid"; const std::string XML_TAG_BUNDLENAMELIST = "bundlenamelist"; const std::string XML_TAG_BUNDLENAME = "bundlename"; + const std::string XML_TAG_POWER_MODE = "powermode"; + const std::string XML_TAG_SWITCH = "switch"; + const std::string XML_TAG_FPS = "fps"; + const std::string XML_TAG_DEGRADATION_FPS = "degradationfps"; } bool ConfigReader::IsValidNode(const xmlNode* currNode) @@ -109,6 +113,49 @@ void ConfigReader::ParseAuth(const xmlNode* currNode) } } +void ConfigReader::ParsePowerMode(const xmlNode* currNode) +{ + if (!IsValidNode(currNode)) { + CONCUR_LOGE("ParsePowerMode:: currNode is nullptr!"); + return; + } + xmlNodePtr currNodePtr = currNode->xmlChildrenNode; + for (; currNodePtr; currNodePtr = currNodePtr->next) { + if (xmlStrcmp(currNodePtr->name, reinterpret_cast(XML_TAG_SWITCH.c_str())) == 0) { + char* switchValue = reinterpret_cast(xmlNodeGetContent(currNode)); + if (!switchValue) { + CONCUR_LOGE("ParsePowerMode:: switch is null!"); + continue; + } + if (strcmp(switchValue, "1") == 0) { + powerModeSchedSwitch_ = true; + } else if (strcmp(switchValue, "0") == 0) { + powerModeSchedSwitch_ = false; + } else { + CONCUR_LOGE("ParsePowerMode:: invalid switch value!"); + } + xmlFree(switchValue); + } + + if (xmlStrcmp(currNodePtr->name, reinterpret_cast(XML_TAG_DEGRADATION_FPS.c_str())) == 0) { + char* fpsValue = reinterpret_cast(xmlGetProp(currNodePtr, + reinterpret_cast(XML_TAG_FPS.c_str()))); + char* deFpsValue = reinterpret_cast(xmlNodeGetContent(currNode)); + if (!fpsValue || !deFpsValue) { + CONCUR_LOGE("ParsePowerMode:: fps is null!"); + continue; + } + if (IsValidFps(fpsValue) && IsPositiveInt(deFpsValue)) { + degradationFpsMap_.insert(std::make_pair(atoi(fpsValue), atoi(deFpsValue))); + } else { + CONCUR_LOGE("ParsePowerMode:: invalid fps value!"); + } + xmlFree(fpsValue); + xmlFree(deFpsValue); + } + } +} + bool ConfigReader::LoadFromConfigFile(const std::string& configFile) { // skip the empty string, else you will get empty node @@ -134,6 +181,9 @@ bool ConfigReader::LoadFromConfigFile(const std::string& configFile) if (xmlStrcmp(currNodePtr->name, reinterpret_cast(XML_TAG_QOS_AUTH.c_str())) == 0) { ParseAuth(currNodePtr); } + if (xmlStrcmp(currNodePtr->name, reinterpret_cast(XML_TAG_POWER_MODE.c_str())) == 0) { + ParsePowerMode(currNodePtr); + } } ConfigHilog(); xmlFreeDoc(xmlDocPtr); @@ -174,6 +224,39 @@ bool ConfigReader::IsBundleNameAuth(std::string& bundleName) return false; } +bool ConfigReader::GetPowerModeSchedSwitch() +{ + return powerModeSchedSwitch_; +} + +int ConfigReader::GetDegratationFps(int fps) +{ + if (degradationFpsMap_.find(fps) == degradationFpsMap_.end()) { + return fps; + } + return degradationFpsMap_[fps]; +} + +bool ConfigReader::IsValidFps(const std::string& fps) +{ + if (fps == "120" || fps == "90" || fps == "60") { + return true; + } + return false; +} + +bool ConfigReader::IsPositiveInt(const std::string& intStr) +{ + int num = 0; + try { + num = stoi(intStr); + } catch (...) { + CONCUR_LOGE("Unexpected number format!"); + return false; + } + return num > 0; +} + void ConfigReader::ConfigHilog() { bool getConfigRead = OHOS::system::GetBoolParameter("persist.qos.configreadlog", false); @@ -184,6 +267,10 @@ void ConfigReader::ConfigHilog() for (auto iter : authProcBundleNameConfigs_) { CONCUR_LOGI("authProcBundleNameConfigs_ contain bundleName = %{public}s", iter.c_str()); } + CONCUR_LOGI("powerModeSchedSwitch_ = %{public}d", powerModeSchedSwitch_); + for (auto iter : degradationFpsMap_) { + CONCUR_LOGI("fps = %{public}d degradationFps = %{public}d", iter.first, iter.second); + } } } } diff --git a/frameworks/concurrent_task_client/include/concurrent_task_type.h b/frameworks/concurrent_task_client/include/concurrent_task_type.h index c900f10a13d8ecdbc5de64f4b805bcd862285341..a83277f2c2934d1a5cb7398bc607ac06530673be 100644 --- a/frameworks/concurrent_task_client/include/concurrent_task_type.h +++ b/frameworks/concurrent_task_client/include/concurrent_task_type.h @@ -28,6 +28,8 @@ enum MsgType { MSG_CONTINUOUS_TASK_END, MSG_GET_FOCUS, MSG_LOSE_FOCUS, + MSG_ENTER_INTERACTION_SCENE, + MSG_EXIT_INTERACTION_SCENE, MSG_SYSTEM_MAX, MSG_APP_START_TYPE = 100, MSG_REG_RENDER = MSG_APP_START_TYPE, diff --git a/services/include/concurrent_task_controller.h b/services/include/concurrent_task_controller.h index a2ee3080b9529df30ca5cf1122c2670ef01d04b1..ca00b9def97e19e92a103ecdcc4c887d1cbe6d7b 100644 --- a/services/include/concurrent_task_controller.h +++ b/services/include/concurrent_task_controller.h @@ -64,16 +64,22 @@ private: void DealSystemRequest(int requestType, const Json::Value& payload); void NewForeground(int uid, int pid); void NewBackground(int uid, int pid); - void NewAppStart(int uid, int pid, const std::string& bundleName); + void NewAppStart(int uid, int pid, const std::string& bundleName, int appType); void AppKilled(int uid, int pid); void ContinuousTaskProcess(int uid, int pid, int status); void FocusStatusProcess(int uid, int pid, int status); + void InteractionSceneProcess(int status); + void DeadlinePerfMode(); + void DeadlinePowerMode(); + bool IsVideoApp(int pid); + int ParseAppType(const Json::Value& payload); int AuthSystemProcess(int pid); bool ConfigReaderInit(); bool ModifySystemRate(const Json::Value& payload); void SetAppRate(const Json::Value& payload); int FindRateFromInfo(int uiTid, const Json::Value& payload); void SetRenderServiceRate(const Json::Value& payload); + void SetAppAndRenderServicRate(int appRate, int rsRate); bool CheckJsonValid(const Json::Value& payload); void SetFrameRate(int rtgId, int rate); std::list::iterator GetRecordOfPid(int pid); @@ -88,6 +94,7 @@ private: std::mutex appInfoLock_; std::mutex rateInfoLock_; std::mutex executorStartLock_; + std::mutex ddlPowerModeLock_; std::list foregroundApp_ = {}; std::list rsThreads_ = {}; std::unordered_map msgType_ = {}; @@ -100,13 +107,18 @@ private: int hardwareGrpId_ = -1; int hardwareTid_ = -1; int systemRate_ = 0; + int uniAppRate_ = 0; bool rtgEnabled_ = false; bool configEnable_ = false; bool rsAuthed_ = false; + bool ddlSceneSchedSwitch_ = false; + bool ddlPowerModeEnable_ = false; + bool isVideoApp_ = false; std::atomic curGamePid_ = -1; int executorNum_ = 0; std::map appBundleName; std::unique_ptr configReader_ = nullptr; + std::unordered_map appTypeCache_; const std::string RENDER_SERVICE_PROCESS_NAME = "render_service"; const std::string RESOURCE_SCHEDULE_PROCESS_NAME = "resource_schedule_service"; diff --git a/services/src/concurrent_task_controller.cpp b/services/src/concurrent_task_controller.cpp index 60e329959e1a468f100bdfcb073e9b01e4937e37..6a5082996d306e6138d6536cd667f37d2a622756 100644 --- a/services/src/concurrent_task_controller.cpp +++ b/services/src/concurrent_task_controller.cpp @@ -44,6 +44,9 @@ namespace { constexpr int RTG_TYPE_MAX = 3; constexpr int RS_UID = 1003; constexpr int EXECUTOR_LIMIT_NUM = 3; + constexpr int APP_TYPE_VIDEO = 10067; + constexpr int APP_TYPE_VIDEO_CLIP = 10026; + constexpr int APP_TYPE_INVALID = -1; } #define CMD_ID_SET_RTG \ @@ -343,12 +346,15 @@ bool TaskController::ConfigReaderInit() return configEnable_; } configEnable_ = true; + ddlSceneSchedSwitch_ = configReader_->GetPowerModeSchedSwitch(); + CONCUR_LOGI("deadline scene sched switch = %{public}d", ddlSceneSchedSwitch_); return configEnable_; } void TaskController::Release() { msgType_.clear(); + appTypeCache_.clear(); if (renderServiceMainGrpId_ > 0) { DestroyRtgGrp(renderServiceMainGrpId_); renderServiceMainGrpId_ = -1; @@ -357,6 +363,7 @@ void TaskController::Release() DestroyRtgGrp(renderServiceRenderGrpId_); renderServiceRenderGrpId_ = -1; } + ddlSceneSchedSwitch_ = false; configReader_ = nullptr; } @@ -371,6 +378,8 @@ void TaskController::TypeMapInit() msgType_.insert(pair("continuousEnd", MSG_CONTINUOUS_TASK_END)); msgType_.insert(pair("getFocus", MSG_GET_FOCUS)); msgType_.insert(pair("loseFocus", MSG_LOSE_FOCUS)); + msgType_.insert(pair("enterInteractionScene", MSG_ENTER_INTERACTION_SCENE)); + msgType_.insert(pair("exitInteractionScene", MSG_EXIT_INTERACTION_SCENE)); } void TaskController::TryCreateRSMainGrp() @@ -457,7 +466,7 @@ void TaskController::DealSystemRequest(int requestType, const Json::Value& paylo NewBackground(uid, pid); break; case MSG_APP_START: - NewAppStart(uid, pid, bundleName); + NewAppStart(uid, pid, bundleName, ParseAppType(payload)); break; case MSG_APP_KILLED: AppKilled(uid, pid); @@ -470,6 +479,10 @@ void TaskController::DealSystemRequest(int requestType, const Json::Value& paylo case MSG_LOSE_FOCUS: FocusStatusProcess(uid, pid, requestType); break; + case MSG_ENTER_INTERACTION_SCENE: + case MSG_EXIT_INTERACTION_SCENE: + InteractionSceneProcess(requestType); + break; default: CONCUR_LOGE("Unknown system request"); break; @@ -571,7 +584,7 @@ void TaskController::NewBackground(int uid, int pid) } } -void TaskController::NewAppStart(int uid, int pid, const std::string& bundleName) +void TaskController::NewAppStart(int uid, int pid, const std::string& bundleName, int appType) { CONCUR_LOGI("pid %{public}d start.", pid); unsigned int pidParam = static_cast(pid); @@ -585,8 +598,12 @@ void TaskController::NewAppStart(int uid, int pid, const std::string& bundleName CONCUR_LOGE("auth_enable %{public}d fail with ret %{public}d", pid, ret); return; } + std::lock_guard lock(appInfoLock_); authApps_.push_back(pid); appBundleName[pid] = bundleName; + if (ddlSceneSchedSwitch_ && appType != APP_TYPE_INVALID) { + appTypeCache_[bundleName] = appType; + } } void TaskController::AppKilled(int uid, int pid) @@ -650,14 +667,65 @@ void TaskController::FocusStatusProcess(int uid, int pid, int status) if (status == static_cast(MSG_GET_FOCUS)) { ret = AuthSwitch(pid, rtgFlag, qosFlag, static_cast(AuthStatus::AUTH_STATUS_FOCUS)); CONCUR_LOGI("pid %{public}d get focus. ret %{public}d", pid, ret); + if (ddlSceneSchedSwitch_) { + if (IsVideoApp(pid)) { + isVideoApp_ = true; + CONCUR_LOGD("video app bundleName %{public}s get focus", appBundleName[pid].c_str()); + } else { + isVideoApp_ = false; + } + } } else if (status == static_cast(MSG_LOSE_FOCUS)) { ret = AuthSwitch(pid, rtgFlag, qosFlag, static_cast(AuthStatus::AUTH_STATUS_FOREGROUND)); CONCUR_LOGI("pid %{public}d lose focus. ret %{public}d", pid, ret); + isVideoApp_ = false; } else { CONCUR_LOGE("Invalid focus status %{public}d", status); } } +void TaskController::InteractionSceneProcess(int status) +{ + std::lock_guard lock(ddlPowerModeLock_); + if (ddlSceneSchedSwitch_) { + if (status == MSG_ENTER_INTERACTION_SCENE) { + DeadlinePerfMode(); + } else if (status == MSG_EXIT_INTERACTION_SCENE) { + if (isVideoApp_) { + return; + } + DeadlinePowerMode(); + } + } +} + +void TaskController::DeadlinePerfMode() +{ + if (ddlPowerModeEnable_) { + StartTrace(HITRACE_TAG_ACE, "Deadline perf mode"); + SetAppAndRenderServicRate(uniAppRate_, systemRate_); + ddlPowerModeEnable_ = false; + CONCUR_LOGI("Deadline switch to perf mode"); + FinishTrace(HITRACE_TAG_ACE); + } +} + +void TaskController::DeadlinePowerMode() +{ + if (!ddlPowerModeEnable_) { + StartTrace(HITRACE_TAG_ACE, "Deadline power mode"); + int appRate = uniAppRate_; + int rsRate = systemRate_; + if (configReader_) { + appRate = configReader_->GetDegratationFps(appRate); + rsRate = configReader_->GetDegratationFps(rsRate); + } + SetAppAndRenderServicRate(appRate, rsRate); + ddlPowerModeEnable_ = true; + CONCUR_LOGI("Deadline switch to power mode"); + FinishTrace(HITRACE_TAG_ACE); + } +} void TaskController::QueryDeadline(int queryItem, DeadlineReply& ddlReply, const Json::Value& payload) { pid_t uid = IPCSkeleton::GetInstance().GetCallingUid(); @@ -768,16 +836,19 @@ void TaskController::SetAppRate(const Json::Value& payload) { int rtgId = 0; int uiTid = 0; - int appRate = 0; - int uniAppRate = FindRateFromInfo(UNI_APP_RATE_ID, payload); - if (uniAppRate > 0) { - CONCUR_LOGD("set unified app rate %{public}d", uniAppRate); - bool ret = OHOS::system::SetParameter(INTERVAL_APP_RATE, std::to_string(uniAppRate)); + int appRate = FindRateFromInfo(UNI_APP_RATE_ID, payload); + if (appRate > 0 && appRate != uniAppRate_) { + CONCUR_LOGD("set unified app rate %{public}d", appRate); + uniAppRate_ = appRate; + if (ddlSceneSchedSwitch_ && ddlPowerModeEnable_ && configReader_) { + appRate = configReader_->GetDegratationFps(appRate); + } + bool ret = OHOS::system::SetParameter(INTERVAL_APP_RATE, std::to_string(appRate)); if (ret == false) { CONCUR_LOGI("set app rate param failed"); } StartTrace(HITRACE_TAG_ACE, - "SetAppRate:" + std::to_string(uniAppRate) + " ret:" + std::to_string(ret)); + "SetAppRate:" + std::to_string(appRate) + " ret:" + std::to_string(ret)); FinishTrace(HITRACE_TAG_ACE); return; } @@ -823,6 +894,9 @@ void TaskController::SetRenderServiceRate(const Json::Value& payload) rsRate, renderServiceMainGrpId_, systemRate_); SetFrameRate(renderServiceMainGrpId_, rsRate); systemRate_ = rsRate; + if (ddlSceneSchedSwitch_ && ddlPowerModeEnable_ && configReader_) { + rsRate = configReader_->GetDegratationFps(rsRate); + } bool ret = OHOS::system::SetParameter(INTERVAL_RS_RATE, std::to_string(rsRate)); if (ret == false) { CONCUR_LOGI("set rs rate param failed"); @@ -833,6 +907,25 @@ void TaskController::SetRenderServiceRate(const Json::Value& payload) } } +void TaskController::SetAppAndRenderServicRate(int appRate, int rsRate) +{ + bool ret = OHOS::system::SetParameter(INTERVAL_APP_RATE, std::to_string(appRate)); + if (ret == false) { + CONCUR_LOGI("set app rate param failed"); + } + StartTrace(HITRACE_TAG_ACE, + "SetAppRate:" + std::to_string(appRate) + " ret:" + std::to_string(ret)); + FinishTrace(HITRACE_TAG_ACE); + + ret = OHOS::system::SetParameter(INTERVAL_RS_RATE, std::to_string(rsRate)); + if (ret == false) { + CONCUR_LOGI("set rs rate param failed"); + } + StartTrace(HITRACE_TAG_ACE, + "SetRSRate:" + std::to_string(rsRate) + " ret:" + std::to_string(ret)); + FinishTrace(HITRACE_TAG_ACE); +} + bool TaskController::CheckJsonValid(const Json::Value& payload) { Json::ValueType type = payload.type(); @@ -890,6 +983,33 @@ int TaskController::CreateNewRtgGrp(int prioType, int rtNum) return ret; } +int TaskController::ParseAppType(const Json::Value& payload) +{ + int appType = APP_TYPE_INVALID; + if (payload.isMember("appType") && payload["appType"].isString()) { + try { + appType = stoi(payload["appType"].asString()); + } catch (...) { + CONCUR_LOGE("Unexpected apptype format"); + return APP_TYPE_INVALID; + } + } + return appType; +} + +bool TaskController::IsVideoApp(int pid) +{ + if (!ddlSceneSchedSwitch_ || appBundleName.find(pid) == appBundleName.end()) { + return false; + } + std::string bundleName = appBundleName[pid]; + if (appTypeCache_.find(bundleName) != appTypeCache_.end()) { + return appTypeCache_[bundleName] == APP_TYPE_VIDEO || + appTypeCache_[bundleName]== APP_TYPE_VIDEO_CLIP; + } + return false; +} + ForegroundAppRecord::ForegroundAppRecord(int pid, int uiTid, bool createGrp) { pid_ = pid; diff --git a/test/BUILD.gn b/test/BUILD.gn index 9c0a7e3fa192c87c4d4f1cb8b98cb725af680d0e..bbd856560d401388c7caab75cb78c3e545edb0f2 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -264,10 +264,8 @@ ohos_unittest("config_reader_test") { module_out_path = module_output_path configs = [ ":test_config" ] - sources = [ - "../common/src/config_reader.cpp", - "unittest/phone/config_reader_test.cpp", - ] + sources = [ "unittest/phone/config_reader_test.cpp" ] + deps = [ "../services:concurrentsvc" ] external_deps = [ "c_utils:utils", diff --git a/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp b/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp index fa8066f8a386b26038424e539f08702b0df35e57..75d4c25a45844c78d84c177a67eb0c154879fa3c 100644 --- a/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp +++ b/test/fuzztest/concurrent_fuzzer/concurrent_fuzzer.cpp @@ -816,7 +816,7 @@ bool FuzzTaskControllerNewAppStart(const uint8_t* data, size_t size) int pid = GetData(); int uid = GetData(); std::string bundleName = std::to_string(GetData()); - TaskController::GetInstance().NewAppStart(uid, pid, bundleName); + TaskController::GetInstance().NewAppStart(uid, pid, bundleName, -1); } return true; } diff --git a/test/unittest/phone/concurrent_task_controller_test.cpp b/test/unittest/phone/concurrent_task_controller_test.cpp index be2df456c41819d49f7e5a7ee7d2948282a0a9f2..19cc24514877550336fe7189940f07a26b8aa22c 100644 --- a/test/unittest/phone/concurrent_task_controller_test.cpp +++ b/test/unittest/phone/concurrent_task_controller_test.cpp @@ -236,7 +236,7 @@ HWTEST_F(ConcurrentTaskControllerTest, NewForegroundTest, TestSize.Level1) int tid = gettid(); fore.NewForeground(uid, tid); fore.NewBackground(uid, tid); - fore.NewAppStart(uid, tid, ""); + fore.NewAppStart(uid, tid, "", -1); fore.NewForeground(uid, tid); fore.NewBackground(uid, tid); fore.ContinuousTaskProcess(uid, tid, static_cast(MSG_CONTINUOUS_TASK_START)); @@ -251,7 +251,7 @@ HWTEST_F(ConcurrentTaskControllerTest, NewForegroundTest, TestSize.Level1) EXPECT_EQ(iter->GetPid(), tid); fore.NewForeground(uid, tid); fore.NewBackground(uid, tid); - fore.NewAppStart(uid, tid, ""); + fore.NewAppStart(uid, tid, "", -1); fore.NewForeground(uid, tid); fore.NewBackground(uid, tid); fore.ContinuousTaskProcess(uid, tid, static_cast(MSG_CONTINUOUS_TASK_END));