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