• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_exe_service.h"
17 
18 #include <file_ex.h>
19 #include <parameters.h>
20 #include <string_ex.h>
21 
22 #include "accesstoken_kit.h"
23 #include "ipc_skeleton.h"
24 #include "system_ability_definition.h"
25 
26 #include "plugin_mgr.h"
27 #include "executor_hitrace_chain.h"
28 #include "res_common_util.h"
29 #include "res_exe_type.h"
30 #include "res_sched_exe_constants.h"
31 #include "res_sched_exe_log.h"
32 #include "res_sched_exe_mgr.h"
33 
34 namespace OHOS {
35 namespace ResourceSchedule {
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 DUMP_PERMISSION = "ohos.permission.DUMP";
41     constexpr int32_t PAYLOAD_MAX_SIZE = 4096;
42     constexpr int32_t KILL_PROCESS_FAILED = -1;
43     constexpr int32_t RSS_UID = 1096;
44     const std::string RES_TYPE_EXT = "extType";
45 
IsTypeVaild(uint32_t type)46     bool IsTypeVaild(uint32_t type)
47     {
48         return type >= ResExeType::RES_TYPE_FIRST && type < ResExeType::RES_TYPE_LAST;
49     }
50 
IsCallingClientRss()51     bool IsCallingClientRss()
52     {
53         int32_t clientUid = IPCSkeleton::GetCallingUid();
54         RSSEXE_LOGD("calling client uid is %{public}d, allowed uid is %{public}d", clientUid, RSS_UID);
55         return RSS_UID == clientUid;
56     }
57 
GetExtResType(uint32_t & resType,const nlohmann::json & context)58     bool GetExtResType(uint32_t& resType, const nlohmann::json& context)
59     {
60         if (resType != ResExeType::RES_TYPE_COMMON_SYNC && resType != ResExeType::RES_TYPE_COMMON_ASYNC) {
61             return true;
62         }
63         int type = 0;
64         if (!context.contains(RES_TYPE_EXT) || !context[RES_TYPE_EXT].is_string()
65             || !StrToInt(context[RES_TYPE_EXT], type)) {
66             RSSEXE_LOGE("use extend resType, but not send resTypeExt with payload");
67             return false;
68         }
69         resType = (uint32_t)type;
70         RSSEXE_LOGD("use extend resType = %{public}d.", resType);
71         return true;
72     }
73 }
74 
75 const bool REGISTER_RESULT =
76     SystemAbility::MakeAndRegisterAbility(DelayedSingleton<ResSchedExeService>::GetInstance().get());
77 
ResSchedExeService()78 ResSchedExeService::ResSchedExeService() : SystemAbility(RES_SCHED_EXE_ABILITY_ID, true)
79 {
80 }
81 
~ResSchedExeService()82 ResSchedExeService::~ResSchedExeService()
83 {
84 }
85 
OnStart()86 void ResSchedExeService::OnStart()
87 {
88     ExecutorHiTraceChain traceChain(__func__);
89     ResSchedExeMgr::GetInstance().Init();
90     if (!Publish(DelayedSingleton<ResSchedExeService>::GetInstance().get())) {
91         RSSEXE_LOGE("ResSchedExeService::Register service failed.");
92         return;
93     }
94     AddSystemAbilityListener(SUSPEND_MANAGER_SYSTEM_ABILITY_ID);
95     RSSEXE_LOGI("ResSchedExeService::OnStart.");
96 }
97 
OnStop()98 void ResSchedExeService::OnStop()
99 {
100     ExecutorHiTraceChain traceChain(__func__);
101     ResSchedExeMgr::GetInstance().Stop();
102     RSSEXE_LOGI("ResSchedExeService::OnStop!");
103 }
104 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)105 void ResSchedExeService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
106 {
107     if (systemAbilityId == SUSPEND_MANAGER_SYSTEM_ABILITY_ID) {
108         RSSEXE_LOGI("ResSchedExeService::OnRemoveSystemAbility SUSPEND_MANAGER_SYSTEM_ABILITY_ID.");
109         nlohmann::json jsonContext;
110         ResSchedExeMgr::GetInstance().SendRequestAsync(ResExeType::RES_TYPE_EXT_SUSPEND_MANAGER_SA_CHANGED,
111             static_cast<int64_t>(false), jsonContext);
112     }
113 }
114 
SendRequestSync(uint32_t resType,int64_t value,const ResJsonType & context,ResJsonType & response,int32_t & funcResult)115 ErrCode ResSchedExeService::SendRequestSync(uint32_t resType, int64_t value,
116                                             const ResJsonType &context, ResJsonType &response, int32_t &funcResult)
117 {
118     ExecutorHiTraceChain traceChain(__func__);
119     RSSEXE_LOGD("ResSchedExeService start to exec SendRequestSync, restType: %{public}u", resType);
120     if (!IsCallingClientRss()) {
121         RSSEXE_LOGE("calling process has no permission!");
122         return ERR_INVALID_OPERATION;
123     }
124     if (!IsTypeVaild(resType)) {
125         RSSEXE_LOGE("The resType is invalid. Dos");
126         return ERR_INVALID_VALUE;
127     }
128 
129     nlohmann::json jsonContext = context.jsonContext;
130     if (jsonContext.size() > PAYLOAD_MAX_SIZE) {
131         RSSEXE_LOGE("The payload is too long. DoS.");
132         return ERR_INVALID_VALUE;
133     }
134     if (!GetExtResType(resType, jsonContext)) {
135         RSSEXE_LOGE("Get ResType Error DoS.");
136         return ERR_INVALID_VALUE;
137     }
138 
139     nlohmann::json jsonResponse;
140     funcResult = ResSchedExeMgr::GetInstance().SendRequestSync(resType, value, jsonContext, jsonResponse);
141     response.jsonContext = jsonResponse;
142     return ERR_OK;
143 }
144 
SendRequestAsync(uint32_t resType,int64_t value,const ResJsonType & context)145 ErrCode ResSchedExeService::SendRequestAsync(uint32_t resType, int64_t value, const ResJsonType& context)
146 {
147     ExecutorHiTraceChain traceChain(__func__);
148     RSSEXE_LOGD("ResSchedExeService start to exec SendRequestAsync, restType: %{public}u", resType);
149     if (!IsCallingClientRss()) {
150         RSSEXE_LOGE("calling process has no permission!");
151         return ERR_INVALID_OPERATION;
152     }
153     if (!IsTypeVaild(resType)) {
154         RSSEXE_LOGE("The resType is invalid. Dos");
155         return ERR_INVALID_VALUE;
156     }
157 
158     nlohmann::json jsonContext = context.jsonContext;
159     if (jsonContext.size() > PAYLOAD_MAX_SIZE) {
160         RSSEXE_LOGE("The payload is too long. DoS.");
161         return ERR_INVALID_VALUE;
162     }
163     if (!GetExtResType(resType, jsonContext)) {
164         RSSEXE_LOGE("Get ResType Error DoS.");
165         return ERR_INVALID_VALUE;
166     }
167 
168     ResSchedExeMgr::GetInstance().SendRequestAsync(resType, value, jsonContext);
169     return ERR_OK;
170 }
171 
KillProcess(uint32_t pid,int32_t & funcResult)172 ErrCode ResSchedExeService::KillProcess(uint32_t pid, int32_t& funcResult)
173 {
174     ExecutorHiTraceChain traceChain(__func__);
175     RSSEXE_LOGD("ResSchedExeService start to exec KillProcess, pid: %{public}u", pid);
176     if (!IsCallingClientRss()) {
177         RSSEXE_LOGE("Calling process has no permission!");
178         return ERR_INVALID_OPERATION;
179     }
180     if (pid <= 0) {
181         RSSEXE_LOGE("Pid should be more than 0.");
182         return ERR_INVALID_VALUE;
183     }
184 
185     funcResult = ResSchedExeMgr::GetInstance().KillProcess(static_cast<pid_t>(pid));
186     return ERR_OK;
187 }
188 
AllowDump()189 bool ResSchedExeService::AllowDump()
190 {
191     if (ENG_MODE == 0) {
192         RSSEXE_LOGE("Not eng mode");
193         return false;
194     }
195     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
196     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, DUMP_PERMISSION);
197     if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
198         RSSEXE_LOGE("CheckPermission failed");
199         return false;
200     }
201     return true;
202 }
203 
Dump(int32_t fd,const std::vector<std::u16string> & args)204 int32_t ResSchedExeService::Dump(int32_t fd, const std::vector<std::u16string>& args)
205 {
206     if (!AllowDump()) {
207         return ResErrCode::RSSEXE_PERMISSION_DENIED;
208     }
209     RSSEXE_LOGI("Dump service.");
210     std::vector<std::string> argsInStr;
211     std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
212         [](const std::u16string &arg) {
213         std::string ret = Str16ToStr8(arg);
214         RSSEXE_LOGI("arg: %{public}s.", ret.c_str());
215         return ret;
216     });
217     std::string result;
218     if (argsInStr.size() == 0) {
219         // hidumper -s said '-h'
220         DumpUsage(result);
221     } else if (argsInStr.size() == DUMP_OPTION + 1) {
222         // hidumper -s said '-h' or hidumper -s said '-a'
223         if (argsInStr[DUMP_OPTION] == "-h") {
224             DumpUsage(result);
225         } else if (argsInStr[DUMP_OPTION] == "-a") {
226             DumpAllInfo(result);
227         } else if (argsInStr[DUMP_OPTION] == "-p") {
228             PluginMgr::GetInstance().DumpAllPlugin(result);
229         } else {
230             result.append("Error params.");
231         }
232     } else if (argsInStr.size() >= DUMP_PARAM_INDEX + 1) {
233         if (argsInStr[DUMP_OPTION] == "-p") {
234             std::vector<std::string> argsInStrToPlugin;
235             argsInStrToPlugin.assign(argsInStr.begin() + DUMP_PARAM_INDEX + 1, argsInStr.end());
236             PluginMgr::GetInstance().DumpOnePlugin(result, argsInStr[DUMP_PARAM_INDEX], argsInStrToPlugin);
237         }
238     }
239 
240     if (!SaveStringToFd(fd, result)) {
241         RSSEXE_LOGE("save to fd failed.");
242     }
243     return ResErrCode::RSSEXE_NO_ERR;
244 }
245 
DumpUsage(std::string & result)246 void ResSchedExeService::DumpUsage(std::string &result)
247 {
248     result.append("usage: resource schedule executor dump [<options>]\n")
249         .append("    -h: show the help.\n")
250         .append("    -a: show all info.\n")
251         .append("    -p: show the all plugin info.\n")
252         .append("    -p (plugin name): show one plugin info.\n");
253     PluginMgr::GetInstance().DumpHelpFromPlugin(result);
254 }
255 
DumpAllInfo(std::string & result)256 void ResSchedExeService::DumpAllInfo(std::string &result)
257 {
258     result.append("================Resource Schedule Executor Infos================\n");
259     PluginMgr::GetInstance().DumpAllPlugin(result);
260 }
261 } // namespace ResourceSchedule
262 } // namespace OHOS
263