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