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_APP_FRAME_DROP,
78         ResType::RES_TYPE_BT_SERVICE_EVENT,
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_SILENT_PLAYBACK,
156         ResType::RES_TYPE_AUDIO_RENDERER_SILENT_PLAYBACK,
157         ResType::RES_TYPE_REPORT_GAME_SCHED,
158         ResType::RES_TYPE_SEND_FRAME_EVENT,
159         ResType::RES_TYPE_BMM_MONITER_CHANGE_EVENT,
160         ResType::SYNC_RES_TYPE_REQUEST_MUTEX_STATUS,
161         ResType::RES_TYPE_CLOUD_CONFIG_UPDATE,
162         ResType::RES_TYPE_RSS_CLOUD_CONFIG_UPDATE,
163         ResType::RES_TYPE_DEVICE_IDLE,
164         ResType::RES_TYPE_BT_SERVICE_EVENT,
165         ResType::SYNC_RES_TYPE_GET_NWEB_PRELOAD_SET,
166         ResType::RES_TYPE_AUDIO_RENDERER_STANDBY,
167         ResType::RES_TYPE_APP_GAME_BOOST_EVENT,
168     };
169     const std::string NEEDED_PERMISSION = "ohos.permission.REPORT_RESOURCE_SCHEDULE_EVENT";
170     const std::string SCENEBOARD_BUNDLE_NAME = "com.ohos.sceneboard";
171 
IsValidToken(MessageParcel & data)172     bool IsValidToken(MessageParcel& data)
173     {
174         std::u16string descriptor = ResSchedServiceStub::GetDescriptor();
175         std::u16string remoteDescriptor = data.ReadInterfaceToken();
176         return descriptor == remoteDescriptor;
177     }
178 
IsHasPermission(const uint32_t type,const std::unordered_set<uint32_t> & saRes)179     bool IsHasPermission(const uint32_t type, const std::unordered_set<uint32_t>& saRes)
180     {
181         if (saRes.find(type) == saRes.end()) {
182             RESSCHED_LOGE("resType:%{public}d not sa report", type);
183             return false;
184         }
185         AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
186         auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
187         if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
188             RESSCHED_LOGE("not native sa");
189             return false;
190         }
191         int32_t hasPermission = AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, NEEDED_PERMISSION);
192         if (hasPermission != 0) {
193             RESSCHED_LOGE("not have permission");
194             return false;
195         }
196         return true;
197     }
198 
IsTypeVaild(const uint32_t type)199     bool IsTypeVaild(const uint32_t type)
200     {
201         return type >= ResType::RES_TYPE_FIRST && type < ResType::RES_TYPE_LAST;
202     }
203 
IsThirdPartType(const uint32_t type,const std::unordered_set<uint32_t> & thirdPartRes)204     bool IsThirdPartType(const uint32_t type, const std::unordered_set<uint32_t>& thirdPartRes)
205     {
206         if (thirdPartRes.find(type) == thirdPartRes.end()) {
207             RESSCHED_LOGD("resType:%{public}d not hap app report", type);
208             return false;
209         }
210         AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
211         auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
212         if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
213             RESSCHED_LOGE("not hap app");
214             return false;
215         }
216 
217         return true;
218     }
219 
IsSBDResType(uint32_t type)220     bool IsSBDResType(uint32_t type)
221     {
222         if (scbRes.find(type) == scbRes.end()) {
223             return false;
224         }
225         AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
226         auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
227         if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
228             return false;
229         }
230         AccessToken::HapTokenInfo callingTokenInfo;
231         AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, callingTokenInfo);
232         if (callingTokenInfo.bundleName == SCENEBOARD_BUNDLE_NAME) {
233             return true;
234         }
235         RESSCHED_LOGE("%{public}s is not sceneboard bundle name", callingTokenInfo.bundleName.c_str());
236         return false;
237     }
238 }
239 
ResSchedServiceStub()240 ResSchedServiceStub::ResSchedServiceStub()
241 {
242     Init();
243 }
244 
~ResSchedServiceStub()245 ResSchedServiceStub::~ResSchedServiceStub()
246 {
247 }
248 
249 int32_t ResSchedServiceStub::ReportDataInner(MessageParcel& data, [[maybe_unused]] MessageParcel& reply)
250 {
251     uint32_t type = 0;
252     int64_t value = 0;
253     std::string payload;
254     int32_t ret = ParseAndCheckReportDataParcel(data, type, value, payload);
255     if (ret != ERR_OK) {
256         RESSCHED_LOGE("%{public}s: parse fail=%{public}d type=%{public}u", __func__, ret, type);
257         return ret;
258     }
259 
260     ReportData(type, value, StringToJsonObj(payload));
261     return ERR_OK;
262 }
263 
ParseAndCheckReportDataParcel(MessageParcel & data,uint32_t & type,int64_t & value,std::string & payload)264 int32_t ResSchedServiceStub::ParseAndCheckReportDataParcel(MessageParcel& data, uint32_t& type, int64_t& value,
265     std::string& payload)
266 {
267     if (!IsValidToken(data)) {
268         return ERR_RES_SCHED_PARCEL_ERROR;
269     }
270 
271     READ_PARCEL(data, Uint32, type, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
272     if (!IsTypeVaild(type)) {
273         RESSCHED_LOGE("type:%{public}u is invalid", type);
274         return ERR_RES_SCHED_PARCEL_ERROR;
275     }
276     if (!IsSBDResType(type) && !IsThirdPartType(type, thirdPartRes_) && !IsHasPermission(type, saRes_)) {
277         RESSCHED_LOGE("type:%{public}u, no permission", type);
278         return ERR_RES_SCHED_PERMISSION_DENIED;
279     }
280 
281     READ_PARCEL(data, Int64, value, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
282     READ_PARCEL(data, String, payload, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
283     if (payload.size() > PAYLOAD_MAX_SIZE) {
284         RESSCHED_LOGE("too long payload.size:%{public}u", (uint32_t)payload.size());
285         return ERR_RES_SCHED_PARCEL_ERROR;
286     }
287     return ERR_OK;
288 }
289 
ReportSyncEventInner(MessageParcel & input,MessageParcel & output)290 int32_t ResSchedServiceStub::ReportSyncEventInner(MessageParcel& input, MessageParcel& output)
291 {
292     uint32_t type = 0;
293     int64_t value = 0;
294     std::string payloadStr;
295     int32_t ret = ParseAndCheckReportDataParcel(input, type, value, payloadStr);
296     if (ret != ERR_OK) {
297         RESSCHED_LOGE("%{public}s: parse fail=%{public}d type=%{public}u", __func__, ret, type);
298         return ret;
299     }
300 
301     nlohmann::json payload = StringToJsonObj(payloadStr);
302     int32_t clientPid = IPCSkeleton::GetCallingPid();
303     int32_t callingUid = IPCSkeleton::GetCallingUid();
304     payload["clientPid"] = std::to_string(clientPid);
305     payload["callingUid"] = std::to_string(callingUid);
306     nlohmann::json reply;
307     ret = ReportSyncEvent(type, value, payload, reply);
308     RESSCHED_LOGD("%{public}s: clientPid=%{public}d, callingUid=%{public}d, type=%{public}u, value=%{public}lld, "
309                   "ret=%{public}d", __func__, clientPid, callingUid, type, (long long)value, ret);
310     WRITE_PARCEL(output, Int32, ret, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
311     WRITE_PARCEL(output, String, reply.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace),
312         ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
313     return ret;
314 }
315 
KillProcessInner(MessageParcel & data,MessageParcel & reply)316 int32_t ResSchedServiceStub::KillProcessInner(MessageParcel& data, MessageParcel& reply)
317 {
318     if (!IsValidToken(data)) {
319         return ERR_RES_SCHED_PARCEL_ERROR;
320     }
321     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
322     int32_t uid = IPCSkeleton::GetCallingUid();
323     Security::AccessToken::ATokenTypeEnum tokenTypeFlag =
324         Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(accessToken);
325     if ((uid != MEMMGR_UID && uid != SAMGR_UID && uid != HIVIEW_UID && uid != GRAPHIC_UID)
326         || tokenTypeFlag != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
327         RESSCHED_LOGE("no permission, kill process fail");
328         return RES_SCHED_KILL_PROCESS_FAIL;
329     }
330     std::string payload;
331     READ_PARCEL(data, String, payload, ERR_RES_SCHED_PARCEL_ERROR, ResSchedServiceStub);
332     if (payload.size() <= PAYLOAD_MAX_SIZE) {
333         int32_t status = KillProcess(StringToJsonObj(payload));
334         reply.WriteInt32(status);
335     } else {
336         reply.WriteInt32(RES_SCHED_DATA_ERROR);
337         RESSCHED_LOGE("The payload is too long. DoS.");
338     }
339     return ERR_OK;
340 }
341 
342 void ResSchedServiceStub::RegisterSystemloadNotifierInner(MessageParcel& data,
343                                                           [[maybe_unused]] MessageParcel& reply)
344 {
345     if (!IsValidToken(data)) {
346         RESSCHED_LOGE("Register invalid token.");
347         return;
348     }
349     sptr<IRemoteObject> notifier = data.ReadRemoteObject();
350     if (notifier == nullptr) {
351         RESSCHED_LOGE("ResSchedServiceStub Read notifier fail.");
352         return;
353     }
354     RegisterSystemloadNotifier(notifier);
355 }
356 
357 void ResSchedServiceStub::UnRegisterSystemloadNotifierInner(MessageParcel& data,
358                                                             [[maybe_unused]] MessageParcel& reply)
359 {
360     if (!IsValidToken(data)) {
361         RESSCHED_LOGE("UnRegister invalid token.");
362         return;
363     }
364     UnRegisterSystemloadNotifier();
365 }
366 
GetSystemloadLevelInner(MessageParcel & data,MessageParcel & reply)367 int32_t ResSchedServiceStub::GetSystemloadLevelInner(MessageParcel& data, MessageParcel& reply)
368 {
369     if (!IsValidToken(data)) {
370         RESSCHED_LOGE("GetSystemload level invalid token.");
371         return ERR_RES_SCHED_PARCEL_ERROR;
372     }
373     int32_t level = GetSystemloadLevel();
374     if (!reply.WriteInt32(level)) {
375         RESSCHED_LOGE("GetSystemload level write reply failed.");
376         return ERR_RES_SCHED_PARCEL_ERROR;
377     }
378     return ERR_OK;
379 }
380 
IsAllowedAppPreloadInner(MessageParcel & data,MessageParcel & reply)381 bool ResSchedServiceStub::IsAllowedAppPreloadInner(MessageParcel& data, MessageParcel& reply)
382 {
383     if (!IsValidToken(data)) {
384         return false;
385     }
386     AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
387     int32_t uid = IPCSkeleton::GetCallingUid();
388     AccessToken::ATokenTypeEnum tokenTypeFlag = AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
389     if (uid != FOUNDATION_UID || tokenTypeFlag != AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
390         RESSCHED_LOGE("Invalid calling token");
391         return false;
392     }
393 
394     std::string bundleName {""};
395     int32_t preloadMode {0};
396     if (!data.ReadString(bundleName) || !data.ReadInt32(preloadMode)) {
397         RESSCHED_LOGE("IsAllowedAppPreloadInner ReadParcelable failed");
398         return false;
399     }
400     bool isAllowedPreload = IsAllowedAppPreload(bundleName, preloadMode);
401     if (!reply.WriteBool(isAllowedPreload)) {
402         RESSCHED_LOGE("IsAllowedAppPreloadInner write isAllowedPreload failed");
403         return false;
404     }
405     return true;
406 }
407 
408 void ResSchedServiceStub::RegisterEventListenerInner(MessageParcel& data,
409     [[maybe_unused]] MessageParcel& reply)
410 {
411     if (!IsValidToken(data)) {
412         RESSCHED_LOGE("%{public}s:Register invalid token.", __func__);
413         return;
414     }
415     uint32_t eventType = ResType::EventType::EVENT_START;
416     uint32_t listenerGroup = ResType::EventListenerGroup::LISTENER_GROUP_COMMON;
417     sptr<IRemoteObject> listener =data.ReadRemoteObject();
418     if (listener == nullptr) {
419         RESSCHED_LOGE("%{public}s:read listener is null.", __func__);
420         return;
421     }
422     READ_PARCEL(data, Uint32, eventType, void(), ResSchedServiceStub);
423     READ_PARCEL(data, Uint32, listenerGroup, void(), ResSchedServiceStub);
424     if (listener == nullptr || eventType == ResType::EventType::EVENT_START) {
425         RESSCHED_LOGE("%{public}s:parse parcel failed.", __func__);
426         return;
427     }
428     RegisterEventListener(listener, eventType, listenerGroup);
429 }
430 
431 void ResSchedServiceStub::UnRegisterEventListenerInner(MessageParcel& data,
432     [[maybe_unused]] MessageParcel& reply)
433 {
434     if (!IsValidToken(data)) {
435         RESSCHED_LOGE("UnRegister invalid token.");
436         return;
437     }
438     uint32_t eventType = ResType::EventType::EVENT_START;
439     uint32_t listenerGroup = ResType::EventListenerGroup::LISTENER_GROUP_COMMON;
440     READ_PARCEL(data, Uint32, eventType, void(), ResSchedServiceStub);
441     READ_PARCEL(data, Uint32, listenerGroup, void(), ResSchedServiceStub);
442     UnRegisterEventListener(eventType, listenerGroup);
443 }
444 
IsLimitRequest(int32_t uid)445 bool ResSchedServiceStub::IsLimitRequest(int32_t uid)
446 {
447     int64_t nowTime = ResCommonUtil::GetNowMillTime();
448     std::lock_guard<std::mutex> lock(mutex_);
449     CheckAndUpdateLimitData(nowTime);
450     if (allRequestCount_.load() >= ALL_UID_REQUEST_LIMIT_COUNT) {
451         RESSCHED_LOGD("all uid request is limit, %{public}d request fail", uid);
452         return true;
453     }
454     auto iter = appRequestCountMap_.find(uid);
455     if (iter == appRequestCountMap_.end()) {
456         appRequestCountMap_[uid] = 1;
457         allRequestCount_ ++;
458         return false;
459     }
460     if (appRequestCountMap_[uid] >= SINGLE_UID_REQUEST_LIMIT_COUNT) {
461         RESSCHED_LOGD("uid:%{public}d request is limit, request fail", uid);
462         return true;
463     }
464     appRequestCountMap_[uid] ++;
465     allRequestCount_ ++;
466     return false;
467 }
468 
CheckAndUpdateLimitData(int64_t nowTime)469 void ResSchedServiceStub::CheckAndUpdateLimitData(int64_t nowTime)
470 {
471     if (nowTime - nextCheckTime_.load() > LIMIT_REQUEST_TIME) {
472         nextCheckTime_.store(nowTime + LIMIT_REQUEST_TIME);
473         appRequestCountMap_.clear();
474         allRequestCount_.store(0);
475         isPrintLimitLog_.store(true);
476     }
477 }
478 
PrintLimitLog(int32_t uid)479 void ResSchedServiceStub::PrintLimitLog(int32_t uid)
480 {
481     if (isPrintLimitLog_.load()) {
482         isPrintLimitLog_.store(false);
483         RESSCHED_LOGI("request limit, allRequestCount_:%{public}d, cur report uid:%{public}d",
484             allRequestCount_.load(), uid);
485     }
486 }
487 
ReportBigData()488 void ResSchedServiceStub::ReportBigData()
489 {
490     if (!isReportBigData_.load()) {
491         return;
492     }
493     if (ResCommonUtil::GetNowMillTime() < nextReportBigDataTime_) {
494         return;
495     }
496     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "SERVICE_REQUEST_LIMIT",
497                     HiviewDFX::HiSysEvent::EventType::FAULT, "REQUEST_LIMIT_COUNT", bigDataReportCount_.load());
498     isReportBigData_.store(false);
499     bigDataReportCount_.store(0);
500 }
501 
InreaseBigDataCount()502 void ResSchedServiceStub::InreaseBigDataCount()
503 {
504     if (!isReportBigData_.load()) {
505         isReportBigData_.store(true);
506         nextReportBigDataTime_ = ResCommonUtil::GetNowMillTime() + FOUR_HOUR_TIME;
507     }
508     bigDataReportCount_ ++;
509 }
510 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)511 int32_t ResSchedServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
512     MessageParcel &reply, MessageOption &option)
513 {
514     ReportBigData();
515     auto uid = IPCSkeleton::GetCallingUid();
516     RESSCHED_LOGD("ResSchedServiceStub::OnRemoteRequest, code = %{public}u, flags = %{public}d,"
517         " uid = %{public}d.", code, option.GetFlags(), uid);
518     if (IsLimitRequest(uid)) {
519         RESSCHED_LOGD("%{public}d is limit request, cur request fail", uid);
520         InreaseBigDataCount();
521         PrintLimitLog(uid);
522         return RES_SCHED_REQUEST_FAIL;
523     }
524     switch (code) {
525         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REPORT_DATA):
526             return ReportDataInner(data, reply);
527         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REPORT_SYNC_EVENT):
528             return ReportSyncEventInner(data, reply);
529         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::KILL_PROCESS):
530             return KillProcessInner(data, reply);
531         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REGISTER_SYSTEMLOAD_NOTIFIER):
532             RegisterSystemloadNotifierInner(data, reply);
533             return ERR_OK;
534         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::UNREGISTER_SYSTEMLOAD_NOTIFIER):
535             UnRegisterSystemloadNotifierInner(data, reply);
536             return ERR_OK;
537         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::GET_SYSTEMLOAD_LEVEL):
538             return GetSystemloadLevelInner(data, reply);
539         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::TOUCH_DOWN_APP_PRELOAD):
540             return IsAllowedAppPreloadInner(data, reply);
541         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::REGISTER_EVENT_LISTENER):
542             RegisterEventListenerInner(data, reply);
543             return ERR_OK;
544         case static_cast<uint32_t>(ResourceScheduleInterfaceCode::UNREGISTER_EVENT_LISTENER):
545             UnRegisterEventListenerInner(data, reply);
546             return ERR_OK;
547         default:
548             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
549     }
550 }
551 
StringToJsonObj(const std::string & payload)552 nlohmann::json ResSchedServiceStub::StringToJsonObj(const std::string& payload)
553 {
554     nlohmann::json jsonObj = nlohmann::json::object();
555     if (payload.empty()) {
556         return jsonObj;
557     }
558     nlohmann::json jsonTmp = nlohmann::json::parse(payload, nullptr, false);
559     if (jsonTmp.is_discarded()) {
560         RESSCHED_LOGE("%{public}s parse payload to json failed: %{public}s.", __func__, payload.c_str());
561         return jsonObj;
562     }
563     if (!jsonTmp.is_object()) {
564         RESSCHED_LOGD("%{public}s payload converted result is not a jsonObj: %{public}s.", __func__, payload.c_str());
565         return jsonObj;
566     }
567     return jsonTmp;
568 }
569 
Init()570 void ResSchedServiceStub::Init()
571 {
572 }
573 } // namespace ResourceSchedule
574 } // namespace OHOS
575