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 #include "res_sched_client.h"
16 #include <string> // for to_string
17 #include <unistd.h> // for getpid
18 #include <new> // for nothrow, operator new
19 #include <unordered_map> // for unordered_map, __hash_map_con...
20 #include <utility> // for pair
21 #include "if_system_ability_manager.h" // for ISystemAbilityManager
22 #include "iremote_broker.h" // for iface_cast
23 #include "iservice_registry.h" // for SystemAbilityManagerClient
24 #include "res_sched_errors.h" // for GET_RES_SCHED_SERVICE_FAILED
25 #include "res_sched_log.h" // for RESSCHED_LOGE, RESSCHED_LOGD
26 #include "system_ability_definition.h" // for RES_SCHED_SYS_ABILITY_ID
27 #include "ffrt_inner.h" // for future
28
29 namespace OHOS {
30 namespace ResourceSchedule {
31 namespace {
32 constexpr int32_t CHECK_MUTEX_TIMEOUT = 100; // 100ms
33 constexpr int32_t CHECK_MUTEX_TIMEOUT_NS = 100 * 1000; // 100ms
34 bool g_isDestroyed = false;
35 }
36
GetInstance()37 ResSchedClient& ResSchedClient::GetInstance()
38 {
39 static ResSchedClient instance;
40 return instance;
41 }
~ResSchedClient()42 ResSchedClient::~ResSchedClient()
43 {
44 std::lock_guard<std::mutex> lock(mutex_);
45 g_isDestroyed = true;
46 if (rss_ && rss_->AsObject()) {
47 rss_->AsObject()->RemoveDeathRecipient(recipient_);
48 }
49 rss_ = nullptr;
50 systemloadCbRegistered_ = false;
51 registeredInnerEvents.clear();
52 }
53
StringToJsonObj(const std::string & str)54 nlohmann::json StringToJsonObj(const std::string& str)
55 {
56 nlohmann::json jsonObj = nlohmann::json::object();
57 if (str.empty()) {
58 return jsonObj;
59 }
60 nlohmann::json jsonTmp = nlohmann::json::parse(str, nullptr, false);
61 if (jsonTmp.is_discarded()) {
62 RESSCHED_LOGE("%{public}s: parse fail, str=%{public}s.", __func__, str.c_str());
63 return jsonObj;
64 }
65 if (!jsonTmp.is_object()) {
66 RESSCHED_LOGD("%{public}s: str=%{public}s is not jsonObj.", __func__, str.c_str());
67 return jsonObj;
68 }
69 return jsonTmp;
70 }
71
ReportData(uint32_t resType,int64_t value,const std::unordered_map<std::string,std::string> & mapPayload)72 void ResSchedClient::ReportData(uint32_t resType, int64_t value,
73 const std::unordered_map<std::string, std::string>& mapPayload)
74 {
75 if (TryConnect() != ERR_OK) {
76 return;
77 }
78 RESSCHED_LOGD("ResSchedClient::ReportData receive resType = %{public}u, value = %{public}lld.",
79 resType, (long long)value);
80 nlohmann::json payload;
81 for (auto it = mapPayload.begin(); it != mapPayload.end(); ++it) {
82 payload[it->first] = it->second;
83 }
84 std::lock_guard<std::mutex> lock(mutex_);
85 if (rss_ == nullptr) {
86 RESSCHED_LOGD("ResSchedClient::ReportData fail to get resource schedule service.");
87 return;
88 }
89 if (!isGetResTypeList_) {
90 rss_->GetResTypeList(resTypeList_);
91 isGetResTypeList_ = true;
92 }
93 if (resTypeList_.find(resType) == resTypeList_.end()) {
94 RESSCHED_LOGD("ResSchedClient::ReportData type not subscribed.");
95 return;
96 }
97 rss_->ReportData(resType, value, payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace));
98 }
99
ReportSyncEvent(const uint32_t resType,const int64_t value,const nlohmann::json & payload,nlohmann::json & reply)100 int32_t ResSchedClient::ReportSyncEvent(const uint32_t resType, const int64_t value, const nlohmann::json& payload,
101 nlohmann::json& reply)
102 {
103 RESSCHED_LOGD("%{public}s: resType=%{public}u, value=%{public}lld.", __func__, resType, (long long)value);
104
105 sptr<IResSchedService> proxy = GetProxy();
106 if (proxy == nullptr) {
107 RESSCHED_LOGD("%{public}s: fail to get rss.", __func__);
108 return RES_SCHED_CONNECT_FAIL;
109 }
110 std::string payloadValue = payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
111 if (resType == ResType::SYNC_RES_TYPE_CHECK_MUTEX_BEFORE_START) {
112 return ReportMutexBeforeStartEvent(resType, value, payload, reply, proxy);
113 } else {
114 int32_t ret;
115 std::string replyValue;
116 proxy->ReportSyncEvent(resType, value, payloadValue, replyValue, ret);
117 reply = StringToJsonObj(replyValue);
118 return ret;
119 }
120 }
121
ReportMutexBeforeStartEvent(const uint32_t resType,const int64_t value,const nlohmann::json & payload,nlohmann::json & reply,sptr<IResSchedService> & proxy)122 int32_t ResSchedClient::ReportMutexBeforeStartEvent(const uint32_t resType, const int64_t value,
123 const nlohmann::json& payload, nlohmann::json& reply, sptr<IResSchedService>& proxy)
124 {
125 auto mtx = std::make_shared<ffrt::mutex>();
126 auto cv = std::make_shared<ffrt::condition_variable>();
127 auto result = std::make_shared<std::pair<int32_t, nlohmann::json>>();
128 auto isSucceed = std::make_shared<std::atomic<bool>>(false);
129 auto payloadValue = std::make_shared<std::string>(
130 payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace));
131 std::unique_lock<ffrt::mutex> lock(*mtx);
132
133 ffrt::submit([resType, value, payload, payloadValue, isSucceed, result, mtx, cv, proxy]() {
134 nlohmann::json ffrtReply;
135 int32_t ret;
136 std::string replyValue;
137 if (proxy == nullptr) {
138 {
139 std::unique_lock<ffrt::mutex> lock(*mtx);
140 result->first = RES_SCHED_CONNECT_FAIL;
141 result->second = ffrtReply;
142 isSucceed->store(false);
143 }
144 cv->notify_all();
145 return;
146 }
147 proxy->ReportSyncEvent(resType, value, *payloadValue, replyValue, ret);
148 ffrtReply = StringToJsonObj(replyValue);
149 {
150 std::unique_lock<ffrt::mutex> lock(*mtx);
151 result->first = ret;
152 result->second = ffrtReply;
153 isSucceed->store(true);
154 }
155 cv->notify_all();
156 }, ffrt::task_attr().timeout(CHECK_MUTEX_TIMEOUT_NS).qos(ffrt::qos_user_interactive));
157 cv->wait_for(lock, std::chrono::milliseconds(CHECK_MUTEX_TIMEOUT));
158 if (!isSucceed->load()) {
159 RESSCHED_LOGW("%{public}s: sync time out", __func__);
160 result->first = RES_SCHED_REQUEST_FAIL;
161 result->second = nlohmann::json{};
162 isSucceed->store(false);
163 }
164 reply = std::move(result->second);
165 return result->first;
166 }
167
ReportSyncEvent(const uint32_t resType,const int64_t value,const std::unordered_map<std::string,std::string> & payload,std::unordered_map<std::string,std::string> & reply)168 int32_t ResSchedClient::ReportSyncEvent(const uint32_t resType, const int64_t value,
169 const std::unordered_map<std::string, std::string>& payload, std::unordered_map<std::string, std::string>& reply)
170 {
171 nlohmann::json tmpPayload;
172 nlohmann::json tmpReply;
173 for (auto it = payload.begin(); it != payload.end(); ++it) {
174 tmpPayload[it->first] = it->second;
175 }
176 auto res = ReportSyncEvent(resType, value, tmpPayload, tmpReply);
177 for (const auto& pair : tmpReply.items()) {
178 reply[pair.key()] = pair.value().dump();
179 }
180 return res;
181 }
182
KillProcess(const std::unordered_map<std::string,std::string> & mapPayload)183 int32_t ResSchedClient::KillProcess(const std::unordered_map<std::string, std::string>& mapPayload)
184 {
185 RESSCHED_LOGD("ResSchedClient::KillProcess receive mission.");
186 nlohmann::json payload;
187 for (auto it = mapPayload.begin(); it != mapPayload.end(); ++it) {
188 payload[it->first] = it->second;
189 }
190 sptr<IResSchedService> proxy = GetProxy();
191 if (proxy == nullptr) {
192 RESSCHED_LOGD("ResSchedClient::KillProcess fail to get resource schedule service.");
193 return RES_SCHED_KILL_PROCESS_FAIL;
194 }
195 int32_t ret;
196 proxy->KillProcess(payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace), ret);
197 return ret;
198 }
199
RegisterSystemloadNotifier(const sptr<ResSchedSystemloadNotifierClient> & callbackObj)200 void ResSchedClient::RegisterSystemloadNotifier(const sptr<ResSchedSystemloadNotifierClient>& callbackObj)
201 {
202 RESSCHED_LOGD("ResSchedClient::RegisterSystemloadNotifier receive mission.");
203 std::lock_guard<std::mutex> lock(mutex_);
204 if (InitSystemloadListenersLocked() != ERR_OK) {
205 RESSCHED_LOGE("ResSchedClient::RegisterSystemloadNotifier init listener failed.");
206 return;
207 }
208 systemloadLevelListener_->RegisterSystemloadLevelCb(callbackObj);
209 if (!systemloadCbRegistered_ && !systemloadLevelListener_->IsSystemloadCbArrayEmpty() && rss_) {
210 rss_->RegisterSystemloadNotifier(systemloadLevelListener_);
211 systemloadCbRegistered_ = true;
212 }
213 AddResSaListenerLocked();
214 }
215
UnRegisterSystemloadNotifier(const sptr<ResSchedSystemloadNotifierClient> & callbackObj)216 void ResSchedClient::UnRegisterSystemloadNotifier(const sptr<ResSchedSystemloadNotifierClient>& callbackObj)
217 {
218 RESSCHED_LOGD("ResSchedClient::UnRegisterSystemloadNotifier receive mission.");
219 std::lock_guard<std::mutex> lock(mutex_);
220 if (systemloadLevelListener_ == nullptr) {
221 RESSCHED_LOGE("ResSchedClient::UnRegisterSystemloadNotifier systemloadLevelListener is null.");
222 return;
223 }
224 systemloadLevelListener_->UnRegisterSystemloadLevelCb(callbackObj);
225 UnRegisterSystemloadListenersLocked();
226 }
227
RegisterEventListener(const sptr<ResSchedEventListener> & eventListener,uint32_t eventType,uint32_t listenerGroup)228 void ResSchedClient::RegisterEventListener(const sptr<ResSchedEventListener>& eventListener,
229 uint32_t eventType, uint32_t listenerGroup)
230 {
231 RESSCHED_LOGD("%{public}s:receive mission.", __func__);
232 std::lock_guard<std::mutex> lock(mutex_);
233 if (InitInnerEventListenerLocked() != ERR_OK) {
234 RESSCHED_LOGE("ResSchedClient::RegisterEventListener init listener failed.");
235 return;
236 }
237 innerEventListener_->RegisterEventListener(eventListener, eventType, listenerGroup);
238 auto item = registeredInnerEvents.find(eventType);
239 if ((item == registeredInnerEvents.end() || item->second.count(listenerGroup) == 0) &&
240 !innerEventListener_->IsInnerEventMapEmpty(eventType, listenerGroup) && rss_) {
241 rss_->RegisterEventListener(innerEventListener_, eventType, listenerGroup);
242 if (item == registeredInnerEvents.end()) {
243 registeredInnerEvents.emplace(eventType, std::unordered_set<uint32_t>());
244 }
245 registeredInnerEvents[eventType].insert(listenerGroup);
246 }
247 AddResSaListenerLocked();
248 }
249
UnRegisterEventListener(const sptr<ResSchedEventListener> & eventListener,uint32_t eventType,uint32_t listenerGroup)250 void ResSchedClient::UnRegisterEventListener(const sptr<ResSchedEventListener>& eventListener,
251 uint32_t eventType, uint32_t listenerGroup)
252 {
253 RESSCHED_LOGD("%{public}s:receive mission.", __func__);
254 std::lock_guard<std::mutex> lock(mutex_);
255 if (innerEventListener_ == nullptr) {
256 RESSCHED_LOGE("%{public}s: innerEventListener_ is null.", __func__);
257 return;
258 }
259 innerEventListener_->UnRegisterEventListener(eventListener, eventType, listenerGroup);
260 UnRegisterEventListenerLocked(eventType, listenerGroup);
261 }
262
GetSystemloadLevel()263 int32_t ResSchedClient::GetSystemloadLevel()
264 {
265 if (TryConnect() != ERR_OK) {
266 return RES_SCHED_CONNECT_FAIL;
267 }
268 RESSCHED_LOGD("ResSchedClient::GetSystemloadLevel receive mission.");
269
270 std::lock_guard<std::mutex> lock(mutex_);
271 if (rss_ == nullptr) {
272 RESSCHED_LOGE("ResSchedClient::GetSystemloadLevel fail to get resource schedule service.");
273 return RES_SCHED_CONNECT_FAIL;
274 }
275 int32_t ret;
276 rss_->GetSystemloadLevel(ret);
277 return ret;
278 }
279
IsAllowedAppPreload(const std::string & bundleName,int32_t preloadMode)280 bool ResSchedClient::IsAllowedAppPreload(const std::string& bundleName, int32_t preloadMode)
281 {
282 if (TryConnect() != ERR_OK) {
283 return false;
284 }
285
286 std::lock_guard<std::mutex> lock(mutex_);
287 if (rss_ == nullptr) {
288 RESSCHED_LOGE("ResSchedClient::IsAllowedAppPreload fail to get resource schedule service.");
289 return false;
290 }
291
292 RESSCHED_LOGD("App preload bundleName %{public}s, preloadMode %{public}d", bundleName.c_str(), preloadMode);
293 bool ret;
294 rss_->IsAllowedAppPreload(bundleName, preloadMode, ret);
295 return ret;
296 }
297
IsAllowedLinkJump(bool & isAllowedLinkJump)298 int32_t ResSchedClient::IsAllowedLinkJump(bool& isAllowedLinkJump)
299 {
300 RESSCHED_LOGD("enter IsAllowedLinkJump");
301 if (TryConnect() != ERR_OK) {
302 return RES_SCHED_CONNECT_FAIL;
303 }
304
305 std::lock_guard<std::mutex> lock(mutex_);
306 if (rss_ == nullptr) {
307 RESSCHED_LOGE("ResSchedClient::IsAllowedLinkJump fail to get resource schedule service.");
308 return RES_SCHED_CONNECT_FAIL;
309 }
310 int32_t ret;
311 rss_->IsAllowedLinkJump(isAllowedLinkJump, ret);
312 return ret;
313 }
314
GetProxy()315 sptr<IResSchedService> ResSchedClient::GetProxy()
316 {
317 if (TryConnect() == ERR_OK) {
318 std::lock_guard<std::mutex> lock(mutex_);
319 return rss_;
320 }
321 return nullptr;
322 }
323
TryConnect()324 ErrCode ResSchedClient::TryConnect()
325 {
326 std::lock_guard<std::mutex> lock(mutex_);
327 if (g_isDestroyed) {
328 return GET_RES_SCHED_SERVICE_FAILED;
329 }
330 if (rss_) {
331 return ERR_OK;
332 }
333
334 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
335 if (!systemManager) {
336 RESSCHED_LOGE("ResSchedClient::Fail to get registry.");
337 return GET_RES_SCHED_SERVICE_FAILED;
338 }
339
340 remoteObject_ = systemManager->CheckSystemAbility(RES_SCHED_SYS_ABILITY_ID);
341 if (!remoteObject_) {
342 RESSCHED_LOGE("ResSchedClient::Fail to connect resource schedule service.");
343 return GET_RES_SCHED_SERVICE_FAILED;
344 }
345
346 rss_ = iface_cast<IResSchedService>(remoteObject_);
347 if (!rss_) {
348 return GET_RES_SCHED_SERVICE_FAILED;
349 }
350 recipient_ = new (std::nothrow) ResSchedDeathRecipient(*this);
351 if (!recipient_) {
352 RESSCHED_LOGE("ResSchedClient::New ResSchedDeathRecipient failed.");
353 return GET_RES_SCHED_SERVICE_FAILED;
354 }
355 rss_->AsObject()->AddDeathRecipient(recipient_);
356 AddResSaListenerLocked();
357 RESSCHED_LOGD("ResSchedClient::Connect resource schedule service success.");
358 return ERR_OK;
359 }
360
StopRemoteObject()361 void ResSchedClient::StopRemoteObject()
362 {
363 std::lock_guard<std::mutex> lock(mutex_);
364 if (rss_ && rss_->AsObject()) {
365 rss_->AsObject()->RemoveDeathRecipient(recipient_);
366 }
367 rss_ = nullptr;
368 systemloadCbRegistered_ = false;
369 registeredInnerEvents.clear();
370 }
371
AddResSaListenerLocked()372 void ResSchedClient::AddResSaListenerLocked()
373 {
374 if (resSchedSvcStatusListener_ != nullptr) {
375 return;
376 }
377 sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
378 if (!systemManager) {
379 RESSCHED_LOGE("ResSchedClient::Fail to get sa mgr client.");
380 return;
381 }
382 resSchedSvcStatusListener_ = new (std::nothrow) ResSchedSvcStatusChange;
383 if (resSchedSvcStatusListener_ == nullptr) {
384 RESSCHED_LOGE("ResSchedClient::Fail to new res svc listener.");
385 return;
386 }
387 int32_t ret = systemManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, resSchedSvcStatusListener_);
388 if (ret != ERR_OK) {
389 RESSCHED_LOGE("ResSchedClient::Register sa status change failed.");
390 resSchedSvcStatusListener_ = nullptr;
391 }
392 }
393
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)394 void ResSchedClient::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
395 {
396 if (systemAbilityId != RES_SCHED_SYS_ABILITY_ID) {
397 RESSCHED_LOGE("ResSchedClient::OnAddSystemAbility is not res sa id.");
398 return;
399 }
400 if (TryConnect() != ERR_OK) {
401 return;
402 }
403 std::lock_guard<std::mutex> lock(mutex_);
404 if (InitInnerEventListenerLocked() != ERR_OK) {
405 RESSCHED_LOGE("ResSchedClient::OnAddSystemAbility init event listener failed.");
406 } else if (innerEventListener_ && rss_) {
407 RecoverEventListener();
408 }
409 if (InitSystemloadListenersLocked() != ERR_OK) {
410 RESSCHED_LOGE("ResSchedClient::OnAddSystemAbility init listener failed.");
411 return;
412 }
413 if (!systemloadCbRegistered_ && !systemloadLevelListener_->IsSystemloadCbArrayEmpty() && rss_) {
414 rss_->RegisterSystemloadNotifier(systemloadLevelListener_);
415 systemloadCbRegistered_ = true;
416 }
417 }
418
RecoverEventListener()419 void ResSchedClient::RecoverEventListener()
420 {
421 for (auto typeAndGroup : innerEventListener_->GetRegisteredTypesAndGroup()) {
422 auto type = typeAndGroup.first;
423 for (auto group : typeAndGroup.second) {
424 if (!rss_) {
425 return;
426 }
427 rss_->RegisterEventListener(innerEventListener_, type, group);
428 if (registeredInnerEvents.find(type) == registeredInnerEvents.end()) {
429 registeredInnerEvents.emplace(type, std::unordered_set<uint32_t>());
430 }
431 registeredInnerEvents[type].insert(group);
432
433 }
434 }
435 }
436
InitSystemloadListenersLocked()437 int32_t ResSchedClient::InitSystemloadListenersLocked()
438 {
439 if (systemloadLevelListener_ != nullptr) {
440 return ERR_OK;
441 }
442 systemloadLevelListener_ = new (std::nothrow) SystemloadLevelListener;
443 if (systemloadLevelListener_ == nullptr) {
444 RESSCHED_LOGW("ResSchedClient::InitSystemloadListenersLocked new listener error.");
445 return RES_SCHED_DATA_ERROR;
446 }
447 return ERR_OK;
448 }
449
InitInnerEventListenerLocked()450 int32_t ResSchedClient::InitInnerEventListenerLocked()
451 {
452 if (innerEventListener_ != nullptr) {
453 return ERR_OK;
454 }
455 innerEventListener_ = new (std::nothrow) InnerEventListener;
456 if (innerEventListener_ == nullptr) {
457 RESSCHED_LOGW("ResSchedClient::InitInnerEventListenerLocked new listener error.");
458 return RES_SCHED_DATA_ERROR;
459 }
460 return ERR_OK;
461 }
462
UnRegisterEventListenerLocked(uint32_t eventType,uint32_t listenerGroup)463 void ResSchedClient::UnRegisterEventListenerLocked(uint32_t eventType, uint32_t listenerGroup)
464 {
465 if (innerEventListener_->IsInnerEventMapEmpty(eventType, listenerGroup) && rss_) {
466 rss_->UnRegisterEventListener(eventType, listenerGroup);
467 auto item = registeredInnerEvents.find(eventType);
468 if (item != registeredInnerEvents.end()) {
469 item->second.erase(listenerGroup);
470 }
471 }
472 }
473
474
UnRegisterSystemloadListenersLocked()475 void ResSchedClient::UnRegisterSystemloadListenersLocked()
476 {
477 if (systemloadLevelListener_->IsSystemloadCbArrayEmpty() && rss_) {
478 rss_->UnRegisterSystemloadNotifier();
479 systemloadCbRegistered_ = false;
480 }
481 }
482
ResSchedDeathRecipient(ResSchedClient & resSchedClient)483 ResSchedClient::ResSchedDeathRecipient::ResSchedDeathRecipient(ResSchedClient &resSchedClient)
484 : resSchedClient_(resSchedClient) {}
485
~ResSchedDeathRecipient()486 ResSchedClient::ResSchedDeathRecipient::~ResSchedDeathRecipient() {}
487
OnRemoteDied(const wptr<IRemoteObject> & remote)488 void ResSchedClient::ResSchedDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
489 {
490 resSchedClient_.StopRemoteObject();
491 }
492
~SystemloadLevelListener()493 ResSchedClient::SystemloadLevelListener::~SystemloadLevelListener()
494 {
495 std::lock_guard<std::mutex> lock(listMutex_);
496 systemloadLevelCbs_.clear();
497 }
498
RegisterSystemloadLevelCb(const sptr<ResSchedSystemloadNotifierClient> & callbackObj)499 void ResSchedClient::SystemloadLevelListener::RegisterSystemloadLevelCb(
500 const sptr<ResSchedSystemloadNotifierClient>& callbackObj)
501 {
502 std::lock_guard<std::mutex> lock(listMutex_);
503 if (callbackObj != nullptr) {
504 for (auto& iter : systemloadLevelCbs_) {
505 if (iter == callbackObj) {
506 RESSCHED_LOGE("ResSchedClient register an exist callback object.");
507 return;
508 }
509 }
510 systemloadLevelCbs_.emplace_back(callbackObj);
511 }
512 RESSCHED_LOGD("Client has registered %{public}d listeners.", static_cast<int32_t>(systemloadLevelCbs_.size()));
513 }
514
UnRegisterSystemloadLevelCb(const sptr<ResSchedSystemloadNotifierClient> & callbackObj)515 void ResSchedClient::SystemloadLevelListener::UnRegisterSystemloadLevelCb(
516 const sptr<ResSchedSystemloadNotifierClient>& callbackObj)
517 {
518 std::lock_guard<std::mutex> lock(listMutex_);
519 systemloadLevelCbs_.remove(callbackObj);
520 RESSCHED_LOGD(
521 "Client left %{public}d systemload level listeners.", static_cast<int32_t>(systemloadLevelCbs_.size()));
522 }
523
IsSystemloadCbArrayEmpty()524 bool ResSchedClient::SystemloadLevelListener::IsSystemloadCbArrayEmpty()
525 {
526 std::lock_guard<std::mutex> lock(listMutex_);
527 return systemloadLevelCbs_.empty();
528 }
529
OnSystemloadLevel(int32_t level)530 ErrCode ResSchedClient::SystemloadLevelListener::OnSystemloadLevel(int32_t level)
531 {
532 std::list<sptr<ResSchedSystemloadNotifierClient>> notifyList;
533 {
534 std::lock_guard<std::mutex> lock(listMutex_);
535 for (auto& iter : systemloadLevelCbs_) {
536 notifyList.push_back(iter);
537 }
538 }
539 // copy notifiers from systemloadLevelCbs_ to revent dead lock
540 for (auto& notifier : notifyList) {
541 if (notifier != nullptr) {
542 notifier->OnSystemloadLevel(level);
543 }
544 }
545 return ERR_OK;
546 }
547
~InnerEventListener()548 ResSchedClient::InnerEventListener::~InnerEventListener()
549 {
550 std::lock_guard<std::mutex> lock(eventMutex_);
551 eventListeners_.clear();
552 }
553
RegisterEventListener(const sptr<ResSchedEventListener> & eventListener,uint32_t eventType,uint32_t listenerGroup)554 void ResSchedClient::InnerEventListener::RegisterEventListener(const sptr<ResSchedEventListener>& eventListener,
555 uint32_t eventType, uint32_t listenerGroup)
556 {
557 std::lock_guard<std::mutex> lock(eventMutex_);
558 if (eventListener == nullptr) {
559 RESSCHED_LOGE("ResSchedClient register an null eventListener object.");
560 return;
561 }
562 auto item = eventListeners_.find(eventType);
563 if (item == eventListeners_.end()) {
564 eventListeners_.emplace(eventType, std::unordered_map<uint32_t, std::list<sptr<ResSchedEventListener>>>());
565 eventListeners_[eventType].emplace(listenerGroup, std::list<sptr<ResSchedEventListener>>());
566 eventListeners_[eventType][listenerGroup].emplace_back(eventListener);
567 } else {
568 auto listenerItem = item->second.find(listenerGroup);
569 if (listenerItem == item->second.end()) {
570 item->second.emplace(listenerGroup, std::list<sptr<ResSchedEventListener>>());
571 }
572 for (auto& iter : listenerItem->second) {
573 if (iter == eventListener) {
574 RESSCHED_LOGE("ResSchedClient register an exist eventListener object.");
575 return;
576 }
577 }
578 item->second[listenerGroup].emplace_back(eventListener);
579 }
580 RESSCHED_LOGD("Client has registered %{public}d eventListener with type:%{public}d.",
581 static_cast<int32_t>(eventListeners_[eventType].size()), eventType);
582 }
583
UnRegisterEventListener(const sptr<ResSchedEventListener> & eventListener,uint32_t eventType,uint32_t listenerGroup)584 void ResSchedClient::InnerEventListener::UnRegisterEventListener(const sptr<ResSchedEventListener>& eventListener,
585 uint32_t eventType, uint32_t listenerGroup)
586 {
587 std::lock_guard<std::mutex> lock(eventMutex_);
588 auto item = eventListeners_.find(eventType);
589 if (item == eventListeners_.end()) {
590 RESSCHED_LOGE("eventListener not registered");
591 return;
592 }
593 auto listenerItem = item->second.find(listenerGroup);
594 if (listenerItem == item->second.end()) {
595 return;
596 }
597 listenerItem->second.remove(eventListener);
598 if (listenerItem->second.size() == 0) {
599 item->second.erase(listenerGroup);
600 RESSCHED_LOGD("Client left 0 listeners with type %{public}d group %{public}d", eventType, listenerGroup);
601 }
602 if (item->second.size() == 0) {
603 eventListeners_.erase(eventType);
604 RESSCHED_LOGD("Client left 0 listeners with type %{public}d.", eventType);
605 return;
606 }
607 RESSCHED_LOGD("Client left %{public}d listeners with type %{public}d.",
608 static_cast<int32_t>(item->second.size()), eventType);
609 }
610
OnReceiveEvent(uint32_t eventType,uint32_t eventValue,uint32_t listenerGroup,const std::string & extInfo)611 ErrCode ResSchedClient::InnerEventListener::OnReceiveEvent(uint32_t eventType, uint32_t eventValue,
612 uint32_t listenerGroup, const std::string& extInfo)
613 {
614 nlohmann::json extInfoJson = StringToJsonObj(extInfo);
615 std::unordered_map<std::string, std::string> extInfoMap;
616 for (auto it = extInfoJson.begin(); it != extInfoJson.end(); ++it) {
617 extInfoMap[it.key()] = it.value().get<std::string>();
618 }
619 std::list<sptr<ResSchedEventListener>> listenerList;
620 {
621 std::lock_guard<std::mutex> lock(eventMutex_);
622 auto item = eventListeners_.find(eventType);
623 if (item == eventListeners_.end()) {
624 return RES_SCHED_DATA_ERROR;
625 }
626 auto listenerItem = item->second.find(listenerGroup);
627 for (auto& iter : listenerItem->second) {
628 listenerList.push_back(iter);
629 }
630 }
631 // copy notifiers from systemloadLevelCbs_ to revent dead lock
632 for (auto& listener : listenerList) {
633 if (listener != nullptr) {
634 listener->OnReceiveEvent(eventType, eventValue, extInfoMap);
635 }
636 }
637 return ERR_OK;
638 }
639
IsInnerEventMapEmpty(uint32_t eventType,uint32_t listenerGroup)640 bool ResSchedClient::InnerEventListener::IsInnerEventMapEmpty(uint32_t eventType, uint32_t listenerGroup)
641 {
642 std::lock_guard<std::mutex> lock(eventMutex_);
643 auto item = eventListeners_.find(eventType);
644 if (item == eventListeners_.end()) {
645 return true;
646 }
647 auto listenerItem = item->second.find(listenerGroup);
648 return listenerItem == item->second.end() || listenerItem->second.empty();
649 }
650
GetRegisteredTypesAndGroup()651 std::unordered_map<uint32_t, std::list<uint32_t>> ResSchedClient::InnerEventListener::GetRegisteredTypesAndGroup()
652 {
653 std::unordered_map<uint32_t, std::list<uint32_t>> ret;
654 std::lock_guard<std::mutex> lock(eventMutex_);
655 for (auto item : eventListeners_) {
656 ret.emplace(item.first, std::list<uint32_t>());
657 for (auto listenerItem : item.second) {
658 ret[item.first].emplace_back(listenerItem.first);
659 }
660 }
661 return ret;
662 }
663
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)664 void ResSchedSvcStatusChange::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
665 {
666 RESSCHED_LOGD("ResSchedSvcStatusChange::OnAddSystemAbility called, said : %{public}d.", systemAbilityId);
667 ResSchedClient::GetInstance().OnAddSystemAbility(systemAbilityId, deviceId);
668 }
669
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)670 void ResSchedSvcStatusChange::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
671 {
672 RESSCHED_LOGD("ResSchedSvcStatusChange::OnRemoveSystemAbility called.");
673 }
674
ReportData(uint32_t resType,int64_t value,const std::unordered_map<std::string,std::string> & mapPayload)675 extern "C" void ReportData(uint32_t resType, int64_t value,
676 const std::unordered_map<std::string, std::string>& mapPayload)
677 {
678 ResSchedClient::GetInstance().ReportData(resType, value, mapPayload);
679 }
680
KillProcess(const std::unordered_map<std::string,std::string> & mapPayload)681 extern "C" void KillProcess(const std::unordered_map<std::string, std::string>& mapPayload)
682 {
683 ResSchedClient::GetInstance().KillProcess(mapPayload);
684 }
685
ReportSyncEvent(const uint32_t resType,const int64_t value,const std::unordered_map<std::string,std::string> & payload,std::unordered_map<std::string,std::string> & reply)686 extern "C" void ReportSyncEvent(const uint32_t resType, const int64_t value,
687 const std::unordered_map<std::string, std::string>& payload, std::unordered_map<std::string, std::string>& reply)
688 {
689 ResSchedClient::GetInstance().ReportSyncEvent(resType, value, payload, reply);
690 }
691 } // namespace ResourceSchedule
692 } // namespace OHOS
693