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