• 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 "res_sched_service_stub.h"
17 #include <cstdint>
18 #include "res_sched_errors.h"
19 #include "res_sched_log.h"
20 #include "res_sched_ipc_interface_code.h"
21 #include "res_type.h"
22 #include "accesstoken_kit.h"
23 #include "ipc_skeleton.h"
24 #include "ipc_util.h"
25 #include "accesstoken_kit.h"
26 #include "res_common_util.h"
27 #include "hisysevent.h"
28 #include "res_common_util.h"
29 
30 namespace OHOS {
31 namespace ResourceSchedule {
32 using namespace OHOS::Security;
33 namespace {
34     #define PAYLOAD_MAX_SIZE 4096
35     constexpr int32_t MEMMGR_UID = 1111;
36     constexpr int32_t SAMGR_UID = 5555;
37     constexpr int32_t FOUNDATION_UID = 5523;
38     constexpr int32_t GRAPHIC_UID = 1003;
39     constexpr int32_t HIVIEW_UID = 1201;
40     constexpr int32_t SINGLE_UID_REQUEST_LIMIT_COUNT = 250;
41     constexpr int32_t ALL_UID_REQUEST_LIMIT_COUNT = 650;
42     constexpr int32_t LIMIT_REQUEST_TIME = 1000;
43     constexpr int64_t FOUR_HOUR_TIME = 4 * 60 * 60 * 1000;
44     static const std::unordered_set<uint32_t> scbRes = {
45         ResType::SYNC_RES_TYPE_THAW_ONE_APP,
46         ResType::RES_TYPE_REPORT_SCENE_BOARD,
47         ResType::RES_TYPE_SHOW_REMOTE_ANIMATION,
48         ResType::RES_TYPE_KEY_PERF_SCENE,
49         ResType::RES_TYPE_MOVE_WINDOW,
50         ResType::RES_TYPE_RESIZE_WINDOW,
51         ResType::RES_TYPE_ONLY_PERF_APP_COLD_START,
52         ResType::RES_TYPE_SCENE_ROTATION,
53         ResType::SYNC_RES_TYPE_CHECK_MUTEX_BEFORE_START,
54         ResType::RES_TYPE_COSMIC_CUBE_STATE_CHANGE,
55     };
56     static const std::unordered_set<uint32_t> thirdPartRes_ = {
57         ResType::RES_TYPE_CLICK_RECOGNIZE,
58         ResType::RES_TYPE_PUSH_PAGE,
59         ResType::RES_TYPE_SLIDE_RECOGNIZE,
60         ResType::RES_TYPE_POP_PAGE,
61         ResType::RES_TYPE_LOAD_PAGE,
62         ResType::RES_TYPE_WEB_GESTURE,
63         ResType::RES_TYPE_REPORT_KEY_THREAD,
64         ResType::RES_TYPE_REPORT_WINDOW_STATE,
65         ResType::RES_TYPE_REPORT_SCENE_SCHED,
66         ResType::RES_TYPE_WEB_GESTURE_MOVE,
67         ResType::RES_TYPE_WEB_SLIDE_NORMAL,
68         ResType::RES_TYPE_LOAD_URL,
69         ResType::RES_TYPE_MOUSEWHEEL,
70         ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE,
71         ResType::RES_TYPE_REPORT_RENDER_THREAD,
72         ResType::RES_TYPE_LONG_FRAME,
73         ResType::RES_TYPE_AUDIO_SILENT_PLAYBACK,
74         ResType::RES_TYPE_REPORT_DISTRIBUTE_TID,
75         ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE,
76         ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE,
77         ResType::RES_TYPE_BT_SERVICE_EVENT,
78         ResType::RES_TYPE_APP_FRAME_DROP,
79     };
80     static const std::unordered_set<uint32_t> saRes_ = {
81         ResType::SYNC_RES_TYPE_THAW_ONE_APP,
82         ResType::SYNC_RES_TYPE_GET_ALL_SUSPEND_STATE,
83         ResType::SYNC_RES_TYPE_GET_THERMAL_DATA,
84         ResType::RES_TYPE_CLICK_RECOGNIZE,
85         ResType::RES_TYPE_SCREEN_STATUS,
86         ResType::RES_TYPE_APP_STATE_CHANGE,
87         ResType::RES_TYPE_ABILITY_STATE_CHANGE,
88         ResType::RES_TYPE_EXTENSION_STATE_CHANGE,
89         ResType::RES_TYPE_PROCESS_STATE_CHANGE,
90         ResType::RES_TYPE_WINDOW_FOCUS,
91         ResType::RES_TYPE_TRANSIENT_TASK,
92         ResType::RES_TYPE_CONTINUOUS_TASK,
93         ResType::RES_TYPE_CGROUP_ADJUSTER,
94         ResType::RES_TYPE_WINDOW_VISIBILITY_CHANGE,
95         ResType::RES_TYPE_REPORT_MMI_PROCESS,
96         ResType::RES_TYPE_APP_INSTALL_UNINSTALL,
97         ResType::RES_TYPE_WIFI_CONNECT_STATE_CHANGE,
98         ResType::RES_TYPE_USER_SWITCH,
99         ResType::RES_TYPE_USER_REMOVE,
100         ResType::RES_TYPE_SCREEN_LOCK,
101         ResType::RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE,
102         ResType::RES_TYPE_NETWORK_LATENCY_REQUEST,
103         ResType::RES_TYPE_CALL_STATE_UPDATE,
104         ResType::RES_TYPE_THREAD_QOS_CHANGE,
105         ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
106         ResType::RES_TYPE_AUDIO_RING_MODE_CHANGE,
107         ResType::RES_TYPE_AUDIO_VOLUME_KEY_CHANGE,
108         ResType::RES_TYPE_APP_ABILITY_START,
109         ResType::RES_TYPE_DEVICE_STILL_STATE_CHANGE,
110         ResType::RES_TYPE_RESIZE_WINDOW,
111         ResType::RES_TYPE_MOVE_WINDOW,
112         ResType::RES_TYPE_SHOW_REMOTE_ANIMATION,
113         ResType::RES_TYPE_REPORT_CAMERA_STATE,
114         ResType::RES_TYPE_RUNNINGLOCK_STATE,
115         ResType::RES_TYPE_DRAG_STATUS_BAR,
116         ResType::RES_TYPE_REPORT_SCENE_BOARD,
117         ResType::RES_TYPE_MMI_INPUT_STATE,
118         ResType::RES_TYPE_ANCO_CUST,
119         ResType::RES_TYPE_TIMEZONE_CHANGED,
120         ResType::RES_TYPE_CONNECTION_OBSERVER,
121         ResType::RES_TYPE_AV_SESSION_ON_SESSION_CREATE,
122         ResType::RES_TYPE_AV_SESSION_ON_SESSION_RELEASE,
123         ResType::RES_TYPE_AV_SESSION_ON_TOP_SESSION_CHANGE,
124         ResType::RES_TYPE_ON_APP_STATE_CHANGED,
125         ResType::RES_TYPE_EFFICIENCY_RESOURCES_STATE_CHANGED,
126         ResType::RES_TYPE_AV_CODEC_STATE,
127         ResType::RES_TYPE_NITZ_TIME_CHANGED,
128         ResType::RES_TYPE_TIME_CHANGED,
129         ResType::RES_TYPE_NITZ_TIMEZONE_CHANGED,
130         ResType::RES_TYPE_CHARGING_DISCHARGING,
131         ResType::RES_TYPE_USB_DEVICE,
132         ResType::RES_TYPE_CALL_STATE_CHANGED,
133         ResType::RES_TYPE_WIFI_P2P_STATE_CHANGED,
134         ResType::RES_TYPE_APP_ASSOCIATED_START,
135         ResType::RES_TYPE_THERMAL_STATE,
136         ResType::RES_TYPE_SOCPERF_CUST_EVENT_BEGIN,
137         ResType::RES_TYPE_SOCPERF_CUST_EVENT_END,
138         ResType::RES_TYPE_KEY_PERF_SCENE,
139         ResType::RES_TYPE_SUPER_LAUNCHER,
140         ResType::RES_TYPE_CAST_SCREEN,
141         ResType::RES_TYPR_SCREEN_COLLABROATION,
142         ResType::RES_TYPE_REPORT_SCREEN_CAPTURE,
143         ResType::RES_TYPE_SA_CONTROL_APP_EVENT,
144         ResType::RES_TYPE_LOCATION_STATUS_CHANGE,
145         ResType::RES_TYPE_REPORT_DISTRIBUTE_COMPONENT_CHANGE,
146         ResType::RES_TYPE_SYSTEM_CPU_LOAD,
147         ResType::RES_TYPE_UPLOAD_DOWNLOAD,
148         ResType::RES_TYPE_SPLIT_SCREEN,
149         ResType::RES_TYPE_FLOATING_WINDOW,
150         ResType::RES_TYPE_FRAME_RATE_REPORT,
151         ResType::RES_TYPE_BOOT_COMPLETED,
152         ResType::RES_TYPE_CONTINUOUS_STARTUP,
153         ResType::RES_TYPE_THERMAL_SCENARIO_REPORT,
154         ResType::RES_TYPE_FORM_STATE_CHANGE_EVENT,
155         ResType::RES_TYPE_AUDIO_RENDERER_SILENT_PLAYBACK,
156         ResType::RES_TYPE_REPORT_GAME_SCHED,
157         ResType::RES_TYPE_SEND_FRAME_EVENT,
158         ResType::RES_TYPE_DEVICE_IDLE,
159         ResType::RES_TYPE_BT_SERVICE_EVENT,
160         ResType::RES_TYPE_BMM_MONITER_CHANGE_EVENT,
161         ResType::SYNC_RES_TYPE_REQUEST_MUTEX_STATUS,
162         ResType::RES_TYPE_CLOUD_CONFIG_UPDATE,
163         ResType::RES_TYPE_RSS_CLOUD_CONFIG_UPDATE,
164         ResType::SYNC_RES_TYPE_GET_NWEB_PRELOAD_SET,
165         ResType::RES_TYPE_AUDIO_RENDERER_STANDBY,
166         ResType::RES_TYPE_APP_GAME_BOOST_EVENT,
167     };
168     const std::string NEEDED_PERMISSION = "ohos.permission.REPORT_RESOURCE_SCHEDULE_EVENT";
169     const std::string SCENEBOARD_BUNDLE_NAME = "com.ohos.sceneboard";
170 
IsValidToken(MessageParcel & data)171     bool IsValidToken(MessageParcel& data)
172     {
173         std::u16string descriptor = ResSchedServiceStub::GetDescriptor();
174         std::u16string remoteDescriptor = data.ReadInterfaceToken();
175         return descriptor == remoteDescriptor;
176     }
177 
IsHasPermission(const uint32_t type,const std::unordered_set<uint32_t> & saRes)178     bool IsHasPermission(const uint32_t type, const std::unordered_set<uint32_t>& saRes)
179     {
180         if (saRes.find(type) == saRes.end()) {
181             RESSCHED_LOGE("resType:%{public}d not sa report", type);
182             return false;
183         }
184         AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
185         auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
186         if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
187             RESSCHED_LOGE("not native sa");
188             return false;
189         }
190         int32_t hasPermission = AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, NEEDED_PERMISSION);
191         if (hasPermission != 0) {
192             RESSCHED_LOGE("not have permission");
193             return false;
194         }
195         return true;
196     }
197 
IsTypeVaild(const uint32_t type)198     bool IsTypeVaild(const uint32_t type)
199     {
200         return type >= ResType::RES_TYPE_FIRST && type < ResType::RES_TYPE_LAST;
201     }
202 
IsThirdPartType(const uint32_t type,const std::unordered_set<uint32_t> & thirdPartRes)203     bool IsThirdPartType(const uint32_t type, const std::unordered_set<uint32_t>& thirdPartRes)
204     {
205         if (thirdPartRes.find(type) == thirdPartRes.end()) {
206             RESSCHED_LOGD("resType:%{public}d not hap app report", type);
207             return false;
208         }
209         AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
210         auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
211         if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
212             RESSCHED_LOGE("not hap app");
213             return false;
214         }
215 
216         return true;
217     }
218 
IsSBDResType(uint32_t type)219     bool IsSBDResType(uint32_t type)
220     {
221         if (scbRes.find(type) == scbRes.end()) {
222             return false;
223         }
224         AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
225         auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
226         if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
227             return false;
228         }
229         AccessToken::HapTokenInfo callingTokenInfo;
230         AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, callingTokenInfo);
231         if (callingTokenInfo.bundleName == SCENEBOARD_BUNDLE_NAME) {
232             return true;
233         }
234         RESSCHED_LOGE("%{public}s is not sceneboard bundle name", callingTokenInfo.bundleName.c_str());
235         return false;
236     }
237 }
238 
ResSchedServiceStub()239 ResSchedServiceStub::ResSchedServiceStub()
240 {
241     Init();
242 }
243 
~ResSchedServiceStub()244 ResSchedServiceStub::~ResSchedServiceStub()
245 {
246 }
247 
ReportDataInner(MessageParcel & data,MessageParcel & reply)248 int32_t ResSchedServiceStub::ReportDataInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply)
249 {
250     uint32_t type = 0;
251     int64_t value = 0;
252     std::string payload;
253     int32_t ret = ParseAndCheckReportDataParcel(data, type, value, payload);
254     if (ret != ERR_OK) {
255         RESSCHED_LOGE("%{public}s: parse fail=%{public}d type=%{public}u", __func__, ret, type);
256         return ret;
257     }
258 
259     ReportData(type, value, StringToJsonObj(payload));
260     return ERR_OK;
261 }
262 
ParseAndCheckReportDataParcel(MessageParcel & data,uint32_t & type,int64_t & value,std::string & payload)263 int32_t ResSchedServiceStub::ParseAndCheckReportDataParcel(MessageParcel& data, uint32_t& type, int64_t& value,
264     std::string& payload)
265 {
266     if (!IsValidToken(data)) {
267         return ERR_RES_SCHED_PARCEL_ERROR;
268     }
269 
270     READ_PARCEL(data, Uint32, type, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
271     if (!IsTypeVaild(type)) {
272         RESSCHED_LOGE("type:%{public}u is invalid", type);
273         return ERR_RES_SCHED_PARCEL_ERROR;
274     }
275     if (!IsSBDResType(type) && !IsThirdPartType(type, thirdPartRes_) && !IsHasPermission(type, saRes_)) {
276         RESSCHED_LOGE("type:%{public}u, no permission", type);
277         return ERR_RES_SCHED_PERMISSION_DENIED;
278     }
279 
280     READ_PARCEL(data, Int64, value, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
281     READ_PARCEL(data, String, payload, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
282     if (payload.size() > PAYLOAD_MAX_SIZE) {
283         RESSCHED_LOGE("too long payload.size:%{public}u", (uint32_t)payload.size());
284         return ERR_RES_SCHED_PARCEL_ERROR;
285     }
286     return ERR_OK;
287 }
288 
ReportSyncEventInner(MessageParcel & input,MessageParcel & output)289 int32_t ResSchedServiceStub::ReportSyncEventInner(MessageParcel& input, MessageParcel& output)
290 {
291     uint32_t type = 0;
292     int64_t value = 0;
293     std::string payloadStr;
294     int32_t ret = ParseAndCheckReportDataParcel(input, type, value, payloadStr);
295     if (ret != ERR_OK) {
296         RESSCHED_LOGE("%{public}s: parse fail=%{public}d type=%{public}u", __func__, ret, type);
297         return ret;
298     }
299 
300     nlohmann::json payload = StringToJsonObj(payloadStr);
301     int32_t clientPid = IPCSkeleton::GetCallingPid();
302     int32_t callingUid = IPCSkeleton::GetCallingUid();
303     payload["clientPid"] = std::to_string(clientPid);
304     payload["callingUid"] = std::to_string(callingUid);
305     nlohmann::json reply;
306     ret = ReportSyncEvent(type, value, payload, reply);
307     RESSCHED_LOGD("%{public}s: clientPid=%{public}d, callingUid=%{public}d, type=%{public}u, value=%{public}lld, "
308                   "ret=%{public}d", __func__, clientPid, callingUid, type, (long long)value, ret);
309     WRITE_PARCEL(output, Int32, ret, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
310     WRITE_PARCEL(output, String, reply.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace),
311         ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
312     return ret;
313 }
314 
KillProcessInner(MessageParcel & data,MessageParcel & reply)315 int32_t ResSchedServiceStub::KillProcessInner(MessageParcel& data, MessageParcel& reply)
316 {
317     if (!IsValidToken(data)) {
318         return ERR_RES_SCHED_PARCEL_ERROR;
319     }
320     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
321     int32_t uid = IPCSkeleton::GetCallingUid();
322     Security::AccessToken::ATokenTypeEnum tokenTypeFlag =
323         Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(accessToken);
324     if ((uid != MEMMGR_UID && uid != SAMGR_UID && uid != HIVIEW_UID && uid != GRAPHIC_UID)
325         || tokenTypeFlag != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
326         RESSCHED_LOGE("no permission, kill process fail");
327         return RES_SCHED_KILL_PROCESS_FAIL;
328     }
329     std::string payload;
330     READ_PARCEL(data, String, payload, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
331     if (payload.size() <= PAYLOAD_MAX_SIZE) {
332         int32_t status = KillProcess(StringToJsonObj(payload));
333         reply.WriteInt32(status);
334     } else {
335         reply.WriteInt32(RES_SCHED_DATA_ERROR);
336         RESSCHED_LOGE("The payload is too long. DoS.");
337     }
338     return ERR_OK;
339 }
340 
RegisterSystemloadNotifierInner(MessageParcel & data,MessageParcel & reply)341 void ResSchedServiceStub::RegisterSystemloadNotifierInner(MessageParcel& data,
342                                                           [[maybe_unused]] MessageParcel& reply)
343 {
344     if (!IsValidToken(data)) {
345         RESSCHED_LOGE("Register invalid token.");
346         return;
347     }
348     sptr<IRemoteObject> notifier = data.ReadRemoteObject();
349     if (notifier == nullptr) {
350         RESSCHED_LOGE("ResSchedServiceStub Read notifier fail.");
351         return;
352     }
353     RegisterSystemloadNotifier(notifier);
354 }
355 
UnRegisterSystemloadNotifierInner(MessageParcel & data,MessageParcel & reply)356 void ResSchedServiceStub::UnRegisterSystemloadNotifierInner(MessageParcel& data,
357                                                             [[maybe_unused]] MessageParcel& reply)
358 {
359     if (!IsValidToken(data)) {
360         RESSCHED_LOGE("UnRegister invalid token.");
361         return;
362     }
363     UnRegisterSystemloadNotifier();
364 }
365 
GetSystemloadLevelInner(MessageParcel & data,MessageParcel & reply)366 int32_t ResSchedServiceStub::GetSystemloadLevelInner(MessageParcel& data, MessageParcel& reply)
367 {
368     if (!IsValidToken(data)) {
369         RESSCHED_LOGE("GetSystemload level invalid token.");
370         return ERR_RES_SCHED_PARCEL_ERROR;
371     }
372     int32_t level = GetSystemloadLevel();
373     if (!reply.WriteInt32(level)) {
374         RESSCHED_LOGE("GetSystemload level write reply failed.");
375         return ERR_RES_SCHED_PARCEL_ERROR;
376     }
377     return ERR_OK;
378 }
379 
IsAllowedAppPreloadInner(MessageParcel & data,MessageParcel & reply)380 bool ResSchedServiceStub::IsAllowedAppPreloadInner(MessageParcel& data, MessageParcel& reply)
381 {
382     if (!IsValidToken(data)) {
383         return false;
384     }
385     AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
386     int32_t uid = IPCSkeleton::GetCallingUid();
387     AccessToken::ATokenTypeEnum tokenTypeFlag = AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
388     if (uid != FOUNDATION_UID || tokenTypeFlag != AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
389         RESSCHED_LOGE("Invalid calling token");
390         return false;
391     }
392 
393     std::string bundleName {""};
394     int32_t preloadMode {0};
395     if (!data.ReadString(bundleName) || !data.ReadInt32(preloadMode)) {
396         RESSCHED_LOGE("IsAllowedAppPreloadInner ReadParcelable failed");
397         return false;
398     }
399     bool isAllowedPreload = IsAllowedAppPreload(bundleName, preloadMode);
400     if (!reply.WriteBool(isAllowedPreload)) {
401         RESSCHED_LOGE("IsAllowedAppPreloadInner write isAllowedPreload failed");
402         return false;
403     }
404     return true;
405 }
406 
RegisterEventListenerInner(MessageParcel & data,MessageParcel & reply)407 void ResSchedServiceStub::RegisterEventListenerInner(MessageParcel& data,
408     [[maybe_unused]] MessageParcel& reply)
409 {
410     if (!IsValidToken(data)) {
411         RESSCHED_LOGE("%{public}s:Register invalid token.", __func__);
412         return;
413     }
414     uint32_t eventType = ResType::EventType::EVENT_START;
415     uint32_t listenerGroup = ResType::EventListenerGroup::LISTENER_GROUP_COMMON;
416     sptr<IRemoteObject> listener =data.ReadRemoteObject();
417     if (listener == nullptr) {
418         RESSCHED_LOGE("%{public}s:read listener is null.", __func__);
419         return;
420     }
421     READ_PARCEL(data, Uint32, eventType, void(), ResSchedServiceStub);
422     READ_PARCEL(data, Uint32, listenerGroup, void(), ResSchedServiceStub);
423     if (listener == nullptr || eventType == ResType::EventType::EVENT_START) {
424         RESSCHED_LOGE("%{public}s:parse parcel failed.", __func__);
425         return;
426     }
427     RegisterEventListener(listener, eventType, listenerGroup);
428 }
429 
UnRegisterEventListenerInner(MessageParcel & data,MessageParcel & reply)430 void ResSchedServiceStub::UnRegisterEventListenerInner(MessageParcel& data,
431     [[maybe_unused]] MessageParcel& reply)
432 {
433     if (!IsValidToken(data)) {
434         RESSCHED_LOGE("UnRegister invalid token.");
435         return;
436     }
437     uint32_t eventType = ResType::EventType::EVENT_START;
438     uint32_t listenerGroup = ResType::EventListenerGroup::LISTENER_GROUP_COMMON;
439     READ_PARCEL(data, Uint32, eventType, void(), ResSchedServiceStub);
440     READ_PARCEL(data, Uint32, listenerGroup, void(), ResSchedServiceStub);
441     UnRegisterEventListener(eventType, listenerGroup);
442 }
443 
IsLimitRequest(int32_t uid)444 bool ResSchedServiceStub::IsLimitRequest(int32_t uid)
445 {
446     int64_t nowTime = ResCommonUtil::GetNowMillTime();
447     std::lock_guard<std::mutex> lock(mutex_);
448     CheckAndUpdateLimitData(nowTime);
449     if (allRequestCount_.load() >= ALL_UID_REQUEST_LIMIT_COUNT) {
450         RESSCHED_LOGD("all uid request is limit, %{public}d request fail", uid);
451         return true;
452     }
453     auto iter = appRequestCountMap_.find(uid);
454     if (iter == appRequestCountMap_.end()) {
455         appRequestCountMap_[uid] = 1;
456         allRequestCount_ ++;
457         return false;
458     }
459     if (appRequestCountMap_[uid] >= SINGLE_UID_REQUEST_LIMIT_COUNT) {
460         RESSCHED_LOGD("uid:%{public}d request is limit, request fail", uid);
461         return true;
462     }
463     appRequestCountMap_[uid] ++;
464     allRequestCount_ ++;
465     return false;
466 }
467 
CheckAndUpdateLimitData(int64_t nowTime)468 void ResSchedServiceStub::CheckAndUpdateLimitData(int64_t nowTime)
469 {
470     if (nowTime - nextCheckTime_.load() > LIMIT_REQUEST_TIME) {
471         nextCheckTime_.store(nowTime + LIMIT_REQUEST_TIME);
472         appRequestCountMap_.clear();
473         allRequestCount_.store(0);
474         isPrintLimitLog_.store(true);
475     }
476 }
477 
PrintLimitLog(int32_t uid)478 void ResSchedServiceStub::PrintLimitLog(int32_t uid)
479 {
480     if (isPrintLimitLog_.load()) {
481         isPrintLimitLog_.store(false);
482         RESSCHED_LOGI("request limit, allRequestCount_:%{public}d, cur report uid:%{public}d",
483             allRequestCount_.load(), uid);
484     }
485 }
486 
ReportBigData()487 void ResSchedServiceStub::ReportBigData()
488 {
489     if (!isReportBigData_.load()) {
490         return;
491     }
492     if (ResCommonUtil::GetNowMillTime() < nextReportBigDataTime_) {
493         return;
494     }
495     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "SERVICE_REQUEST_LIMIT",
496                     HiviewDFX::HiSysEvent::EventType::FAULT, "REQUEST_LIMIT_COUNT", bigDataReportCount_.load());
497     isReportBigData_.store(false);
498     bigDataReportCount_.store(0);
499 }
500 
InreaseBigDataCount()501 void ResSchedServiceStub::InreaseBigDataCount()
502 {
503     if (!isReportBigData_.load()) {
504         isReportBigData_.store(true);
505         nextReportBigDataTime_ = ResCommonUtil::GetNowMillTime() + FOUR_HOUR_TIME;
506     }
507     bigDataReportCount_ ++;
508 }
509 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)510 int32_t ResSchedServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
511     MessageParcel &reply, MessageOption &option)
512 {
513     ReportBigData();
514     auto uid = IPCSkeleton::GetCallingUid();
515     RESSCHED_LOGD("ResSchedServiceStub::OnRemoteRequest, code = %{public}u, flags = %{public}d,"
516         " uid = %{public}d.", code, option.GetFlags(), uid);
517     if (IsLimitRequest(uid)) {
518         RESSCHED_LOGD("%{public}d is limit request, cur request fail", uid);
519         InreaseBigDataCount();
520         PrintLimitLog(uid);
521         return RES_SCHED_REQUEST_FAIL;
522     }
523     switch (code) {
524         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REPORT_DATA):
525             return ReportDataInner(data, reply);
526         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REPORT_SYNC_EVENT):
527             return ReportSyncEventInner(data, reply);
528         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::KILL_PROCESS):
529             return KillProcessInner(data, reply);
530         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REGISTER_SYSTEMLOAD_NOTIFIER):
531             RegisterSystemloadNotifierInner(data, reply);
532             return ERR_OK;
533         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::UNREGISTER_SYSTEMLOAD_NOTIFIER):
534             UnRegisterSystemloadNotifierInner(data, reply);
535             return ERR_OK;
536         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::GET_SYSTEMLOAD_LEVEL):
537             return GetSystemloadLevelInner(data, reply);
538         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::TOUCH_DOWN_APP_PRELOAD):
539             return IsAllowedAppPreloadInner(data, reply);
540         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REGISTER_EVENT_LISTENER):
541             RegisterEventListenerInner(data, reply);
542             return ERR_OK;
543         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::UNREGISTER_EVENT_LISTENER):
544             UnRegisterEventListenerInner(data, reply);
545             return ERR_OK;
546         default:
547             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
548     }
549 }
550 
StringToJsonObj(const std::string & payload)551 nlohmann::json ResSchedServiceStub::StringToJsonObj(const std::string& payload)
552 {
553     nlohmann::json jsonObj = nlohmann::json::object();
554     if (payload.empty()) {
555         return jsonObj;
556     }
557     nlohmann::json jsonTmp = nlohmann::json::parse(payload, nullptr, false);
558     if (jsonTmp.is_discarded()) {
559         RESSCHED_LOGE("%{public}s parse payload to json failed: %{public}s.", __func__, payload.c_str());
560         return jsonObj;
561     }
562     if (!jsonTmp.is_object()) {
563         RESSCHED_LOGD("%{public}s payload converted result is not a jsonObj: %{public}s.", __func__, payload.c_str());
564         return jsonObj;
565     }
566     return jsonTmp;
567 }
568 
Init()569 void ResSchedServiceStub::Init()
570 {
571 }
572 } // namespace ResourceSchedule
573 } // namespace OHOS
574