1 /*
2 * Copyright (c) 2024-2025 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 "file_ex.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 char* 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 char* SYSTEMLOAD_FILE = "/data/service/el1/public/ressched/systemload";
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 systemload;
75 if (LoadStringFromFile(SYSTEMLOAD_FILE, systemload)) {
76 for (auto& vec : g_systemloadPair) {
77 if (vec.first == systemload) {
78 systemloadLevel_ = vec.second;
79 RESSCHED_LOGI("load systemload from file, value:%{public}d", (int)systemloadLevel_);
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 if (SaveStringToFile(SYSTEMLOAD_FILE, vec.first)) {
147 RESSCHED_LOGI("save systemload succeed,systemload is %{public}d", (int)vec.second);
148 } else {
149 RESSCHED_LOGW("save systemload failed,systemload is %{public}d", (int)vec.second);
150 }
151 }
152 }
153
154 if (notifierHandler_ == nullptr) {
155 RESSCHED_LOGE("OnDeviceLevelChanged error due to notifierHandler null.");
156 return;
157 }
158
159 OnDeviceLevelChangedLock(level);
160 }
161
OnApplicationStateChange(int32_t state,int32_t pid)162 void NotifierMgr::OnApplicationStateChange(int32_t state, int32_t pid)
163 {
164 RESSCHED_LOGD("OnApplicationStateChange called, state: %{public}d, pid : %{public}d .", state, pid);
165 std::lock_guard<std::mutex> autoLock(notifierMutex_);
166 auto iter = notifierMap_.find(pid);
167 if (iter == notifierMap_.end()) {
168 return;
169 }
170 auto& info = iter->second;
171 if (!info.hapApp) {
172 RESSCHED_LOGW("OnApplicationStateChange called, not app.");
173 return;
174 }
175 if (state == static_cast<int32_t>(ApplicationState::APP_STATE_FOREGROUND)) {
176 info.foreground = true;
177 if (systemloadLevel_ != info.level) {
178 info.level = systemloadLevel_;
179 std::vector<sptr<IRemoteObject>> vec{ info.notifier };
180 HandleDeviceLevelChange(vec, systemloadLevel_);
181 }
182 }
183 if (state == static_cast<int32_t>(ApplicationState::APP_STATE_BACKGROUND)
184 || state == static_cast<int32_t>(ApplicationState::APP_STATE_TERMINATED)
185 || state == static_cast<int32_t>(ApplicationState::APP_STATE_END)) {
186 info.foreground = false;
187 }
188 }
189
GetSystemloadLevel()190 int32_t NotifierMgr::GetSystemloadLevel()
191 {
192 RESSCHED_LOGD("GetSystemloadLevel called");
193 return static_cast<int32_t>(systemloadLevel_);
194 }
195
RemoveNotifierLock(const sptr<IRemoteObject> & notifier)196 void NotifierMgr::RemoveNotifierLock(const sptr<IRemoteObject>& notifier)
197 {
198 RESSCHED_LOGD("RemoveNotifierLock called");
199 std::lock_guard<std::mutex> autoLock(notifierMutex_);
200 for (auto& notifiers : notifierMap_) {
201 if (notifiers.second.notifier != notifier) {
202 continue;
203 }
204 notifiers.second.notifier->RemoveDeathRecipient(notifierDeathRecipient_);
205 notifierMap_.erase(notifiers.first);
206 return;
207 }
208 }
209
OnDeviceLevelChangedLock(int32_t level)210 void NotifierMgr::OnDeviceLevelChangedLock(int32_t level)
211 {
212 std::vector<sptr<IRemoteObject>> notifierArray;
213 {
214 std::lock_guard<std::mutex> autoLock(notifierMutex_);
215 for (auto& notifiers : notifierMap_) {
216 auto pid = notifiers.first;
217 auto& info = notifiers.second;
218 if (info.hapApp && !info.foreground) {
219 RESSCHED_LOGD("app on background, pid = %{public}d .", pid);
220 continue;
221 }
222 info.level = level;
223 notifierArray.push_back(info.notifier);
224 }
225 }
226 HandleDeviceLevelChange(notifierArray, level);
227 }
228
IsHapApp()229 bool NotifierMgr::IsHapApp()
230 {
231 Security::AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
232 auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
233 if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
234 RESSCHED_LOGE("not hap app");
235 return false;
236 }
237 return true;
238 }
239
DumpRegisterInfo()240 std::vector<std::pair<int32_t, bool>> NotifierMgr::DumpRegisterInfo()
241 {
242 std::vector<std::pair<int32_t, bool>> vec;
243 {
244 std::lock_guard<std::mutex> autoLock(notifierMutex_);
245 for (auto& notifiers : notifierMap_) {
246 vec.push_back({ notifiers.first, notifiers.second.hapApp });
247 }
248 }
249 return vec;
250 }
251
HandleDeviceLevelChange(std::vector<sptr<IRemoteObject>> & notifierVec,int32_t level)252 void NotifierMgr::HandleDeviceLevelChange(std::vector<sptr<IRemoteObject>>& notifierVec, int32_t level)
253 {
254 auto func = [notifierVec, level] () {
255 for (auto& notifier : notifierVec) {
256 if (notifier == nullptr) {
257 continue;
258 }
259 auto proxy = std::make_unique<ResSchedSystemloadNotifierProxy>(notifier);
260 proxy->OnSystemloadLevel(level);
261 }
262 };
263 notifierHandler_->submit(func);
264 }
265 } // ResourceSchedule
266 } // OHOS