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 "event_listener_mgr.h"
32
33 namespace OHOS {
34 namespace ResourceSchedule {
35 using namespace OHOS::Security;
36 namespace {
37 constexpr int32_t DUMP_OPTION = 0;
38 constexpr int32_t DUMP_PARAM_INDEX = 1;
39 const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
40 const std::string APP_PRELOAD_PLIGIN_NAME = "libapp_preload_plugin.z.so";
41 }
42
ReportData(uint32_t resType, int64_t value, const nlohmann::json& payload)43 void ResSchedService::ReportData(uint32_t resType, int64_t value, const nlohmann::json& payload)
44 {
45 int32_t clientPid = IPCSkeleton::GetCallingPid();
46 RESSCHED_LOGD("ResSchedService receive data from ipc resType: %{public}u, value: %{public}lld, pid: %{public}d",
47 resType, (long long)value, clientPid);
48 const nlohmann::json* payloadP = &payload;
49 int32_t callingUid = IPCSkeleton::GetCallingUid();
50 nlohmann::json* payloadM = const_cast<nlohmann::json*>(payloadP);
51 (*payloadM)["callingUid"] = std::to_string(callingUid);
52 (*payloadM)["clientPid"] = std::to_string(clientPid);
53 ResSchedMgr::GetInstance().ReportData(resType, value, *payloadM);
54 }
55
ReportSyncEvent(const uint32_t resType, const int64_t value, const nlohmann::json& payload, nlohmann::json& reply)56 int32_t ResSchedService::ReportSyncEvent(const uint32_t resType, const int64_t value, const nlohmann::json& payload,
57 nlohmann::json& reply)
58 {
59 return PluginMgr::GetInstance().DeliverResource(std::make_shared<ResData>(resType, value, payload, reply));
60 }
61
KillProcess(const nlohmann::json& payload)62 int32_t ResSchedService::KillProcess(const nlohmann::json& payload)
63 {
64 return ResSchedMgr::GetInstance().KillProcessByClient(payload);
65 }
66
RegisterSystemloadNotifier(const sptr<IRemoteObject>& notifier)67 void ResSchedService::RegisterSystemloadNotifier(const sptr<IRemoteObject>& notifier)
68 {
69 NotifierMgr::GetInstance().RegisterNotifier(IPCSkeleton::GetCallingPid(), notifier);
70 }
71
UnRegisterSystemloadNotifier()72 void ResSchedService::UnRegisterSystemloadNotifier()
73 {
74 NotifierMgr::GetInstance().UnRegisterNotifier(IPCSkeleton::GetCallingPid());
75 }
76
RegisterEventListener(const sptr<IRemoteObject>& eventListener, uint32_t eventType, uint32_t listenerGroup)77 void ResSchedService::RegisterEventListener(const sptr<IRemoteObject>& eventListener, uint32_t eventType,
78 uint32_t listenerGroup)
79 {
80 EventListenerMgr::GetInstance().RegisterEventListener(IPCSkeleton::GetCallingPid(), eventListener, eventType,
81 listenerGroup);
82 }
83
UnRegisterEventListener(uint32_t eventType, uint32_t listenerGroup)84 void ResSchedService::UnRegisterEventListener(uint32_t eventType, uint32_t listenerGroup)
85 {
86 EventListenerMgr::GetInstance().UnRegisterEventListener(IPCSkeleton::GetCallingPid(), eventType, listenerGroup);
87 }
88
GetSystemloadLevel()89 int32_t ResSchedService::GetSystemloadLevel()
90 {
91 return NotifierMgr::GetInstance().GetSystemloadLevel();
92 }
93
OnDeviceLevelChanged(int32_t type, int32_t level)94 void ResSchedService::OnDeviceLevelChanged(int32_t type, int32_t level)
95 {
96 NotifierMgr::GetInstance().OnDeviceLevelChanged(type, level);
97 }
98
IsAllowedAppPreload(const std::string& bundleName, int32_t preloadMode)99 bool ResSchedService::IsAllowedAppPreload(const std::string& bundleName, int32_t preloadMode)
100 {
101 LoadAppPreloadPlugin();
102 if (!appPreloadFunc_) {
103 RESSCHED_LOGE("%{public}s, no allow AppPreload !", __func__, errno);
104 return false;
105 }
106 return appPreloadFunc_(bundleName, preloadMode);
107 }
108
LoadAppPreloadPlugin()109 void ResSchedService::LoadAppPreloadPlugin()
110 {
111 std::shared_ptr<PluginLib> libInfoPtr = PluginMgr::GetInstance().GetPluginLib(APP_PRELOAD_PLIGIN_NAME);
112 if (libInfoPtr == nullptr) {
113 RESSCHED_LOGE("ResSchedService::LoadAppPreloadPlugin libInfoPtr nullptr");
114 isLoadAppPreloadPlugin_ = false;
115 return;
116 }
117
118 if (isLoadAppPreloadPlugin_) {
119 RESSCHED_LOGI("ResSchedService::LoadAppPreloadPlugin, already loaded AppPreloadPlugin");
120 return;
121 }
122
123 appPreloadFunc_ = reinterpret_cast<OnIsAllowedAppPreloadFunc>(dlsym(libInfoPtr->handle.get(),
124 "OnIsAllowedAppPreload"));
125 isLoadAppPreloadPlugin_ = true;
126 }
127
AllowDump()128 bool ResSchedService::AllowDump()
129 {
130 if (ENG_MODE == 0) {
131 RESSCHED_LOGE("Not eng mode");
132 return false;
133 }
134 Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
135 int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP");
136 if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
137 RESSCHED_LOGE("CheckPermission failed");
138 return false;
139 }
140 return true;
141 }
142
Dump(int32_t fd, const std::vector<std::u16string>& args)143 int32_t ResSchedService::Dump(int32_t fd, const std::vector<std::u16string>& args)
144 {
145 if (!AllowDump()) {
146 return ERR_RES_SCHED_PERMISSION_DENIED;
147 }
148 RESSCHED_LOGI("%{public}s Dump service.", __func__);
149 std::vector<std::string> argsInStr;
150 std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
151 [](const std::u16string &arg) {
152 std::string ret = Str16ToStr8(arg);
153 RESSCHED_LOGI("%{public}s arg: %{public}s.", __func__, ret.c_str());
154 return ret;
155 });
156 std::string result;
157 if (argsInStr.size() == 0) {
158 // hidumper -s said '-h'
159 DumpUsage(result);
160 } else if (argsInStr.size() == DUMP_OPTION + 1) {
161 // hidumper -s said '-h' or hidumper -s said '-a'
162 DumpExt(argsInStr, result);
163 } else if (argsInStr.size() >= DUMP_PARAM_INDEX + 1) {
164 if (argsInStr[DUMP_OPTION] == "-p") {
165 std::vector<std::string> argsInStrToPlugin;
166 argsInStrToPlugin.assign(argsInStr.begin() + DUMP_PARAM_INDEX + 1, argsInStr.end());
167 PluginMgr::GetInstance().DumpOnePlugin(result, argsInStr[DUMP_PARAM_INDEX], argsInStrToPlugin);
168 } else if (argsInStr[DUMP_OPTION] == "sendDebugToExecutor") {
169 DumpExecutorDebugCommand(argsInStr, result);
170 }
171 }
172
173 if (!SaveStringToFd(fd, result)) {
174 RESSCHED_LOGE("%{public}s save to fd failed.", __func__);
175 }
176 return ERR_OK;
177 }
178
179
DumpExt(const std::vector<std::string>& argsInStr, std::string &result)180 void ResSchedService::DumpExt(const std::vector<std::string>& argsInStr, std::string &result)
181 {
182 if (argsInStr[DUMP_OPTION] == "-h") {
183 DumpUsage(result);
184 } else if (argsInStr[DUMP_OPTION] == "-a") {
185 DumpAllInfo(result);
186 } else if (argsInStr[DUMP_OPTION] == "-p") {
187 PluginMgr::GetInstance().DumpAllPlugin(result);
188 } else if (argsInStr[DUMP_OPTION] == "getSystemloadInfo") {
189 DumpSystemLoadInfo(result);
190 } else if (argsInStr[DUMP_OPTION] == "sendDebugToExecutor") {
191 DumpExecutorDebugCommand(argsInStr, result);
192 } else if (argsInStr[DUMP_OPTION] == "PluginConfig") {
193 DumpAllPluginConfig(result);
194 } else {
195 result.append("Error params.");
196 }
197 }
198
DumpSystemLoadInfo(std::string &result)199 void ResSchedService::DumpSystemLoadInfo(std::string &result)
200 {
201 result.append("systemloadLevel:")
202 .append(ToString(NotifierMgr::GetInstance().GetSystemloadLevel()))
203 .append("\n");
204 auto notifierInfo = NotifierMgr::GetInstance().DumpRegisterInfo();
205 std::string native("natives:");
206 std::string hap("apps:");
207 for (auto& info : notifierInfo) {
208 std::string str = ToString(info.first).append(" ");
209 if (info.second) {
210 hap.append(str);
211 } else {
212 native.append(str);
213 }
214 }
215 hap.append("\n");
216 native.append("\n");
217 result.append(native).append(hap);
218 }
219
DumpUsage(std::string &result)220 void ResSchedService::DumpUsage(std::string &result)
221 {
222 result.append("usage: resource schedule service dump [<options>]\n")
223 .append(" -h: show the help.\n")
224 .append(" -a: show all info.\n")
225 .append(" -p: show the all plugin info.\n")
226 .append(" -p (plugin name): show one plugin info.\n");
227 PluginMgr::GetInstance().DumpHelpFromPlugin(result);
228 }
229
DumpAllInfo(std::string &result)230 void ResSchedService::DumpAllInfo(std::string &result)
231 {
232 result.append("================Resource Schedule Service Infos================\n");
233 PluginMgr::GetInstance().DumpAllPlugin(result);
234 }
235
DumpExecutorDebugCommand(const std::vector<std::string>& args, std::string& result)236 void ResSchedService::DumpExecutorDebugCommand(const std::vector<std::string>& args, std::string& result)
237 {
238 // hidumper -s said 'sendDebugToExecutor [isSync times]' isSync - 0/1(default 0), times - 1~...(default 1)
239 result.append("Send debug command to resource_schedule_executor.\n");
240 bool isSync = true;
241 int times = 1;
242 if (args.size() > DUMP_PARAM_INDEX + 1) {
243 int arg = atoi(args[DUMP_PARAM_INDEX + 1].c_str());
244 times = arg > 0 ? arg : times;
245 }
246 if (args.size() > DUMP_PARAM_INDEX) {
247 isSync = atoi(args[DUMP_PARAM_INDEX].c_str()) == 0;
248 }
249 uint32_t internal = 200;
250 for (int i = 0; i < times; i++) {
251 ResSchedExeClient::GetInstance().SendDebugCommand(isSync);
252 usleep(internal);
253 }
254 }
255
DumpAllPluginConfig(std::string &result)256 void ResSchedService::DumpAllPluginConfig(std::string &result)
257 {
258 result.append("================Resource Schedule Plugin Config================\n");
259 PluginMgr::GetInstance().DumpAllPluginConfig(result);
260 }
261 } // namespace ResourceSchedule
262 } // namespace OHOS
263
264