• 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 #include "res_sched_event_reporter.h"
28 #include "hisysevent.h"
29 
30 namespace OHOS {
31 namespace ResourceSchedule {
32 using OHOS::AppExecFwk::ApplicationState;
33 
34 static constexpr size_t MAX_REPORT_SIZE = 100;
35 static constexpr int64_t REPORT_INTERVAL_MS = static_cast<int64_t>(2) * 60 * 60 * 1000 * 1000;
36 static constexpr int64_t FIRST_REPORT_DELAY_MS = 10 * 1000 * 1000;
37 static const char* SYSTEMLOAD_CHANGE = "systemLoadChange";
38 
39 static std::map<ResType::DeviceStatus, std::string> g_DeviceStatusType = {
40     { ResType::DeviceStatus::SYSTEMLOAD_LEVEL, SYSTEMLOAD_CHANGE }
41 };
42 
43 static std::vector<std::pair<std::string, ResType::SystemloadLevel>> g_systemloadPair = {
44     { "LOW", ResType::SystemloadLevel::LOW },
45     { "NORMAL", ResType::SystemloadLevel::NORMAL },
46     { "MEDIUM", ResType::SystemloadLevel::MEDIUM },
47     { "HIGH", ResType::SystemloadLevel::HIGH },
48     { "OVERHEATED", ResType::SystemloadLevel::OVERHEATED },
49     { "WARNING", ResType::SystemloadLevel::WARNING },
50     { "EMERGENCY", ResType::SystemloadLevel::EMERGENCY },
51     { "ESCAPE", ResType::SystemloadLevel::ESCAPE }
52 };
53 
54 static const char* SYSTEMLOAD_FILE = "/data/service/el1/public/ressched/systemload";
55 
GetInstance()56 NotifierMgr& NotifierMgr::GetInstance()
57 {
58     static NotifierMgr notifierMgr;
59     return notifierMgr;
60 }
61 
~NotifierMgr()62 NotifierMgr::~NotifierMgr()
63 {
64     // 先锁notifierMutex_后锁hisyseventMutex_,防止与RegisterNotifier死锁
65     std::lock_guard<std::mutex> autoLock(notifierMutex_);
66     notifierMap_.clear();
67     std::lock_guard<ffrt::mutex> hisyseventLock(hisyseventMutex_);
68     hisyseventBundleNames_.clear();
69 }
70 
Init()71 void NotifierMgr::Init()
72 {
73     if (initialized_) {
74         RESSCHED_LOGE("NotifierMgr has initialized");
75         return;
76     }
77     notifierDeathRecipient_ = sptr<IRemoteObject::DeathRecipient>(
78         new (std::nothrow) ResSchedCommonDeathRecipient([](const sptr<IRemoteObject>& notifier) {
79             NotifierMgr::GetInstance().OnRemoteNotifierDied(notifier);
80         }));
81     notifierHandler_ = std::make_shared<ffrt::queue>("DeviceNotifyQueue");
82     std::string systemload;
83     if (LoadStringFromFile(SYSTEMLOAD_FILE, systemload)) {
84         for (auto& vec : g_systemloadPair) {
85             if (vec.first == systemload) {
86                 systemloadLevel_ = vec.second;
87                 RESSCHED_LOGI("load systemload from file, value:%{public}d", (int)systemloadLevel_);
88             }
89         }
90     }
91     initialized_ = true;
92     ResschedEventReporter::GetInstance().ReportFileSizeEvent(SYSTEMLOAD_FILE);
93 }
94 
Deinit()95 void NotifierMgr::Deinit()
96 {
97     notifierHandler_.reset();
98 }
99 
RegisterNotifier(int32_t pid,const sptr<IRemoteObject> & notifier)100 void NotifierMgr::RegisterNotifier(int32_t pid, const sptr<IRemoteObject>& notifier)
101 {
102     RESSCHED_LOGD("RegisterNotifier called, pid = %{public}d.", pid);
103     if (notifier == nullptr) {
104         RESSCHED_LOGE("RegisterNotifier notifier is null");
105         return;
106     }
107     if (notifierDeathRecipient_ == nullptr) {
108         RESSCHED_LOGE("RegisterNotifier error due to notifierDeathRecipient null");
109         return;
110     }
111     // 加{}控制notifierMutex_锁作用域
112     {
113         std::lock_guard<std::mutex> autoLock(notifierMutex_);
114         auto iter = notifierMap_.find(pid);
115         if (iter == notifierMap_.end()) {
116             NotifierInfo info;
117             info.notifier = notifier;
118             info.hapApp = IsHapApp();
119             notifierMap_[pid] = info;
120             notifier->AddDeathRecipient(notifierDeathRecipient_);
121         }
122     }
123     NotifierMgr::GetInstance().ReportPidToHisysevent(pid);
124 }
125 
ReportPidToHisysevent(const int32_t pid)126 void NotifierMgr::ReportPidToHisysevent(const int32_t pid)
127 {
128     std::lock_guard<ffrt::mutex> autoLock(hisyseventMutex_);
129     std::string bundleName = NotifierMgr::GetInstance().GetBundleNameByPid(pid);
130     if (bundleName.empty()) {
131         RESSCHED_LOGW("pid %{public}d get bundleName error, not report", pid);
132         return;
133     }
134     hisyseventBundleNames_.insert(bundleName);
135     if (!isTaskSubmit_) {
136         NotifierMgr::GetInstance().NotifierEventReportDelay(FIRST_REPORT_DELAY_MS);
137         isTaskSubmit_ = true;
138     }
139     size_t size = hisyseventBundleNames_.size();
140     if (size >= MAX_REPORT_SIZE) {
141         NotifierMgr::GetInstance().NotifierEventReport();
142     }
143 }
144 
NotifierEventReportDelay(int64_t delay)145 void NotifierMgr::NotifierEventReportDelay(int64_t delay)
146 {
147     ffrt::submit([]() {
148          NotifierMgr::GetInstance().NotifierEventReportPeriod();
149         }, ffrt::task_attr().delay(delay));
150 }
151 
NotifierEventReportPeriod()152 void NotifierMgr::NotifierEventReportPeriod()
153 {
154     std::lock_guard<ffrt::mutex> autoLock(hisyseventMutex_);
155     NotifierMgr::GetInstance().NotifierEventReport();
156     NotifierEventReportDelay(REPORT_INTERVAL_MS);
157 }
158 
NotifierEventReport()159 void NotifierMgr::NotifierEventReport()
160 {
161     if (!hisyseventBundleNames_.empty()) {
162         std::vector<std::string> bundleNames;
163         for (const auto& item : hisyseventBundleNames_) {
164             bundleNames.emplace_back(item);
165         }
166         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "SYSTEM_LOAD_LEVEL",
167             HiviewDFX::HiSysEvent::EventType::STATISTIC, "BUNDLE_NAMES", bundleNames);
168     }
169     hisyseventBundleNames_.clear();
170 }
171 
GetBundleNameByPid(int32_t pid)172 std::string NotifierMgr::GetBundleNameByPid(int32_t pid)
173 {
174     std::string bundleName = "";
175     int32_t uid = 0;
176     if (appMgrClient_ == nullptr) {
177         appMgrClient_ = std::make_shared<AppExecFwk::AppMgrClient>();
178     }
179     std::string identity = IPCSkeleton::ResetCallingIdentity();
180     int32_t ret = static_cast<int32_t>(appMgrClient_->GetBundleNameByPid(pid, bundleName, uid));
181     IPCSkeleton::SetCallingIdentity(identity);
182     return bundleName;
183 }
184 
UnRegisterNotifier(int32_t pid)185 void NotifierMgr::UnRegisterNotifier(int32_t pid)
186 {
187     RESSCHED_LOGD("UnRegisterNotifier called");
188     std::lock_guard<std::mutex> autoLock(notifierMutex_);
189     auto iter = notifierMap_.find(pid);
190     if (iter != notifierMap_.end()) {
191         iter->second.notifier->RemoveDeathRecipient(notifierDeathRecipient_);
192         notifierMap_.erase(pid);
193     }
194 }
195 
OnRemoteNotifierDied(const sptr<IRemoteObject> & notifier)196 void NotifierMgr::OnRemoteNotifierDied(const sptr<IRemoteObject>& notifier)
197 {
198     RESSCHED_LOGD("OnRemoteNotifierDied called");
199     if (notifier == nullptr) {
200         RESSCHED_LOGW("remote notifier null");
201         return;
202     }
203     RemoveNotifierLock(notifier);
204 }
205 
OnDeviceLevelChanged(int32_t type,int32_t level)206 void NotifierMgr::OnDeviceLevelChanged(int32_t type, int32_t level)
207 {
208     RESSCHED_LOGD("OnDeviceLevelChanged called");
209     auto cbType = static_cast<ResType::DeviceStatus>(type);
210     if (g_DeviceStatusType.count(cbType) == 0) {
211         RESSCHED_LOGW("OnDeviceLevelChanged, no type matched");
212         return;
213     }
214 
215     systemloadLevel_ = static_cast<ResType::SystemloadLevel>(level);
216     for (auto& vec : g_systemloadPair) {
217         if (systemloadLevel_ == vec.second) {
218             if (SaveStringToFile(SYSTEMLOAD_FILE, vec.first)) {
219                 RESSCHED_LOGD("save systemload succeed,systemload is %{public}d", (int)vec.second);
220             } else {
221                 RESSCHED_LOGW("save systemload failed,systemload is %{public}d", (int)vec.second);
222             }
223         }
224     }
225 
226     if (notifierHandler_ == nullptr) {
227         RESSCHED_LOGE("OnDeviceLevelChanged error due to notifierHandler null.");
228         return;
229     }
230 
231     OnDeviceLevelChangedLock(level);
232 }
233 
OnApplicationStateChange(int32_t state,int32_t pid)234 void NotifierMgr::OnApplicationStateChange(int32_t state, int32_t pid)
235 {
236     RESSCHED_LOGD("OnApplicationStateChange called, state: %{public}d, pid : %{public}d .", state, pid);
237     std::lock_guard<std::mutex> autoLock(notifierMutex_);
238     auto iter = notifierMap_.find(pid);
239     if (iter == notifierMap_.end()) {
240         return;
241     }
242     auto& info = iter->second;
243     if (!info.hapApp) {
244         RESSCHED_LOGW("OnApplicationStateChange called, not app.");
245         return;
246     }
247     if (state == static_cast<int32_t>(ApplicationState::APP_STATE_FOREGROUND)) {
248         info.foreground = true;
249         if (systemloadLevel_ != info.level) {
250             info.level = systemloadLevel_;
251             std::vector<sptr<IRemoteObject>> vec{ info.notifier };
252             HandleDeviceLevelChange(vec, systemloadLevel_);
253         }
254     }
255     if (state == static_cast<int32_t>(ApplicationState::APP_STATE_BACKGROUND)
256         || state == static_cast<int32_t>(ApplicationState::APP_STATE_TERMINATED)
257         || state == static_cast<int32_t>(ApplicationState::APP_STATE_END)) {
258         info.foreground = false;
259     }
260 }
261 
GetSystemloadLevel()262 int32_t NotifierMgr::GetSystemloadLevel()
263 {
264     RESSCHED_LOGD("GetSystemloadLevel called");
265     return static_cast<int32_t>(systemloadLevel_);
266 }
267 
RemoveNotifierLock(const sptr<IRemoteObject> & notifier)268 void NotifierMgr::RemoveNotifierLock(const sptr<IRemoteObject>& notifier)
269 {
270     RESSCHED_LOGD("RemoveNotifierLock called");
271     std::lock_guard<std::mutex> autoLock(notifierMutex_);
272     for (auto& notifiers : notifierMap_) {
273         if (notifiers.second.notifier != notifier) {
274             continue;
275         }
276         notifiers.second.notifier->RemoveDeathRecipient(notifierDeathRecipient_);
277         notifierMap_.erase(notifiers.first);
278         return;
279     }
280 }
281 
OnDeviceLevelChangedLock(int32_t level)282 void NotifierMgr::OnDeviceLevelChangedLock(int32_t level)
283 {
284     std::vector<sptr<IRemoteObject>> notifierArray;
285     {
286         std::lock_guard<std::mutex> autoLock(notifierMutex_);
287         for (auto& notifiers : notifierMap_) {
288             auto pid = notifiers.first;
289             auto& info = notifiers.second;
290             if (info.hapApp && !info.foreground) {
291                 RESSCHED_LOGD("app on background, pid = %{public}d .", pid);
292                 continue;
293             }
294             info.level = level;
295             notifierArray.push_back(info.notifier);
296         }
297     }
298     HandleDeviceLevelChange(notifierArray, level);
299 }
300 
IsHapApp()301 bool NotifierMgr::IsHapApp()
302 {
303     Security::AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
304     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
305     if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
306         RESSCHED_LOGE("not hap app");
307         return false;
308     }
309     return true;
310 }
311 
DumpRegisterInfo()312 std::vector<std::pair<int32_t, bool>> NotifierMgr::DumpRegisterInfo()
313 {
314     std::vector<std::pair<int32_t, bool>> vec;
315     {
316         std::lock_guard<std::mutex> autoLock(notifierMutex_);
317         for (auto& notifiers : notifierMap_) {
318             vec.push_back({ notifiers.first, notifiers.second.hapApp });
319         }
320     }
321     return vec;
322 }
323 
HandleDeviceLevelChange(std::vector<sptr<IRemoteObject>> & notifierVec,int32_t level)324 void NotifierMgr::HandleDeviceLevelChange(std::vector<sptr<IRemoteObject>>& notifierVec, int32_t level)
325 {
326     auto func = [notifierVec, level] () {
327         for (auto& notifier : notifierVec) {
328             if (notifier == nullptr) {
329                 continue;
330             }
331             auto proxy = std::make_unique<ResSchedSystemloadNotifierProxy>(notifier);
332             proxy->OnSystemloadLevel(level);
333         }
334     };
335     notifierHandler_->submit(func);
336 }
337 } // ResourceSchedule
338 } // OHOS