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