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