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