• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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