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 "hilog_tag_wrapper.h"
22 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
23 #include "res_sched_client.h"
24 #include "res_type.h"
25 #endif
26
27 namespace OHOS {
28 namespace AAFwk {
29 using AssociatedStartType = ResourceSchedule::ResType::AssociatedStartType;
GetInstance()30 ResSchedUtil &ResSchedUtil::GetInstance()
31 {
32 static ResSchedUtil instance;
33 return instance;
34 }
35
convertType(int64_t resSchedType)36 int64_t ResSchedUtil::convertType(int64_t resSchedType)
37 {
38 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
39 if (resSchedType == RES_TYPE_SCB_START_ABILITY) {
40 return static_cast<int64_t>(AssociatedStartType::SCB_START_ABILITY);
41 } else if (resSchedType == RES_TYPE_EXTENSION_START_ABILITY) {
42 return static_cast<int64_t>(AssociatedStartType::EXTENSION_START_ABILITY);
43 } else if (resSchedType == RES_TYPE_MISSION_LIST_START_ABILITY) {
44 return static_cast<int64_t>(AssociatedStartType::MISSION_LIST_START_ABILITY);
45 }
46 #endif
47 TAG_LOGE(AAFwkTag::DEFAULT, "sched invalid");
48 return -1;
49 }
50
ReportAbilityStartInfoToRSS(const AbilityInfo & abilityInfo,int32_t pid,bool isColdStart)51 void ResSchedUtil::ReportAbilityStartInfoToRSS(const AbilityInfo &abilityInfo, int32_t pid, bool isColdStart)
52 {
53 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
54 uint32_t resType = ResourceSchedule::ResType::RES_TYPE_APP_ABILITY_START;
55 std::unordered_map<std::string, std::string> eventParams {
56 { "name", "ability_start" },
57 { "uid", std::to_string(abilityInfo.applicationInfo.uid) },
58 { "bundleName", abilityInfo.applicationInfo.bundleName },
59 { "abilityName", abilityInfo.name },
60 { "pid", std::to_string(pid) }
61 };
62 TAG_LOGD(AAFwkTag::DEFAULT, "call");
63 ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, isColdStart ? 1 : 0, eventParams);
64 #endif
65 }
66
ReportAbilityAssociatedStartInfoToRSS(const AbilityInfo & abilityInfo,int64_t resSchedType,int32_t callerUid,int32_t callerPid)67 void ResSchedUtil::ReportAbilityAssociatedStartInfoToRSS(
68 const AbilityInfo &abilityInfo, int64_t resSchedType, int32_t callerUid, int32_t callerPid)
69 {
70 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
71 uint32_t resType = ResourceSchedule::ResType::RES_TYPE_APP_ASSOCIATED_START;
72 std::unordered_map<std::string, std::string> eventParams {
73 { "name", "associated_start" },
74 { "caller_uid", std::to_string(callerUid) },
75 { "caller_pid", std::to_string(callerPid) },
76 { "callee_uid", std::to_string(abilityInfo.applicationInfo.uid) },
77 { "callee_bundle_name", abilityInfo.applicationInfo.bundleName }
78 };
79 int64_t type = convertType(resSchedType);
80 TAG_LOGD(AAFwkTag::DEFAULT, "call");
81 ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, type, eventParams);
82 #endif
83 }
84
ReportEventToRSS(const int32_t uid,const std::string & bundleName,const std::string & reason,const int32_t callerPid)85 void ResSchedUtil::ReportEventToRSS(const int32_t uid, const std::string &bundleName, const std::string &reason,
86 const int32_t callerPid)
87 {
88 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
89 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_THAW_ONE_APP;
90 nlohmann::json payload;
91 payload.emplace("uid", uid);
92 payload.emplace("pid", -1);
93 payload.emplace("bundleName", bundleName);
94 payload.emplace("reason", reason);
95 payload.emplace("callerPid", callerPid);
96 nlohmann::json reply;
97 TAG_LOGD(AAFwkTag::DEFAULT, "call");
98 ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply);
99 #endif
100 }
101
GetAllFrozenPidsFromRSS(std::unordered_set<int32_t> & frozenPids)102 void ResSchedUtil::GetAllFrozenPidsFromRSS(std::unordered_set<int32_t> &frozenPids)
103 {
104 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
105 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_GET_ALL_SUSPEND_STATE;
106 nlohmann::json payload;
107 nlohmann::json reply;
108 TAG_LOGD(AAFwkTag::DEFAULT, "call");
109 int32_t ret = ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply);
110 if (ret != 0 || !reply.contains("allSuspendState") || !reply["allSuspendState"].is_array()) {
111 TAG_LOGE(AAFwkTag::DEFAULT, "ReportSyncEvent fail");
112 return;
113 }
114
115 for (nlohmann::json &appObj : reply["allSuspendState"]) {
116 // Here can get uid if needed
117 if (!appObj.contains("pidsState") || !appObj["pidsState"].is_array()) {
118 continue;
119 }
120
121 for (nlohmann::json &pidObj : appObj["pidsState"]) {
122 if (!pidObj.contains("pid") || !pidObj["pid"].is_number() ||
123 !pidObj.contains("isFrozen") || !pidObj["isFrozen"].is_boolean()) {
124 break;
125 }
126 int32_t pid = pidObj["pid"].get<int32_t>();
127 bool isFrozen = pidObj["isFrozen"].get<bool>();
128 if (isFrozen) {
129 frozenPids.insert(pid);
130 }
131 }
132 }
133 if (frozenPids.empty()) {
134 TAG_LOGW(AAFwkTag::DEFAULT, "Get frozen pids empty");
135 }
136 #endif
137 }
138
CheckShouldForceKillProcess(int32_t pid)139 bool ResSchedUtil::CheckShouldForceKillProcess(int32_t pid)
140 {
141 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
142 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_SHOULD_FORCE_KILL_PROCESS;
143 nlohmann::json payload;
144 nlohmann::json reply;
145 payload.emplace("pid", pid);
146 ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply);
147 if (!reply.contains("ShouldForceKillProcess") || !reply["ShouldForceKillProcess"].is_number_integer()) {
148 return true;
149 }
150 return reply["ShouldForceKillProcess"].get<int32_t>() == 1;
151 #else
152 return true;
153 #endif
154 }
155
ReportLoadingEventToRss(LoadingStage stage,int32_t pid,int32_t uid,int64_t timeDuration,int64_t abilityRecordId)156 void ResSchedUtil::ReportLoadingEventToRss(LoadingStage stage, int32_t pid, int32_t uid,
157 int64_t timeDuration, int64_t abilityRecordId)
158 {
159 #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE
160 uint32_t resType = ResourceSchedule::ResType::RES_TYPE_KEY_PERF_SCENE;
161 std::unordered_map<std::string, std::string> eventParams {
162 { "extType", "10015"},
163 { "pid", std::to_string(pid) },
164 { "uid", std::to_string(uid) },
165 };
166 if (timeDuration > 0) { // millisecond
167 eventParams.emplace("timeoutDuration", std::to_string(timeDuration));
168 }
169 if (abilityRecordId > 0) {
170 eventParams.emplace("abilityRecordId", std::to_string(abilityRecordId));
171 }
172
173 int64_t type = static_cast<int64_t>(stage);
174 TAG_LOGD(AAFwkTag::DEFAULT, "call");
175 ResourceSchedule::ResSchedClient::GetInstance().ReportData(resType, type, eventParams);
176 #endif
177 }
178
GetNWebPreloadSet() const179 std::unordered_set<std::string> ResSchedUtil::GetNWebPreloadSet() const
180 {
181 uint32_t resType = ResourceSchedule::ResType::SYNC_RES_TYPE_GET_NWEB_PRELOAD_SET;
182 nlohmann::json payload;
183 nlohmann::json reply;
184 ResourceSchedule::ResSchedClient::GetInstance().ReportSyncEvent(resType, 0, payload, reply);
185 if (!reply.contains("NWebPreloadSet")) {
186 TAG_LOGW(AAFwkTag::DEFAULT, "does not get preload process set");
187 return {};
188 }
189 auto jsonObj = reply["NWebPreloadSet"];
190 return { jsonObj.begin(), jsonObj.end() };
191 }
192 } // namespace AAFwk
193 } // namespace OHOS