• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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