1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "notifier_mgr.h"
17 
18 #include <vector>
19 
20 #include "accesstoken_kit.h"
21 #include "ipc_skeleton.h"
22 #include "app_mgr_constants.h"
23 #include "parameters.h"
24 #include "res_sched_log.h"
25 #include "res_sched_common_death_recipient.h"
26 #include "res_sched_systemload_notifier_proxy.h"
27 
28 namespace OHOS {
29 namespace ResourceSchedule {
30 using OHOS::AppExecFwk::ApplicationState;
31 
32 static const std::string SYSTEMLOAD_CHANGE = "systemLoadChange";
33 
34 static std::map<ResType::DeviceStatus, std::string> g_DeviceStatusType = {
35     { ResType::DeviceStatus::SYSTEMLOAD_LEVEL, SYSTEMLOAD_CHANGE }
36 };
37 
38 static std::vector<std::pair<std::string, ResType::SystemloadLevel>> g_systemloadPair = {
39     { "LOW", ResType::SystemloadLevel::LOW },
40     { "NORMAL", ResType::SystemloadLevel::NORMAL },
41     { "MEDIUM", ResType::SystemloadLevel::MEDIUM },
42     { "HIGH", ResType::SystemloadLevel::HIGH },
43     { "OVERHEATED", ResType::SystemloadLevel::OVERHEATED },
44     { "WARNING", ResType::SystemloadLevel::WARNING },
45     { "EMERGENCY", ResType::SystemloadLevel::EMERGENCY },
46     { "ESCAPE", ResType::SystemloadLevel::ESCAPE }
47 };
48 
49 static const std::string SYSTEMLOAD_PARAMETER = "resourceschedule.systemload.level";
50 
GetInstance()51 NotifierMgr& NotifierMgr::GetInstance()
52 {
53     static NotifierMgr notifierMgr;
54     return notifierMgr;
55 }
56 
~NotifierMgr()57 NotifierMgr::~NotifierMgr()
58 {
59     std::lock_guard<std::mutex> autoLock(notifierMutex_);
60     notifierMap_.clear();
61 }
62 
Init()63 void NotifierMgr::Init()
64 {
65     if (initialized_) {
66         RESSCHED_LOGE("NotifierMgr has initialized");
67         return;
68     }
69     notifierDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(
70         new (std::nothrow) ResSchedCommonDeathRecipient([](const sptr<IRemoteObject>& notifier) {
71             NotifierMgr::GetInstance().OnRemoteNotifierDied(notifier);
72         }));
73     notifierHandler_ = std::make_shared<ffrt::queue>("DeviceNotifyQueue");
74     std::string systemloadParamDef;
75     std::string systemloadParam = OHOS::system::GetParameter(SYSTEMLOAD_PARAMETER, systemloadParamDef);
76     if (!systemloadParam.empty()) {
77         for (auto& vec : g_systemloadPair) {
78             if (vec.first == systemloadParam) {
79                 systemloadLevel_ = vec.second;
80             }
81         }
82     }
83     initialized_ = true;
84 }
85 
Deinit()86 void NotifierMgr::Deinit()
87 {
88     notifierHandler_.reset();
89 }
90 
RegisterNotifier(int32_t pid,const sptr<IRemoteObject> & notifier)91 void NotifierMgr::RegisterNotifier(int32_t pid, const sptr<IRemoteObject>& notifier)
92 {
93     RESSCHED_LOGD("RegisterNotifier called, pid = %{public}d.", pid);
94     if (notifier == nullptr) {
95         RESSCHED_LOGE("RegisterNotifier notifier is null");
96         return;
97     }
98     if (notifierDeathRecipient_ == nullptr) {
99         RESSCHED_LOGE("RegisterNotifier error due to notifierDeathRecipient null");
100         return;
101     }
102     std::lock_guard<std::mutex> autoLock(notifierMutex_);
103     auto iter = notifierMap_.find(pid);
104     if (iter == notifierMap_.end()) {
105         NotifierInfo info;
106         info.notifier = notifier;
107         info.hapApp = IsHapApp();
108         notifierMap_[pid] = info;
109         notifier->AddDeathRecipient(notifierDeathRecipient_);
110     }
111 }
112 
UnRegisterNotifier(int32_t pid)113 void NotifierMgr::UnRegisterNotifier(int32_t pid)
114 {
115     RESSCHED_LOGD("UnRegisterNotifier called");
116     std::lock_guard<std::mutex> autoLock(notifierMutex_);
117     auto iter = notifierMap_.find(pid);
118     if (iter != notifierMap_.end()) {
119         iter->second.notifier->RemoveDeathRecipient(notifierDeathRecipient_);
120         notifierMap_.erase(pid);
121     }
122 }
123 
OnRemoteNotifierDied(const sptr<IRemoteObject> & notifier)124 void NotifierMgr::OnRemoteNotifierDied(const sptr<IRemoteObject>& notifier)
125 {
126     RESSCHED_LOGD("OnRemoteNotifierDied called");
127     if (notifier == nullptr) {
128         RESSCHED_LOGW("remote notifier null");
129         return;
130     }
131     RemoveNotifierLock(notifier);
132 }
133 
OnDeviceLevelChanged(int32_t type,int32_t level)134 void NotifierMgr::OnDeviceLevelChanged(int32_t type, int32_t level)
135 {
136     RESSCHED_LOGD("OnDeviceLevelChanged called");
137     auto cbType = static_cast<ResType::DeviceStatus>(type);
138     if (g_DeviceStatusType.count(cbType) == 0) {
139         RESSCHED_LOGW("OnDeviceLevelChanged, no type matched");
140         return;
141     }
142 
143     systemloadLevel_ = static_cast<ResType::SystemloadLevel>(level);
144     for (auto& vec : g_systemloadPair) {
145         if (systemloadLevel_ == vec.second) {
146             OHOS::system::SetParameter(SYSTEMLOAD_PARAMETER, vec.first);
147         }
148     }
149 
150     if (notifierHandler_ == nullptr) {
151         RESSCHED_LOGE("OnDeviceLevelChanged error due to notifierHandler null.");
152         return;
153     }
154 
155     OnDeviceLevelChangedLock(level);
156 }
157 
OnApplicationStateChange(int32_t state,int32_t pid)158 void NotifierMgr::OnApplicationStateChange(int32_t state, int32_t pid)
159 {
160     RESSCHED_LOGD("OnApplicationStateChange called, state: %{public}d, pid : %{public}d .", state, pid);
161     std::lock_guard<std::mutex> autoLock(notifierMutex_);
162     auto iter = notifierMap_.find(pid);
163     if (iter == notifierMap_.end()) {
164         return;
165     }
166     auto& info = iter->second;
167     if (!info.hapApp) {
168         RESSCHED_LOGW("OnApplicationStateChange called, not app.");
169         return;
170     }
171     if (state == static_cast<int32_t>(ApplicationState::APP_STATE_FOREGROUND)) {
172         info.foreground = true;
173         if (systemloadLevel_ != info.level) {
174             info.level = systemloadLevel_;
175             std::vector<sptr<IRemoteObject>> vec{ info.notifier };
176             HandleDeviceLevelChange(vec, systemloadLevel_);
177         }
178     }
179     if (state == static_cast<int32_t>(ApplicationState::APP_STATE_BACKGROUND)
180         || state == static_cast<int32_t>(ApplicationState::APP_STATE_TERMINATED)
181         || state == static_cast<int32_t>(ApplicationState::APP_STATE_END)) {
182         info.foreground = false;
183     }
184 }
185 
GetSystemloadLevel()186 int32_t NotifierMgr::GetSystemloadLevel()
187 {
188     RESSCHED_LOGD("GetSystemloadLevel called");
189     return static_cast<int32_t>(systemloadLevel_);
190 }
191 
RemoveNotifierLock(const sptr<IRemoteObject> & notifier)192 void NotifierMgr::RemoveNotifierLock(const sptr<IRemoteObject>& notifier)
193 {
194     RESSCHED_LOGD("RemoveNotifierLock called");
195     std::lock_guard<std::mutex> autoLock(notifierMutex_);
196     for (auto& notifiers : notifierMap_) {
197         if (notifiers.second.notifier != notifier) {
198             continue;
199         }
200         notifiers.second.notifier->RemoveDeathRecipient(notifierDeathRecipient_);
201         notifierMap_.erase(notifiers.first);
202         return;
203     }
204 }
205 
OnDeviceLevelChangedLock(int32_t level)206 void NotifierMgr::OnDeviceLevelChangedLock(int32_t level)
207 {
208     std::vector<sptr<IRemoteObject>> notifierArray;
209     {
210         std::lock_guard<std::mutex> autoLock(notifierMutex_);
211         for (auto& notifiers : notifierMap_) {
212             auto pid = notifiers.first;
213             auto& info = notifiers.second;
214             if (info.hapApp && !info.foreground) {
215                 RESSCHED_LOGD("app on background, pid = %{public}d .", pid);
216                 continue;
217             }
218             info.level = level;
219             notifierArray.push_back(info.notifier);
220         }
221     }
222     HandleDeviceLevelChange(notifierArray, level);
223 }
224 
IsHapApp()225 bool NotifierMgr::IsHapApp()
226 {
227     Security::AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
228     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
229     if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
230         RESSCHED_LOGE("not hap app");
231         return false;
232     }
233     return true;
234 }
235 
DumpRegisterInfo()236 std::vector<std::pair<int32_t, bool>> NotifierMgr::DumpRegisterInfo()
237 {
238     std::vector<std::pair<int32_t, bool>> vec;
239     {
240         std::lock_guard<std::mutex> autoLock(notifierMutex_);
241         for (auto& notifiers : notifierMap_) {
242             vec.push_back({ notifiers.first, notifiers.second.hapApp });
243         }
244     }
245     return vec;
246 }
247 
HandleDeviceLevelChange(std::vector<sptr<IRemoteObject>> & notifierVec,int32_t level)248 void NotifierMgr::HandleDeviceLevelChange(std::vector<sptr<IRemoteObject>>& notifierVec, int32_t level)
249 {
250     auto func = [notifierVec, level] () {
251         for (auto& notifier : notifierVec) {
252             if (notifier == nullptr) {
253                 continue;
254             }
255             auto proxy = std::make_unique<ResSchedSystemloadNotifierProxy>(notifier);
256             proxy->OnSystemloadLevel(level);
257         }
258     };
259     notifierHandler_->submit(func);
260 }
261 } // ResourceSchedule
262 } // OHOS