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