1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "res_sched_util.h" 17 18#include <string> 19 20#include "ability_info.h" 21#include "ui_extension_utils.h" 22#include "hilog_tag_wrapper.h" 23#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 24#include "res_sched_client.h" 25#include "res_type.h" 26#endif 27 28namespace OHOS { 29namespace AAFwk { 30using AssociatedStartType = ResourceSchedule::ResType::AssociatedStartType; 31ResSchedUtil &ResSchedUtil::GetInstance() 32{ 33 static ResSchedUtil instance; 34 return instance; 35} 36 37int64_t ResSchedUtil::convertType(int64_t resSchedType) 38{ 39#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 40 if (resSchedType == RES_TYPE_SCB_START_ABILITY) { 41 return static_cast<int64_t>(AssociatedStartType::SCB_START_ABILITY); 42 } else if (resSchedType == RES_TYPE_EXTENSION_START_ABILITY) { 43 return static_cast<int64_t>(AssociatedStartType::EXTENSION_START_ABILITY); 44 } else if (resSchedType == RES_TYPE_MISSION_LIST_START_ABILITY) { 45 return static_cast<int64_t>(AssociatedStartType::MISSION_LIST_START_ABILITY); 46 } 47#endif 48 TAG_LOGE(AAFwkTag::DEFAULT, "sched invalid"); 49 return -1; 50} 51 52void ResSchedUtil::ReportAbilityStartInfoToRSS(const AbilityInfo &abilityInfo, int32_t pid, bool isColdStart) 53{ 54#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 55 uint32_t resType = ResourceSchedule::ResType::RES_TYPE_APP_ABILITY_START; 56 std::unordered_map<std::string, std::string> eventParams { 57 { "name", "ability_start" }, 58 { "uid", std::to_string(abilityInfo.applicationInfo.uid) }, 59 { "bundleName", abilityInfo.applicationInfo.bundleName }, 60 { "abilityName", abilityInfo.name }, 61 { "pid", std::to_string(pid) } 62 }; 63 TAG_LOGD(AAFwkTag::DEFAULT, "call"); 64 ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, isColdStart ? 1 : 0, eventParams); 65#endif 66} 67 68void ResSchedUtil::ReportAbilityAssociatedStartInfoToRSS( 69 const AbilityInfo &abilityInfo, int64_t resSchedType, int32_t callerUid, int32_t callerPid) 70{ 71#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 72 uint32_t resType = ResourceSchedule::ResType::RES_TYPE_APP_ASSOCIATED_START; 73 std::unordered_map<std::string, std::string> eventParams { 74 { "name", "associated_start" }, 75 { "caller_uid", std::to_string(callerUid) }, 76 { "caller_pid", std::to_string(callerPid) }, 77 { "callee_uid", std::to_string(abilityInfo.applicationInfo.uid) }, 78 { "callee_bundle_name", abilityInfo.applicationInfo.bundleName } 79 }; 80 int64_t type = convertType(resSchedType); 81 TAG_LOGD(AAFwkTag::DEFAULT, "call"); 82 ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, type, eventParams); 83#endif 84} 85 86std::string ResSchedUtil::GetThawReasonByAbilityType(const AbilityInfo &abilityInfo) 87{ 88 std::string reason; 89 if (abilityInfo.type == AppExecFwk::AbilityType::PAGE) { 90 reason = "THAW_BY_START_PAGE_ABILITY"; 91 } else if (abilityInfo.type == AppExecFwk::AbilityType::EXTENSION && 92 abilityInfo.extensionAbilityType == AppExecFwk::ExtensionAbilityType::SERVICE) { 93 reason = "THAW_BY_START_SERVICE_EXTENSION"; 94 } else if (abilityInfo.type == AppExecFwk::AbilityType::EXTENSION && 95 AAFwk::UIExtensionUtils::IsUIExtension(abilityInfo.extensionAbilityType)) { 96 reason = "THAW_BY_START_UI_EXTENSION"; 97 } else { 98 reason = "THAW_BY_START_NOT_PAGE_ABILITY"; 99 } 100 return reason; 101} 102 103void ResSchedUtil::ReportEventToRSS(const int32_t uid, const std::string &bundleName, const std::string &reason, 104 const int32_t pid, const int32_t callerPid) 105{ 106#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 107 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_THAW_ONE_APP; 108 nlohmann::json payload; 109 payload.emplace("uid", uid); 110 payload.emplace("pid", pid); 111 payload.emplace("bundleName", bundleName); 112 payload.emplace("reason", reason); 113 payload.emplace("callerPid", callerPid); 114 nlohmann::json reply; 115 TAG_LOGD(AAFwkTag::DEFAULT, "call"); 116 ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply); 117#endif 118} 119 120void ResSchedUtil::GetAllFrozenPidsFromRSS(std::unordered_set<int32_t> &frozenPids) 121{ 122#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 123 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_GET_ALL_SUSPEND_STATE; 124 nlohmann::json payload; 125 nlohmann::json reply; 126 TAG_LOGD(AAFwkTag::DEFAULT, "call"); 127 int32_t ret = ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply); 128 if (ret != 0 || !reply.contains("allSuspendState") || !reply["allSuspendState"].is_array()) { 129 TAG_LOGE(AAFwkTag::DEFAULT, "ReportSyncEvent fail"); 130 return; 131 } 132 133 for (nlohmann::json &appObj : reply["allSuspendState"]) { 134 // Here can get uid if needed 135 if (!appObj.contains("pidsState") || !appObj["pidsState"].is_array()) { 136 continue; 137 } 138 139 for (nlohmann::json &pidObj : appObj["pidsState"]) { 140 if (!pidObj.contains("pid") || !pidObj["pid"].is_number() || 141 !pidObj.contains("isFrozen") || !pidObj["isFrozen"].is_boolean()) { 142 break; 143 } 144 int32_t pid = pidObj["pid"].get<int32_t>(); 145 bool isFrozen = pidObj["isFrozen"].get<bool>(); 146 if (isFrozen) { 147 frozenPids.insert(pid); 148 } 149 } 150 } 151 if (frozenPids.empty()) { 152 TAG_LOGW(AAFwkTag::DEFAULT, "empty frozen pids"); 153 } 154#endif 155} 156 157bool ResSchedUtil::CheckShouldForceKillProcess(int32_t pid) 158{ 159#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 160 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_SHOULD_FORCE_KILL_PROCESS; 161 nlohmann::json payload; 162 nlohmann::json reply; 163 payload.emplace("pid", pid); 164 ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply); 165 if (!reply.contains("ShouldForceKillProcess") || !reply["ShouldForceKillProcess"].is_number_integer()) { 166 return true; 167 } 168 return reply["ShouldForceKillProcess"].get<int32_t>() == 1; 169#else 170 return true; 171#endif 172} 173 174void ResSchedUtil::ReportLoadingEventToRss(LoadingStage stage, int32_t pid, int32_t uid, int64_t timeDuration) 175{ 176#ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE 177 uint32_t resType = ResourceSchedule::ResType::RES_TYPE_KEY_PERF_SCENE; 178 std::unordered_map<std::string, std::string> eventParams { 179 { "extType", "10015"}, 180 { "pid", std::to_string(pid) }, 181 { "uid", std::to_string(uid) }, 182 }; 183 if (timeDuration > 0) { // millisecond 184 eventParams.emplace("timeoutDuration", std::to_string(timeDuration)); 185 } 186 int64_t type = static_cast<int64_t>(stage); 187 TAG_LOGD(AAFwkTag::DEFAULT, "call"); 188 ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, type, eventParams); 189#endif 190} 191} // namespace AAFwk 192} // namespace OHOS