• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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