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