• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 <cstdint>
17 #include <dlfcn.h>
18 #include "res_sched_service.h"
19 #include <file_ex.h>
20 #include <parameters.h>
21 #include <string_ex.h>
22 #include "accesstoken_kit.h"
23 #include "ipc_skeleton.h"
24 #include "notifier_mgr.h"
25 #include "plugin_mgr.h"
26 #include "res_sched_errors.h"
27 #include "res_sched_exe_client.h"
28 #include "res_sched_log.h"
29 #include "res_sched_mgr.h"
30 #include "tokenid_kit.h"
31 #include "sched_controller.h"
32 #include "supervisor.h"
33 #include "ressched_utils.h"
34 #include "event_listener_mgr.h"
35 
36 namespace OHOS {
37 namespace ResourceSchedule {
38 using namespace OHOS::Security;
39 namespace {
40     constexpr int32_t DUMP_OPTION = 0;
41     constexpr int32_t DUMP_PARAM_INDEX = 1;
42     const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
43     const std::string APP_PRELOAD_PLIGIN_NAME = "libapp_preload_plugin.z.so";
44 }
45 
ReportData(uint32_t resType,int64_t value,const nlohmann::json & payload)46 void ResSchedService::ReportData(uint32_t resType, int64_t value, const nlohmann::json& payload)
47 {
48     int32_t clientPid = IPCSkeleton::GetCallingPid();
49     RESSCHED_LOGD("ResSchedService receive data from ipc resType: %{public}u, value: %{public}lld, pid: %{public}d",
50                   resType, (long long)value, clientPid);
51     const nlohmann::json* payloadP = &payload;
52     int32_t callingUid = IPCSkeleton::GetCallingUid();
53     nlohmann::json* payloadM = const_cast<nlohmann::json*>(payloadP);
54     (*payloadM)["callingUid"] = std::to_string(callingUid);
55     (*payloadM)["clientPid"] = std::to_string(clientPid);
56     ResSchedMgr::GetInstance().ReportData(resType, value, *payloadM);
57 }
58 
ReportSyncEvent(const uint32_t resType,const int64_t value,const nlohmann::json & payload,nlohmann::json & reply)59 int32_t ResSchedService::ReportSyncEvent(const uint32_t resType, const int64_t value, const nlohmann::json& payload,
60     nlohmann::json& reply)
61 {
62     return PluginMgr::GetInstance().DeliverResource(std::make_shared<ResData>(resType, value, payload, reply));
63 }
64 
KillProcess(const nlohmann::json & payload)65 int32_t ResSchedService::KillProcess(const nlohmann::json& payload)
66 {
67     return ResSchedMgr::GetInstance().KillProcessByClient(payload);
68 }
69 
RegisterSystemloadNotifier(const sptr<IRemoteObject> & notifier)70 void ResSchedService::RegisterSystemloadNotifier(const sptr<IRemoteObject>& notifier)
71 {
72     NotifierMgr::GetInstance().RegisterNotifier(IPCSkeleton::GetCallingPid(), notifier);
73 }
74 
UnRegisterSystemloadNotifier()75 void ResSchedService::UnRegisterSystemloadNotifier()
76 {
77     NotifierMgr::GetInstance().UnRegisterNotifier(IPCSkeleton::GetCallingPid());
78 }
79 
RegisterEventListener(const sptr<IRemoteObject> & eventListener,uint32_t eventType,uint32_t listenerGroup)80 void ResSchedService::RegisterEventListener(const sptr<IRemoteObject>& eventListener, uint32_t eventType,
81     uint32_t listenerGroup)
82 {
83     EventListenerMgr::GetInstance().RegisterEventListener(IPCSkeleton::GetCallingPid(), eventListener, eventType,
84         listenerGroup);
85 }
86 
UnRegisterEventListener(uint32_t eventType,uint32_t listenerGroup)87 void ResSchedService::UnRegisterEventListener(uint32_t eventType, uint32_t listenerGroup)
88 {
89     EventListenerMgr::GetInstance().UnRegisterEventListener(IPCSkeleton::GetCallingPid(), eventType, listenerGroup);
90 }
91 
GetSystemloadLevel()92 int32_t ResSchedService::GetSystemloadLevel()
93 {
94     return NotifierMgr::GetInstance().GetSystemloadLevel();
95 }
96 
OnDeviceLevelChanged(int32_t type,int32_t level)97 void ResSchedService::OnDeviceLevelChanged(int32_t type, int32_t level)
98 {
99     NotifierMgr::GetInstance().OnDeviceLevelChanged(type, level);
100     nlohmann::json payload;
101     payload["systemloadLevel"] = std::to_string(level);
102     ResSchedUtils::GetInstance().ReportDataInProcess(type, level, payload);
103 }
104 
IsAllowedAppPreload(const std::string & bundleName,int32_t preloadMode)105 bool ResSchedService::IsAllowedAppPreload(const std::string& bundleName, int32_t preloadMode)
106 {
107     LoadAppPreloadPlugin();
108     if (!appPreloadFunc_) {
109         RESSCHED_LOGE("%{public}s, no allow AppPreload !", __func__, errno);
110         return false;
111     }
112     return appPreloadFunc_(bundleName, preloadMode);
113 }
114 
LoadAppPreloadPlugin()115 void ResSchedService::LoadAppPreloadPlugin()
116 {
117     std::shared_ptr<PluginLib> libInfoPtr = PluginMgr::GetInstance().GetPluginLib(APP_PRELOAD_PLIGIN_NAME);
118     if (libInfoPtr == nullptr) {
119         RESSCHED_LOGE("ResSchedService::LoadAppPreloadPlugin libInfoPtr nullptr");
120         isLoadAppPreloadPlugin_ = false;
121         return;
122     }
123 
124     if (isLoadAppPreloadPlugin_) {
125         RESSCHED_LOGI("ResSchedService::LoadAppPreloadPlugin, already loaded AppPreloadPlugin");
126         return;
127     }
128 
129     appPreloadFunc_ = reinterpret_cast<OnIsAllowedAppPreloadFunc>(dlsym(libInfoPtr->handle.get(),
130         "OnIsAllowedAppPreload"));
131     isLoadAppPreloadPlugin_ = true;
132 }
133 
AllowDump()134 bool ResSchedService::AllowDump()
135 {
136     if (ENG_MODE == 0) {
137         RESSCHED_LOGE("Not eng mode");
138         return false;
139     }
140     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
141     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP");
142     if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
143         RESSCHED_LOGE("CheckPermission failed");
144         return false;
145     }
146     return true;
147 }
148 
Dump(int32_t fd,const std::vector<std::u16string> & args)149 int32_t ResSchedService::Dump(int32_t fd, const std::vector<std::u16string>& args)
150 {
151     if (!AllowDump()) {
152         return ERR_RES_SCHED_PERMISSION_DENIED;
153     }
154     RESSCHED_LOGI("%{public}s Dump service.", __func__);
155     std::vector<std::string> argsInStr;
156     std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
157         [](const std::u16string &arg) {
158         std::string ret = Str16ToStr8(arg);
159         RESSCHED_LOGI("%{public}s arg: %{public}s.", __func__, ret.c_str());
160         return ret;
161     });
162     std::string result;
163     if (argsInStr.size() == 0) {
164         // hidumper -s said '-h'
165         DumpUsage(result);
166     } else if (argsInStr.size() == DUMP_OPTION + 1) {
167         // hidumper -s said '-h' or hidumper -s said '-a'
168         DumpExt(argsInStr, result);
169     } else if (argsInStr.size() >= DUMP_PARAM_INDEX + 1) {
170         if (argsInStr[DUMP_OPTION] == "-p") {
171             std::vector<std::string> argsInStrToPlugin;
172             argsInStrToPlugin.assign(argsInStr.begin() + DUMP_PARAM_INDEX + 1, argsInStr.end());
173             PluginMgr::GetInstance().DumpOnePlugin(result, argsInStr[DUMP_PARAM_INDEX], argsInStrToPlugin);
174         } else if (argsInStr[DUMP_OPTION] == "sendDebugToExecutor") {
175             DumpExecutorDebugCommand(argsInStr, result);
176         }
177     }
178 
179     if (!SaveStringToFd(fd, result)) {
180         RESSCHED_LOGE("%{public}s save to fd failed.", __func__);
181     }
182     return ERR_OK;
183 }
184 
185 
DumpExt(const std::vector<std::string> & argsInStr,std::string & result)186 void ResSchedService::DumpExt(const std::vector<std::string>& argsInStr, std::string &result)
187 {
188     if (argsInStr[DUMP_OPTION] == "-h") {
189         DumpUsage(result);
190     } else if (argsInStr[DUMP_OPTION] == "-a") {
191         DumpAllInfo(result);
192     } else if (argsInStr[DUMP_OPTION] == "-p") {
193         PluginMgr::GetInstance().DumpAllPlugin(result);
194     } else if (argsInStr[DUMP_OPTION] == "getRunningLockInfo") {
195         DumpProcessRunningLock(result);
196     } else if (argsInStr[DUMP_OPTION] == "getProcessEventInfo") {
197         DumpProcessEventState(result);
198     } else if (argsInStr[DUMP_OPTION] == "getProcessWindowInfo") {
199         DumpProcessWindowInfo(result);
200     } else if (argsInStr[DUMP_OPTION] == "getSystemloadInfo") {
201         DumpSystemLoadInfo(result);
202     } else if (argsInStr[DUMP_OPTION] == "sendDebugToExecutor") {
203         DumpExecutorDebugCommand(argsInStr, result);
204     } else if (argsInStr[DUMP_OPTION] == "PluginConfig") {
205         DumpAllPluginConfig(result);
206     } else {
207         result.append("Error params.");
208     }
209 }
210 
DumpProcessRunningLock(std::string & result)211 void ResSchedService::DumpProcessRunningLock(std::string &result)
212 {
213     auto supervisor = SchedController::GetInstance().GetSupervisor();
214     if (supervisor == nullptr) {
215         result.append("get supervisor failed");
216         return;
217     }
218 
219     std::map<int32_t, std::shared_ptr<Application>> uidMap = supervisor->GetUidsMap();
220     for (auto it = uidMap.begin(); it != uidMap.end(); it++) {
221         int32_t uid = it->first;
222         std::shared_ptr<Application> app = it->second;
223         std::map<pid_t, std::shared_ptr<ProcessRecord>> pidMap = app->GetPidsMap();
224         for (auto pidIt = pidMap.begin(); pidIt != pidMap.end(); pidIt++) {
225             int32_t pid = pidIt->first;
226             std::shared_ptr<ProcessRecord> process = pidIt->second;
227             for (auto lockIt = process->runningLockState_.begin();
228                 lockIt != process->runningLockState_.end(); lockIt++) {
229                 uint32_t lockType = lockIt->first;
230                 bool lockState = lockIt->second;
231                 result.append("uid:").append(ToString(uid))
232                     .append(", pid:").append(ToString(pid))
233                     .append(", lockType:").append(ToString(lockType))
234                     .append(", lockState:").append(ToString(lockState)).append("\n");
235             }
236         }
237     }
238 }
239 
DumpProcessWindowInfo(std::string & result)240 void ResSchedService::DumpProcessWindowInfo(std::string &result)
241 {
242     auto supervisor = SchedController::GetInstance().GetSupervisor();
243     if (supervisor == nullptr) {
244         result.append("get supervisor failed");
245         return;
246     }
247 
248     std::map<int32_t, std::shared_ptr<Application>> uidMap = supervisor->GetUidsMap();
249     for (auto it = uidMap.begin(); it != uidMap.end(); it++) {
250         int32_t uid = it->first;
251         std::shared_ptr<Application> app = it->second;
252         std::map<pid_t, std::shared_ptr<ProcessRecord>> pidMap = app->GetPidsMap();
253         std::string bundleName = app->GetName();
254         for (auto pidIt = pidMap.begin(); pidIt != pidMap.end(); pidIt++) {
255             int32_t pid = pidIt->first;
256             std::shared_ptr<ProcessRecord> process = pidIt->second;
257             if (process->windows_.size() == 0) {
258                 continue;
259             }
260             result.append("uid:").append(ToString(uid))
261                 .append(", pid:").append(ToString(pid))
262                 .append(", bundleName:").append(bundleName)
263                 .append(", processDrawingState:").append(ToString(process->processDrawingState_))
264                 .append(", windowInfo:").append("\n");
265             for (auto &windows : process->windows_) {
266                 result.append("    windowId:").append(ToString(windows->windowId_))
267                     .append(", visibilityState:").append(ToString(windows->visibilityState_))
268                     .append(", isVisible:").append(ToString(windows->isVisible_))
269                     .append(", isFocus:").append(ToString(windows->isFocused_))
270                     .append(", topWebRenderUid:").append(ToString(windows->topWebviewRenderUid_))
271                     .append("\n");
272             }
273         }
274     }
275 }
276 
DumpProcessEventState(std::string & result)277 void ResSchedService::DumpProcessEventState(std::string &result)
278 {
279     auto supervisor = SchedController::GetInstance().GetSupervisor();
280     if (supervisor == nullptr) {
281         result.append("get supervisor failed");
282         return;
283     }
284 
285     std::map<int32_t, std::shared_ptr<Application>> uidMap = supervisor->GetUidsMap();
286     for (auto it = uidMap.begin(); it != uidMap.end(); it++) {
287         int32_t uid = it->first;
288         std::shared_ptr<Application> app = it->second;
289         std::map<pid_t, std::shared_ptr<ProcessRecord>> pidMap = app->GetPidsMap();
290         for (auto pidIt = pidMap.begin(); pidIt != pidMap.end(); pidIt++) {
291             int32_t pid = pidIt->first;
292             std::shared_ptr<ProcessRecord> process = pidIt->second;
293             result.append("uid:").append(ToString(uid))
294                 .append(", pid:").append(ToString(pid))
295                 .append(", processState:").append(ToString(process->processState_))
296                 .append(", napState:").append(ToString(process->isNapState_))
297                 .append(", processDrawingState:").append(ToString(process->processDrawingState_))
298                 .append(", mmiState:").append(ToString(process->mmiStatus_))
299                 .append(", camearaStatus:").append(ToString(process->cameraState_))
300                 .append(", bluetoothStatus:").append(ToString(process->bluetoothState_))
301                 .append(", wifiStatus:").append(ToString(process->wifiState_))
302                 .append(", screenCaptureState:").append(ToString(process->screenCaptureState_))
303                 .append(", videoState:").append(ToString(process->videoState_))
304                 .append(", audioPlayingState:").append(ToString(process->audioPlayingState_))
305                 .append(", isActive:").append(ToString(process->isActive_))
306                 .append(", linkedWindowId:").append(ToString(process->linkedWindowId_))
307                 .append("\n");
308         }
309     }
310 }
311 
DumpSystemLoadInfo(std::string & result)312 void ResSchedService::DumpSystemLoadInfo(std::string &result)
313 {
314     result.append("systemloadLevel:")
315         .append(ToString(NotifierMgr::GetInstance().GetSystemloadLevel()))
316         .append("\n");
317     auto notifierInfo = NotifierMgr::GetInstance().DumpRegisterInfo();
318     std::string native("natives:");
319     std::string hap("apps:");
320     for (auto& info : notifierInfo) {
321         std::string str = ToString(info.first).append(" ");
322         if (info.second) {
323             hap.append(str);
324         } else {
325             native.append(str);
326         }
327     }
328     hap.append("\n");
329     native.append("\n");
330     result.append(native).append(hap);
331 }
332 
DumpUsage(std::string & result)333 void ResSchedService::DumpUsage(std::string &result)
334 {
335     result.append("usage: resource schedule service dump [<options>]\n")
336         .append("    -h: show the help.\n")
337         .append("    -a: show all info.\n")
338         .append("    -p: show the all plugin info.\n")
339         .append("    -p (plugin name): show one plugin info.\n");
340     PluginMgr::GetInstance().DumpHelpFromPlugin(result);
341 }
342 
DumpAllInfo(std::string & result)343 void ResSchedService::DumpAllInfo(std::string &result)
344 {
345     result.append("================Resource Schedule Service Infos================\n");
346     PluginMgr::GetInstance().DumpAllPlugin(result);
347 }
348 
DumpExecutorDebugCommand(const std::vector<std::string> & args,std::string & result)349 void ResSchedService::DumpExecutorDebugCommand(const std::vector<std::string>& args, std::string& result)
350 {
351     // hidumper -s said 'sendDebugToExecutor [isSync times]' isSync - 0/1(default 0), times - 1~...(default 1)
352     result.append("Send debug command to resource_schedule_executor.\n");
353     bool isSync = true;
354     int times = 1;
355     if (args.size() > DUMP_PARAM_INDEX + 1) {
356         int arg = atoi(args[DUMP_PARAM_INDEX + 1].c_str());
357         times = arg > 0 ? arg : times;
358     }
359     if (args.size() > DUMP_PARAM_INDEX) {
360         isSync = atoi(args[DUMP_PARAM_INDEX].c_str()) == 0;
361     }
362     uint32_t internal = 200;
363     for (int i = 0; i < times; i++) {
364         ResSchedExeClient::GetInstance().SendDebugCommand(isSync);
365         usleep(internal);
366     }
367 }
368 
DumpAllPluginConfig(std::string & result)369 void ResSchedService::DumpAllPluginConfig(std::string &result)
370 {
371     result.append("================Resource Schedule Plugin Config================\n");
372     PluginMgr::GetInstance().DumpAllPluginConfig(result);
373 }
374 } // namespace ResourceSchedule
375 } // namespace OHOS
376 
377