1 /*
2 * Copyright (c) 2022-2025 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 #include "hisysevent.h"
33 #include "res_common_util.h"
34 #include "res_sa_init.h"
35
36 namespace OHOS {
37 namespace ResourceSchedule {
38 using namespace OHOS::Security;
39 namespace {
40 #define PAYLOAD_MAX_SIZE 4096
41 static constexpr int32_t DUMP_OPTION = 0;
42 static constexpr int32_t DUMP_PARAM_INDEX = 1;
43 static const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
44 static const char* APP_PRELOAD_PLIGIN_NAME = "libapp_preload_plugin.z.so";
45 static const char* NEEDED_PERMISSION = "ohos.permission.REPORT_RESOURCE_SCHEDULE_EVENT";
46 static const char* SCENEBOARD_BUNDLE_NAME = "com.ohos.sceneboard";
47 static constexpr int32_t MEMMGR_UID = 1111;
48 static constexpr int32_t SAMGR_UID = 5555;
49 static constexpr int32_t FOUNDATION_UID = 5523;
50 static constexpr int32_t GRAPHIC_UID = 1003;
51 static constexpr int32_t HIVIEW_UID = 1201;
52 static constexpr int32_t SINGLE_UID_REQUEST_LIMIT_COUNT = 250;
53 static constexpr int32_t ALL_UID_REQUEST_LIMIT_COUNT = 650;
54 static constexpr int32_t LIMIT_REQUEST_TIME = 1000;
55 static constexpr int64_t FOUR_HOUR_TIME = 4 * 60 * 60 * 1000;
56 static const std::unordered_set<uint32_t> SCB_RES = {
57 ResType::SYNC_RES_TYPE_THAW_ONE_APP,
58 ResType::RES_TYPE_REPORT_SCENE_BOARD,
59 ResType::RES_TYPE_SHOW_REMOTE_ANIMATION,
60 ResType::RES_TYPE_KEY_PERF_SCENE,
61 ResType::RES_TYPE_MOVE_WINDOW,
62 ResType::RES_TYPE_RESIZE_WINDOW,
63 ResType::RES_TYPE_ONLY_PERF_APP_COLD_START,
64 ResType::RES_TYPE_SCENE_ROTATION,
65 ResType::SYNC_RES_TYPE_CHECK_MUTEX_BEFORE_START,
66 ResType::RES_TYPE_COSMIC_CUBE_STATE_CHANGE,
67 ResType::RES_TYPE_GESTURE_ANIMATION,
68 ResType::RES_TYPE_RAISE_WORKER_THREAD_PRIORITY,
69 };
70 static const std::unordered_set<uint32_t> THIRDPART_RES = {
71 ResType::RES_TYPE_CLICK_RECOGNIZE,
72 ResType::RES_TYPE_KEY_EVENT,
73 ResType::RES_TYPE_PUSH_PAGE,
74 ResType::RES_TYPE_SLIDE_RECOGNIZE,
75 ResType::RES_TYPE_POP_PAGE,
76 ResType::RES_TYPE_LOAD_PAGE,
77 ResType::RES_TYPE_WEB_GESTURE,
78 ResType::RES_TYPE_REPORT_KEY_THREAD,
79 ResType::RES_TYPE_REPORT_WINDOW_STATE,
80 ResType::RES_TYPE_REPORT_SCENE_SCHED,
81 ResType::RES_TYPE_WEB_GESTURE_MOVE,
82 ResType::RES_TYPE_WEB_SLIDE_NORMAL,
83 ResType::RES_TYPE_LOAD_URL,
84 ResType::RES_TYPE_MOUSEWHEEL,
85 ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE,
86 ResType::RES_TYPE_REPORT_RENDER_THREAD,
87 ResType::RES_TYPE_LONG_FRAME,
88 ResType::RES_TYPE_REPORT_VSYNC_TID,
89 ResType::RES_TYPE_WEB_DRAG_RESIZE,
90 ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE,
91 ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE,
92 ResType::RES_TYPE_BT_SERVICE_EVENT,
93 ResType::RES_TYPE_APP_FRAME_DROP,
94 ResType::RES_TYPE_REPORT_DISTRIBUTE_TID,
95 ResType::RES_TYPE_AXIS_EVENT,
96 ResType::RES_TYPE_CROWN_ROTATION_STATUS,
97 ResType::RES_TYPE_RED_ENVELOPE,
98 ResType::RES_TYPE_RECV_ABC_LOAD_COMPLETED,
99 ResType::RES_TYPE_SET_BACKGROUND_PROCESS_PRIORITY,
100 ResType::RES_TYPE_CHECK_APP_IS_IN_SCHEDULE_LIST,
101 ResType::RES_TYPE_SHORT_TERM_LOAD,
102 ResType::RES_TYPE_PAGE_TRANSITION,
103 ResType::RES_TYPE_VOICE_RECOGNIZE_WAKE,
104 };
105 static const std::unordered_set<uint32_t> FG_THIRDPART_RES = {
106 ResType::RES_TYPE_CLICK_RECOGNIZE,
107 ResType::RES_TYPE_KEY_EVENT,
108 ResType::RES_TYPE_SLIDE_RECOGNIZE,
109 ResType::RES_TYPE_LOAD_URL,
110 ResType::RES_TYPE_MOUSEWHEEL,
111 ResType::RES_TYPE_LONG_FRAME,
112 ResType::RES_TYPE_WEB_DRAG_RESIZE,
113 ResType::RES_TYPE_APP_FRAME_DROP,
114 ResType::RES_TYPE_AXIS_EVENT,
115 };
116 static const std::unordered_set<uint32_t> SA_RES = {
117 ResType::SYNC_RES_TYPE_THAW_ONE_APP,
118 ResType::SYNC_RES_TYPE_GET_ALL_SUSPEND_STATE,
119 ResType::SYNC_RES_TYPE_GET_THERMAL_DATA,
120 ResType::RES_TYPE_CLICK_RECOGNIZE,
121 ResType::RES_TYPE_SCREEN_STATUS,
122 ResType::RES_TYPE_APP_STATE_CHANGE,
123 ResType::RES_TYPE_ABILITY_STATE_CHANGE,
124 ResType::RES_TYPE_EXTENSION_STATE_CHANGE,
125 ResType::RES_TYPE_PROCESS_STATE_CHANGE,
126 ResType::RES_TYPE_WINDOW_FOCUS,
127 ResType::RES_TYPE_TRANSIENT_TASK,
128 ResType::RES_TYPE_CONTINUOUS_TASK,
129 ResType::RES_TYPE_CGROUP_ADJUSTER,
130 ResType::RES_TYPE_WINDOW_VISIBILITY_CHANGE,
131 ResType::RES_TYPE_REPORT_MMI_PROCESS,
132 ResType::RES_TYPE_APP_INSTALL_UNINSTALL,
133 ResType::RES_TYPE_WIFI_CONNECT_STATE_CHANGE,
134 ResType::RES_TYPE_USER_SWITCH,
135 ResType::RES_TYPE_USER_REMOVE,
136 ResType::RES_TYPE_SCREEN_LOCK,
137 ResType::RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE,
138 ResType::RES_TYPE_NETWORK_LATENCY_REQUEST,
139 ResType::RES_TYPE_CALL_STATE_UPDATE,
140 ResType::RES_TYPE_THREAD_QOS_CHANGE,
141 ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
142 ResType::RES_TYPE_AUDIO_RING_MODE_CHANGE,
143 ResType::RES_TYPE_AUDIO_VOLUME_KEY_CHANGE,
144 ResType::RES_TYPE_APP_ABILITY_START,
145 ResType::RES_TYPE_PRELOAD_APPLICATION,
146 ResType::RES_TYPE_DEVICE_STILL_STATE_CHANGE,
147 ResType::RES_TYPE_RESIZE_WINDOW,
148 ResType::RES_TYPE_MOVE_WINDOW,
149 ResType::RES_TYPE_SHOW_REMOTE_ANIMATION,
150 ResType::RES_TYPE_REPORT_CAMERA_STATE,
151 ResType::RES_TYPE_RUNNINGLOCK_STATE,
152 ResType::RES_TYPE_DRAG_STATUS_BAR,
153 ResType::RES_TYPE_REPORT_SCENE_BOARD,
154 ResType::RES_TYPE_MMI_INPUT_STATE,
155 ResType::RES_TYPE_ANCO_CUST,
156 ResType::RES_TYPE_TIMEZONE_CHANGED,
157 ResType::RES_TYPE_APP_ASSOCIATED_START,
158 ResType::RES_TYPE_THERMAL_STATE,
159 ResType::RES_TYPE_REPORT_SCREEN_CAPTURE,
160 ResType::RES_TYPE_KEY_PERF_SCENE,
161 ResType::RES_TYPE_SUPER_LAUNCHER,
162 ResType::RES_TYPE_CAST_SCREEN,
163 ResType::RES_TYPR_SCREEN_COLLABROATION,
164 ResType::RES_TYPE_SA_CONTROL_APP_EVENT,
165 ResType::RES_TYPE_SYSTEM_CPU_LOAD,
166 ResType::RES_TYPE_UPLOAD_DOWNLOAD,
167 ResType::RES_TYPE_SPLIT_SCREEN,
168 ResType::RES_TYPE_FLOATING_WINDOW,
169 ResType::RES_TYPE_FRAME_RATE_REPORT,
170 ResType::RES_TYPE_LOCATION_STATUS_CHANGE,
171 ResType::RES_TYPE_REPORT_DISTRIBUTE_COMPONENT_CHANGE,
172 ResType::RES_TYPE_FORM_STATE_CHANGE_EVENT,
173 ResType::RES_TYPE_THERMAL_SCENARIO_REPORT,
174 ResType::RES_TYPE_BOOT_COMPLETED,
175 ResType::RES_TYPE_CONTINUOUS_STARTUP,
176 ResType::RES_TYPE_AUDIO_RENDERER_SILENT_PLAYBACK,
177 ResType::RES_TYPE_REPORT_GAME_SCHED,
178 ResType::RES_TYPE_SEND_FRAME_EVENT,
179 ResType::RES_TYPE_CLOUD_CONFIG_UPDATE,
180 ResType::RES_TYPE_DEVICE_IDLE,
181 ResType::RES_TYPE_BT_SERVICE_EVENT,
182 ResType::RES_TYPE_BMM_MONITER_CHANGE_EVENT,
183 ResType::RES_TYPE_GAME_INFO_NOTIFY,
184 ResType::SYNC_RES_TYPE_REQUEST_MUTEX_STATUS,
185 ResType::SYNC_RES_TYPE_SHOULD_FORCE_KILL_PROCESS,
186 ResType::RES_TYPE_CLICK_RECOGNIZE,
187 ResType::RES_TYPE_RSS_CLOUD_CONFIG_UPDATE,
188 ResType::SYNC_RES_TYPE_GET_NWEB_PRELOAD_SET,
189 ResType::RES_TYPE_AUDIO_RENDERER_STANDBY,
190 ResType::RES_TYPE_APP_GAME_BOOST_EVENT,
191 ResType::RES_TYPE_DISPLAY_MULTI_SCREEN,
192 ResType::RES_TYPE_INTENT_CTRL_APP,
193 ResType::RES_TYPE_GET_GAME_SCENE_INFO,
194 ResType::RES_TYPE_FRAME_RATE_REPORT_FROM_RS,
195 ResType::RES_TYPE_SHORT_TERM_LOAD,
196 ResType::RES_TYPE_DYNAMICALLY_SET_SUSPEND_EXEMPT,
197 #ifdef RESSCHED_RESOURCESCHEDULE_FILE_COPY_SOC_PERF_ENABLE
198 ResType::RES_TYPE_FILE_COPY_STATUS,
199 #endif
200 };
201
IsHasPermission(const uint32_t type)202 bool IsHasPermission(const uint32_t type)
203 {
204 if (SA_RES.find(type) == SA_RES.end()) {
205 RESSCHED_LOGE("resType:%{public}d not sa report", type);
206 return false;
207 }
208 AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
209 auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
210 if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
211 RESSCHED_LOGD("not native sa");
212 return false;
213 }
214 int32_t hasPermission = AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, NEEDED_PERMISSION);
215 if (hasPermission != 0) {
216 RESSCHED_LOGE("not have permission");
217 return false;
218 }
219 return true;
220 }
221
IsTypeVaild(const uint32_t type)222 bool IsTypeVaild(const uint32_t type)
223 {
224 return type >= ResType::RES_TYPE_FIRST && type < ResType::RES_TYPE_LAST;
225 }
226
IsThirdPartType(const uint32_t type)227 bool IsThirdPartType(const uint32_t type)
228 {
229 if (THIRDPART_RES.find(type) == THIRDPART_RES.end()) {
230 RESSCHED_LOGD("resType:%{public}d not hap app report", type);
231 return false;
232 }
233 if (FG_THIRDPART_RES.find(type) != FG_THIRDPART_RES.end() &&
234 !ResSchedMgr::GetInstance().IsForegroundApp(IPCSkeleton::GetCallingPid())) {
235 RESSCHED_LOGD("not foreground app");
236 return false;
237 }
238 AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
239 auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
240 if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
241 RESSCHED_LOGE("not hap app");
242 return false;
243 }
244
245 return true;
246 }
247
IsSBDResType(uint32_t type)248 bool IsSBDResType(uint32_t type)
249 {
250 if (SCB_RES.find(type) == SCB_RES.end()) {
251 return false;
252 }
253 AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
254 auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
255 if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
256 return false;
257 }
258 AccessToken::HapTokenInfo callingTokenInfo;
259 AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, callingTokenInfo);
260 if (callingTokenInfo.bundleName == SCENEBOARD_BUNDLE_NAME) {
261 return true;
262 }
263 RESSCHED_LOGE("%{public}s is not sceneboard bundle name", callingTokenInfo.bundleName.c_str());
264 return false;
265 }
266 }
267
StringToJsonObj(const std::string & str)268 nlohmann::json ResSchedService::StringToJsonObj(const std::string& str)
269 {
270 nlohmann::json jsonObj = nlohmann::json::object();
271 if (str.empty()) {
272 return jsonObj;
273 }
274 nlohmann::json jsonTmp = nlohmann::json::parse(str, nullptr, false);
275 if (jsonTmp.is_discarded()) {
276 RESSCHED_LOGE("%{public}s: parse fail, str=%{public}s.", __func__, str.c_str());
277 return jsonObj;
278 }
279 if (!jsonTmp.is_object()) {
280 RESSCHED_LOGD("%{public}s: str=%{public}s is not jsonObj.", __func__, str.c_str());
281 return jsonObj;
282 }
283 return jsonTmp;
284 }
285
ReportData(uint32_t resType,int64_t value,const std::string & payload)286 ErrCode ResSchedService::ReportData(uint32_t resType, int64_t value, const std::string& payload)
287 {
288 int32_t checkResult = RemoteRequestCheck();
289 if (checkResult != ERR_OK) {
290 RESSCHED_LOGD("check remote request fail.");
291 return checkResult;
292 }
293
294 int32_t ret = CheckReportDataParcel(resType, value, payload);
295 if (ret != ERR_OK) {
296 RESSCHED_LOGE("%{public}s: check report data parcel fail ret=%{public}d, type=%{public}u.",
297 __func__, ret, resType);
298 return ret;
299 }
300
301 int32_t clientPid = IPCSkeleton::GetCallingPid();
302 RESSCHED_LOGD("ResSchedService receive data from ipc resType: %{public}u, value: %{public}lld, pid: %{public}d",
303 resType, (long long)value, clientPid);
304 nlohmann::json reportDataPayload = StringToJsonObj(payload);
305 int32_t callingUid = IPCSkeleton::GetCallingUid();
306 reportDataPayload["callingUid"] = std::to_string(callingUid);
307 reportDataPayload["clientPid"] = std::to_string(clientPid);
308 ResSchedMgr::GetInstance().ReportData(resType, value, reportDataPayload);
309 ResSchedIpcThread::GetInstance().SetQos(clientPid);
310 return ERR_OK;
311 }
312
ReportSyncEvent(const uint32_t resType,const int64_t value,const std::string & payload,std::string & reply,int32_t & resultValue)313 ErrCode ResSchedService::ReportSyncEvent(const uint32_t resType, const int64_t value, const std::string& payload,
314 std::string& reply, int32_t& resultValue)
315 {
316 int32_t checkResult = RemoteRequestCheck();
317 if (checkResult != ERR_OK) {
318 RESSCHED_LOGD("check remote request fail.");
319 resultValue = checkResult;
320 return ERR_OK;
321 }
322
323 int32_t ret = CheckReportDataParcel(resType, value, payload);
324 if (ret != ERR_OK) {
325 RESSCHED_LOGE("%{public}s: check report data parcel fail ret=%{public}d, type=%{public}u.",
326 __func__, ret, resType);
327 resultValue = ret;
328 return ERR_OK;
329 }
330 nlohmann::json payloadJsonValue;
331 nlohmann::json replyValue;
332 payloadJsonValue = StringToJsonObj(payload);
333 int32_t clientPid = IPCSkeleton::GetCallingPid();
334 int32_t callingUid = IPCSkeleton::GetCallingUid();
335 payloadJsonValue["clientPid"] = std::to_string(clientPid);
336 payloadJsonValue["callingUid"] = std::to_string(callingUid);
337 resultValue = PluginMgr::GetInstance().DeliverResource(
338 std::make_shared<ResData>(resType, value, payloadJsonValue, replyValue));
339 reply = replyValue.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
340 ResSchedIpcThread::GetInstance().SetQos(clientPid);
341 return ERR_OK;
342 }
343
KillProcess(const std::string & payload,int32_t & resultValue)344 ErrCode ResSchedService::KillProcess(const std::string& payload, int32_t& resultValue)
345 {
346 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
347 int32_t uid = IPCSkeleton::GetCallingUid();
348 Security::AccessToken::ATokenTypeEnum tokenTypeFlag =
349 Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(accessToken);
350 if ((uid != MEMMGR_UID && uid != SAMGR_UID && uid != HIVIEW_UID && uid != GRAPHIC_UID)
351 || tokenTypeFlag != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
352 RESSCHED_LOGE("no permission, kill process fail");
353 resultValue = RES_SCHED_KILL_PROCESS_FAIL;
354 return ERR_OK;
355 }
356
357 if (payload.size() > PAYLOAD_MAX_SIZE) {
358 RESSCHED_LOGE("The payload is too long. DoS.");
359 resultValue = RES_SCHED_KILL_PROCESS_FAIL;
360 return ERR_OK;
361 }
362
363 resultValue = ResSchedMgr::GetInstance().KillProcessByClient(StringToJsonObj(payload));
364 return ERR_OK;
365 }
366
RegisterSystemloadNotifier(const sptr<IRemoteObject> & notifier)367 ErrCode ResSchedService::RegisterSystemloadNotifier(const sptr<IRemoteObject>& notifier)
368 {
369 if (notifier == nullptr) {
370 RESSCHED_LOGE("ResSchedService notifier is nullptr.");
371 return RES_SCHED_DATA_ERROR;
372 }
373
374 NotifierMgr::GetInstance().RegisterNotifier(IPCSkeleton::GetCallingPid(), notifier);
375 return ERR_OK;
376 }
377
UnRegisterSystemloadNotifier()378 ErrCode ResSchedService::UnRegisterSystemloadNotifier()
379 {
380 NotifierMgr::GetInstance().UnRegisterNotifier(IPCSkeleton::GetCallingPid());
381 return ERR_OK;
382 }
383
RegisterEventListener(const sptr<IRemoteObject> & eventListener,uint32_t eventType,uint32_t listenerGroup)384 ErrCode ResSchedService::RegisterEventListener(const sptr<IRemoteObject>& eventListener, uint32_t eventType,
385 uint32_t listenerGroup)
386 {
387 EventListenerMgr::GetInstance().RegisterEventListener(IPCSkeleton::GetCallingPid(), eventListener, eventType,
388 listenerGroup);
389 return ERR_OK;
390 }
391
UnRegisterEventListener(uint32_t eventType,uint32_t listenerGroup)392 ErrCode ResSchedService::UnRegisterEventListener(uint32_t eventType, uint32_t listenerGroup)
393 {
394 EventListenerMgr::GetInstance().UnRegisterEventListener(IPCSkeleton::GetCallingPid(), eventType, listenerGroup);
395 return ERR_OK;
396 }
397
GetSystemloadLevel(int32_t & resultValue)398 ErrCode ResSchedService::GetSystemloadLevel(int32_t& resultValue)
399 {
400 resultValue = NotifierMgr::GetInstance().GetSystemloadLevel();
401 return ERR_OK;
402 }
403
OnDeviceLevelChanged(int32_t type,int32_t level)404 void ResSchedService::OnDeviceLevelChanged(int32_t type, int32_t level)
405 {
406 NotifierMgr::GetInstance().OnDeviceLevelChanged(type, level);
407 }
408
IsAllowedAppPreload(const std::string & bundleName,int32_t preloadMode,bool & resultValue)409 ErrCode ResSchedService::IsAllowedAppPreload(const std::string& bundleName, int32_t preloadMode, bool& resultValue)
410 {
411 AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
412 int32_t uid = IPCSkeleton::GetCallingUid();
413 AccessToken::ATokenTypeEnum tokenTypeFlag = AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
414 if (uid != FOUNDATION_UID || tokenTypeFlag != AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
415 RESSCHED_LOGE("Invalid calling token");
416 resultValue = false;
417 return ERR_OK;
418 }
419
420 LoadAppPreloadPlugin();
421 if (!appPreloadFunc_) {
422 RESSCHED_LOGE("%{public}s, no allow AppPreload !", __func__);
423 resultValue = false;
424 return ERR_OK;
425 }
426 resultValue = appPreloadFunc_(bundleName, preloadMode);
427 return ERR_OK;
428 }
429
LoadAppPreloadPlugin()430 void ResSchedService::LoadAppPreloadPlugin()
431 {
432 std::shared_ptr<PluginLib> libInfoPtr = PluginMgr::GetInstance().GetPluginLib(APP_PRELOAD_PLIGIN_NAME);
433 if (libInfoPtr == nullptr) {
434 RESSCHED_LOGE("ResSchedService::LoadAppPreloadPlugin libInfoPtr nullptr");
435 isLoadAppPreloadPlugin_ = false;
436 return;
437 }
438
439 if (isLoadAppPreloadPlugin_) {
440 RESSCHED_LOGI("ResSchedService::LoadAppPreloadPlugin, already loaded AppPreloadPlugin");
441 return;
442 }
443
444 appPreloadFunc_ = reinterpret_cast<OnIsAllowedAppPreloadFunc>(dlsym(libInfoPtr->handle.get(),
445 "OnIsAllowedAppPreload"));
446 isLoadAppPreloadPlugin_ = true;
447 }
448
IsAllowedLinkJump(bool isAllowedLinkJump,int32_t & resultValue)449 ErrCode ResSchedService::IsAllowedLinkJump(bool isAllowedLinkJump, int32_t& resultValue)
450 {
451 AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
452 AccessToken::ATokenTypeEnum tokenTypeFlag = AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
453 if (tokenTypeFlag != AccessToken::ATokenTypeEnum::TOKEN_HAP) {
454 RESSCHED_LOGE("Invalid calling token");
455 resultValue = RES_SCHED_ACCESS_TOKEN_FAIL;
456 return ERR_OK;
457 }
458
459 AccessToken::HapTokenInfo callingTokenInfo;
460 AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, callingTokenInfo);
461 std::string callingBundleName = callingTokenInfo.bundleName;
462 if (!PluginMgr::GetInstance().GetLinkJumpOptConfig(callingBundleName, isAllowedLinkJump)) {
463 RESSCHED_LOGE("Invalid callingBundleName");
464 resultValue = ERR_RES_SCHED_INVALID_PARAM;
465 return ERR_OK;
466 }
467 resultValue = ERR_OK;
468 return ERR_OK;
469 }
470
AllowDump()471 bool ResSchedService::AllowDump()
472 {
473 if (ENG_MODE == 0) {
474 RESSCHED_LOGE("Not eng mode");
475 return false;
476 }
477 Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
478 int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP");
479 if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
480 RESSCHED_LOGE("CheckPermission failed");
481 return false;
482 }
483 return true;
484 }
485
Dump(int32_t fd,const std::vector<std::u16string> & args)486 int32_t ResSchedService::Dump(int32_t fd, const std::vector<std::u16string>& args)
487 {
488 if (!AllowDump()) {
489 return ERR_RES_SCHED_PERMISSION_DENIED;
490 }
491 RESSCHED_LOGI("%{public}s Dump service.", __func__);
492 std::vector<std::string> argsInStr;
493 std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
494 [](const std::u16string &arg) {
495 std::string ret = Str16ToStr8(arg);
496 RESSCHED_LOGI("%{public}s arg: %{public}s.", __func__, ret.c_str());
497 return ret;
498 });
499 std::string result;
500 if (argsInStr.size() == 0) {
501 // hidumper -s said '-h'
502 DumpUsage(result);
503 } else if (argsInStr.size() == DUMP_OPTION + 1) {
504 // hidumper -s said '-h' or hidumper -s said '-a'
505 DumpExt(argsInStr, result);
506 } else if (argsInStr.size() >= DUMP_PARAM_INDEX + 1) {
507 if (argsInStr[DUMP_OPTION] == "-p") {
508 std::vector<std::string> argsInStrToPlugin;
509 argsInStrToPlugin.assign(argsInStr.begin() + DUMP_PARAM_INDEX + 1, argsInStr.end());
510 PluginMgr::GetInstance().DumpOnePlugin(result, argsInStr[DUMP_PARAM_INDEX], argsInStrToPlugin);
511 } else if (argsInStr[DUMP_OPTION] == "sendDebugToExecutor") {
512 DumpExecutorDebugCommand(argsInStr, result);
513 }
514 }
515
516 if (!SaveStringToFd(fd, result)) {
517 RESSCHED_LOGE("%{public}s save to fd failed.", __func__);
518 }
519 return ERR_OK;
520 }
521
522
DumpExt(const std::vector<std::string> & argsInStr,std::string & result)523 void ResSchedService::DumpExt(const std::vector<std::string>& argsInStr, std::string &result)
524 {
525 if (argsInStr[DUMP_OPTION] == "-h") {
526 DumpUsage(result);
527 } else if (argsInStr[DUMP_OPTION] == "-a") {
528 DumpAllInfo(result);
529 } else if (argsInStr[DUMP_OPTION] == "-p") {
530 PluginMgr::GetInstance().DumpAllPlugin(result);
531 } else if (argsInStr[DUMP_OPTION] == "getSystemloadInfo") {
532 DumpSystemLoadInfo(result);
533 } else if (argsInStr[DUMP_OPTION] == "sendDebugToExecutor") {
534 DumpExecutorDebugCommand(argsInStr, result);
535 } else if (argsInStr[DUMP_OPTION] == "PluginConfig") {
536 DumpAllPluginConfig(result);
537 } else {
538 result.append("Error params.");
539 }
540 }
541
DumpSystemLoadInfo(std::string & result)542 void ResSchedService::DumpSystemLoadInfo(std::string &result)
543 {
544 result.append("systemloadLevel:")
545 .append(ToString(NotifierMgr::GetInstance().GetSystemloadLevel()))
546 .append("\n");
547 auto notifierInfo = NotifierMgr::GetInstance().DumpRegisterInfo();
548 std::string native("natives:");
549 std::string hap("apps:");
550 for (auto& info : notifierInfo) {
551 std::string str = ToString(info.first).append(" ");
552 if (info.second) {
553 hap.append(str);
554 } else {
555 native.append(str);
556 }
557 }
558 hap.append("\n");
559 native.append("\n");
560 result.append(native).append(hap);
561 }
562
DumpUsage(std::string & result)563 void ResSchedService::DumpUsage(std::string &result)
564 {
565 result.append("usage: resource schedule service dump [<options>]\n")
566 .append(" -h: show the help.\n")
567 .append(" -a: show all info.\n")
568 .append(" -p: show the all plugin info.\n")
569 .append(" -p (plugin name): show one plugin info.\n");
570 PluginMgr::GetInstance().DumpHelpFromPlugin(result);
571 }
572
DumpAllInfo(std::string & result)573 void ResSchedService::DumpAllInfo(std::string &result)
574 {
575 result.append("================Resource Schedule Service Infos================\n");
576 PluginMgr::GetInstance().DumpAllPlugin(result);
577 }
578
DumpExecutorDebugCommand(const std::vector<std::string> & args,std::string & result)579 void ResSchedService::DumpExecutorDebugCommand(const std::vector<std::string>& args, std::string& result)
580 {
581 // hidumper -s said 'sendDebugToExecutor [isSync times]' isSync - 0/1(default 0), times - 1~...(default 1)
582 result.append("Send debug command to resource_schedule_executor.\n");
583 bool isSync = true;
584 int times = 1;
585 if (args.size() > DUMP_PARAM_INDEX + 1) {
586 int arg = atoi(args[DUMP_PARAM_INDEX + 1].c_str());
587 times = arg > 0 ? arg : times;
588 }
589 if (args.size() > DUMP_PARAM_INDEX) {
590 isSync = atoi(args[DUMP_PARAM_INDEX].c_str()) == 0;
591 }
592 uint32_t internal = 200;
593 for (int i = 0; i < times; i++) {
594 ResSchedExeClient::GetInstance().SendDebugCommand(isSync);
595 usleep(internal);
596 }
597 }
598
DumpAllPluginConfig(std::string & result)599 void ResSchedService::DumpAllPluginConfig(std::string &result)
600 {
601 result.append("================Resource Schedule Plugin Config================\n");
602 PluginMgr::GetInstance().DumpAllPluginConfig(result);
603 }
604
CheckReportDataParcel(const uint32_t & type,const int64_t & value,const std::string & payload)605 int32_t ResSchedService::CheckReportDataParcel(const uint32_t& type, const int64_t& value,
606 const std::string& payload)
607 {
608 if (!IsTypeVaild(type)) {
609 RESSCHED_LOGE("type:%{public}u is invalid", type);
610 return ERR_RES_SCHED_PARCEL_ERROR;
611 }
612 if (!IsSBDResType(type) && !IsThirdPartType(type) && !IsHasPermission(type)) {
613 RESSCHED_LOGD("type:%{public}u, no permission", type);
614 return ERR_RES_SCHED_PERMISSION_DENIED;
615 }
616
617 if (payload.size() > PAYLOAD_MAX_SIZE) {
618 RESSCHED_LOGE("too long payload.size:%{public}u", (uint32_t)payload.size());
619 return ERR_RES_SCHED_PARCEL_ERROR;
620 }
621 return ERR_OK;
622 }
623
PrintLimitLog(int32_t uid)624 void ResSchedService::PrintLimitLog(int32_t uid)
625 {
626 if (isPrintLimitLog_.load()) {
627 isPrintLimitLog_.store(false);
628 RESSCHED_LOGI("request limit, allRequestCount_:%{public}d, cur report uid:%{public}d",
629 allRequestCount_.load(), uid);
630 }
631 }
632
ReportBigData()633 void ResSchedService::ReportBigData()
634 {
635 if (!isReportBigData_.load()) {
636 return;
637 }
638 if (ResCommonUtil::GetNowMillTime(true) < nextReportBigDataTime_) {
639 return;
640 }
641 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "SERVICE_REQUEST_LIMIT",
642 HiviewDFX::HiSysEvent::EventType::FAULT, "REQUEST_LIMIT_COUNT", bigDataReportCount_.load());
643 isReportBigData_.store(false);
644 bigDataReportCount_.store(0);
645 }
646
InreaseBigDataCount()647 void ResSchedService::InreaseBigDataCount()
648 {
649 if (!isReportBigData_.load()) {
650 isReportBigData_.store(true);
651 nextReportBigDataTime_ = ResCommonUtil::GetNowMillTime(true) + FOUR_HOUR_TIME;
652 }
653 bigDataReportCount_.fetch_add(1, std::memory_order_relaxed);
654 }
655
IsLimitRequest(int32_t uid)656 bool ResSchedService::IsLimitRequest(int32_t uid)
657 {
658 std::lock_guard<std::mutex> lock(mutex_);
659 int64_t nowTime = ResCommonUtil::GetNowMillTime(true);
660 CheckAndUpdateLimitData(nowTime);
661 if (allRequestCount_.load() >= ALL_UID_REQUEST_LIMIT_COUNT) {
662 RESSCHED_LOGD("all uid request is limit, %{public}d request fail", uid);
663 return true;
664 }
665 auto iter = appRequestCountMap_.find(uid);
666 if (iter == appRequestCountMap_.end()) {
667 appRequestCountMap_[uid] = 1;
668 allRequestCount_.fetch_add(1, std::memory_order_relaxed);
669 return false;
670 }
671 if (appRequestCountMap_[uid] >= SINGLE_UID_REQUEST_LIMIT_COUNT) {
672 RESSCHED_LOGD("uid:%{public}d request is limit, request fail", uid);
673 return true;
674 }
675 appRequestCountMap_[uid] ++;
676 allRequestCount_.fetch_add(1, std::memory_order_relaxed);
677 return false;
678 }
679
CheckAndUpdateLimitData(int64_t nowTime)680 void ResSchedService::CheckAndUpdateLimitData(int64_t nowTime)
681 {
682 if (nowTime - nextCheckTime_.load() >= 0) {
683 nextCheckTime_.store(nowTime + LIMIT_REQUEST_TIME);
684 appRequestCountMap_.clear();
685 allRequestCount_.store(0);
686 isPrintLimitLog_.store(true);
687 }
688 }
689
RemoteRequestCheck()690 int32_t ResSchedService::RemoteRequestCheck()
691 {
692 ReportBigData();
693 auto uid = IPCSkeleton::GetCallingUid();
694 if (IsLimitRequest(uid)) {
695 RESSCHED_LOGD("%{public}d is limit request, cur request fail", uid);
696 InreaseBigDataCount();
697 PrintLimitLog(uid);
698 return RES_SCHED_REQUEST_FAIL;
699 }
700 return ERR_OK;
701 }
702
703 } // namespace ResourceSchedule
704 } // namespace OHOS
705
706