1 /*
2 * Copyright (c) 2022-2023 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 "sched_controller.h"
17
18 #include "if_system_ability_manager.h"
19 #include "iservice_registry.h"
20 #include "system_ability_definition.h"
21 #include "app_mgr_interface.h"
22 #include "app_state_observer.h"
23 #include "app_startup_scene_rec.h"
24 #ifdef CONFIG_BGTASK_MGR
25 #include "background_task_mgr_helper.h"
26 #include "background_task_observer.h"
27 #endif
28 #include "bundle_mgr_interface.h"
29 #include "cgroup_adjuster.h"
30 #include "cgroup_event_handler.h"
31 #include "cgroup_sched_common.h"
32 #include "cgroup_sched_log.h"
33 #include "hisysevent.h"
34 #include "ressched_utils.h"
35 #include "res_type.h"
36 #include "supervisor.h"
37 #include "window_state_observer.h"
38 #ifdef POWER_MANAGER_ENABLE
39 #include "power_mgr_client.h"
40 #endif
41
42 #undef LOG_TAG
43 #define LOG_TAG "SchedController"
44
45 namespace OHOS {
46 namespace ResourceSchedule {
47 namespace {
48 const std::string CG_HANDLER_QUEUE = "CgroupEventHandlerQueue";
49 }
50
51 #ifdef CONFIG_BGTASK_MGR
52 using OHOS::BackgroundTaskMgr::BackgroundTaskMgrHelper;
53 #endif
54
GetAppManagerInstance()55 OHOS::sptr<OHOS::AppExecFwk::IAppMgr> GetAppManagerInstance()
56 {
57 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
58 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
59 OHOS::sptr<OHOS::IRemoteObject> object = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID);
60 return OHOS::iface_cast<OHOS::AppExecFwk::IAppMgr>(object);
61 }
62
GetInstance()63 SchedController& SchedController::GetInstance()
64 {
65 static SchedController instance;
66 return instance;
67 }
68
Init()69 void SchedController::Init()
70 {
71 ChronoScope cs("Init SchedController.");
72 // Init supervisor which contains cached data for ccgroup controller.
73 InitSupervisor();
74 // init dispatch resource function map
75 InitDispatchResFuncMap();
76 // Init cgroup handler thread
77 InitCgroupHandler();
78 // Init cgroup adjuster thread
79 InitCgroupAdjuster();
80 InitAppStartupSceneRec();
81 }
82
Deinit()83 void SchedController::Deinit()
84 {
85 if (cgHandler_) {
86 cgHandler_ = nullptr;
87 }
88 if (supervisor_) {
89 supervisor_ = nullptr;
90 }
91 DeinitAppStartupSceneRec();
92 }
93
94
UnregisterStateObservers()95 void SchedController::UnregisterStateObservers()
96 {
97 UnsubscribeAppState();
98 UnsubscribeBackgroundTask();
99 UnsubscribeWindowState();
100 }
101
GetProcessGroup(pid_t pid)102 int SchedController::GetProcessGroup(pid_t pid)
103 {
104 if (!supervisor_) {
105 CGS_LOGE("%{public}s, supervisor nullptr.", __func__);
106 return (int32_t)(SP_DEFAULT);
107 }
108 std::shared_ptr<ProcessRecord> pr = supervisor_->FindProcessRecord(pid);
109 return pr ? (int32_t)(pr->curSchedGroup_) : (int32_t)(SP_DEFAULT);
110 }
111
ReportAbilityStatus(int32_t saId,const std::string & deviceId,uint32_t status)112 void SchedController::ReportAbilityStatus(int32_t saId, const std::string& deviceId, uint32_t status)
113 {
114 CGS_LOGD("%{public}s sdId:%{public}d, status:%{public}d", __func__, saId, status);
115 auto handler = this->cgHandler_;
116 if (!handler) {
117 return;
118 }
119 handler->PostTask([handler, saId, deviceId, status] {
120 if (status > 0) {
121 handler->HandleAbilityAdded(saId, deviceId);
122 } else {
123 handler->HandleAbilityRemoved(saId, deviceId);
124 }
125 });
126 }
127
DispatchResource(uint32_t resType,int64_t value,const nlohmann::json & payload)128 void SchedController::DispatchResource(uint32_t resType, int64_t value, const nlohmann::json& payload)
129 {
130 auto handler = this->cgHandler_;
131 if (!handler) {
132 return;
133 }
134
135 auto iter = dispatchResFuncMap_.find(resType);
136 if (iter == dispatchResFuncMap_.end()) {
137 DispatchOtherResource(resType, value, payload);
138 return;
139 }
140 handler->PostTask([func = iter->second, handler, resType, value, payload] {
141 func(handler, resType, value, payload);
142 });
143 DispatchOtherResource(resType, value, payload);
144 }
145
DispatchOtherResource(uint32_t resType,int64_t value,const nlohmann::json & payload)146 void SchedController::DispatchOtherResource(uint32_t resType, int64_t value, const nlohmann::json& payload)
147 {
148 auto handler = this->cgHandler_;
149 if (!handler) {
150 return;
151 }
152 handler->PostTask([handler, resType, value, payload] {
153 switch (resType) {
154 case ResType::RES_TYPE_REPORT_CAMERA_STATE:
155 case ResType::RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE:
156 case ResType::RES_TYPE_WIFI_CONNECT_STATE_CHANGE:
157 case ResType::RES_TYPE_MMI_INPUT_STATE: {
158 handler->HandleReportHisysEvent(resType, value, payload);
159 break;
160 }
161 case ResType::RES_TYPE_REPORT_SCREEN_CAPTURE: {
162 handler->HandleReportScreenCaptureEvent(resType, value, payload);
163 break;
164 }
165 case ResType::RES_TYPE_AV_CODEC_STATE: {
166 handler->HandleReportAvCodecEvent(resType, value, payload);
167 break;
168 }
169 default: {
170 break;
171 }
172 }
173 });
174 ResSchedUtils::GetInstance().DispatchResourceExt(resType, value, payload);
175 }
176
GetBundleNameByUid(const int32_t uid)177 std::string SchedController::GetBundleNameByUid(const int32_t uid)
178 {
179 std::string bundleName = "";
180 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
181 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
182 OHOS::sptr<OHOS::IRemoteObject> object =
183 systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
184 sptr<AppExecFwk::IBundleMgr> iBundleMgr = OHOS::iface_cast<OHOS::AppExecFwk::IBundleMgr>(object);
185 if (!iBundleMgr) {
186 CGS_LOGD("%{public}s null bundle manager.", __func__);
187 return bundleName;
188 }
189
190 ErrCode ret = iBundleMgr->GetNameForUid(uid, bundleName);
191 if (ret != ERR_OK) {
192 CGS_LOGD("%{public}s get bundle name failed for %{public}d, err_code:%{public}d.", __func__, uid, ret);
193 }
194 return bundleName;
195 }
196
InitCgroupHandler()197 inline void SchedController::InitCgroupHandler()
198 {
199 cgHandler_ = std::make_shared<CgroupEventHandler>(CG_HANDLER_QUEUE);
200 cgHandler_->SetSupervisor(supervisor_);
201 }
202
InitCgroupAdjuster()203 inline void SchedController::InitCgroupAdjuster()
204 {
205 CgroupAdjuster::GetInstance().InitAdjuster();
206 }
207
InitSupervisor()208 inline void SchedController::InitSupervisor()
209 {
210 supervisor_ = std::make_shared<Supervisor>();
211 }
212
InitDispatchResFuncMap()213 void SchedController::InitDispatchResFuncMap()
214 {
215 dispatchResFuncMap_ = {
216 { ResType::RES_TYPE_REPORT_MMI_PROCESS, [](std::shared_ptr<CgroupEventHandler> handler,
217 uint32_t resType, int64_t value, const nlohmann::json& payload)
218 { handler->HandleReportMMIProcess(resType, value, payload); } },
219 { ResType::RES_TYPE_REPORT_RENDER_THREAD, [](std::shared_ptr<CgroupEventHandler> handler,
220 uint32_t resType, int64_t value, const nlohmann::json& payload)
221 { handler->HandleReportRenderThread(resType, value, payload); } },
222 { ResType::RES_TYPE_REPORT_KEY_THREAD, [](std::shared_ptr<CgroupEventHandler> handler,
223 uint32_t resType, int64_t value, const nlohmann::json& payload)
224 { handler->HandleReportKeyThread(resType, value, payload); } },
225 { ResType::RES_TYPE_REPORT_WINDOW_STATE, [](std::shared_ptr<CgroupEventHandler> handler,
226 uint32_t resType, int64_t value, const nlohmann::json& payload)
227 { handler->HandleReportWindowState(resType, value, payload); } },
228 { ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE, [](std::shared_ptr<CgroupEventHandler> handler,
229 uint32_t resType, int64_t value, const nlohmann::json& payload)
230 { handler->HandleReportWebviewAudioState(resType, value, payload); } },
231 { ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE, [](std::shared_ptr<CgroupEventHandler> handler,
232 uint32_t resType, int64_t value, const nlohmann::json& payload)
233 { handler->HandleReportAudioState(resType, value, payload); } },
234 { ResType::RES_TYPE_RUNNINGLOCK_STATE, [](std::shared_ptr<CgroupEventHandler> handler,
235 uint32_t resType, int64_t value, const nlohmann::json& payload)
236 { handler->HandleReportRunningLockEvent(resType, value, payload); } },
237 { ResType::RES_TYPE_REPORT_SCENE_BOARD, [](std::shared_ptr<CgroupEventHandler> handler,
238 uint32_t resType, int64_t value, const nlohmann::json& payload)
239 { handler->HandleSceneBoardState(resType, value, payload); } },
240 { ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE, [](std::shared_ptr<CgroupEventHandler> handler,
241 uint32_t resType, int64_t value, const nlohmann::json& payload)
242 { handler->HandleWebviewScreenCapture(resType, value, payload); } },
243 { ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE, [](std::shared_ptr<CgroupEventHandler> handler,
244 uint32_t resType, int64_t value, const nlohmann::json& payload)
245 { handler->HandleReportWebviewVideoState(resType, value, payload); } },
246 };
247 }
248
InitAppStartupSceneRec()249 inline void SchedController::InitAppStartupSceneRec()
250 {
251 AppStartupSceneRec::GetInstance().Init();
252 }
253
DeinitAppStartupSceneRec()254 inline void SchedController::DeinitAppStartupSceneRec()
255 {
256 AppStartupSceneRec::GetInstance().Deinit();
257 }
258
SubscribeAppState()259 bool SchedController::SubscribeAppState()
260 {
261 if (appStateObserver_) {
262 return true;
263 }
264 sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppManagerInstance();
265 if (!appManager) {
266 CGS_LOGE("%{public}s app manager nullptr!", __func__);
267 return false;
268 }
269 appStateObserver_ = new (std::nothrow)RmsApplicationStateObserver();
270 if (!appStateObserver_) {
271 CGS_LOGE("%{public}s allocate app state observer failed!", __func__);
272 return false;
273 }
274 int32_t err = appManager->RegisterApplicationStateObserver(appStateObserver_);
275 if (err != 0) {
276 CGS_LOGE("%{public}s register to appmanager failed. err:%{public}d", __func__, err);
277 appStateObserver_ = nullptr;
278 return false;
279 }
280 CGS_LOGI("%{public}s success.", __func__);
281 return true;
282 }
283
UnsubscribeAppState()284 void SchedController::UnsubscribeAppState()
285 {
286 if (!appStateObserver_) {
287 return;
288 }
289
290 sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppManagerInstance();
291 if (appManager) {
292 int32_t err = appManager->UnregisterApplicationStateObserver(appStateObserver_);
293 if (err == 0) {
294 CGS_LOGI("%{public}s success.", __func__);
295 } else {
296 CGS_LOGE("%{public}s failed. err:%{public}d", __func__, err);
297 }
298 }
299 appStateObserver_ = nullptr;
300 }
301
SubscribeBackgroundTask()302 bool SchedController::SubscribeBackgroundTask()
303 {
304 #ifdef CONFIG_BGTASK_MGR
305 if (isBgtaskSubscribed_) {
306 return true;
307 }
308 if (!backgroundTaskObserver_) {
309 backgroundTaskObserver_ = std::make_shared<BackgroundTaskObserver>();
310 }
311 int ret = BackgroundTaskMgrHelper::SubscribeBackgroundTask(*backgroundTaskObserver_);
312 if (ret != 0) {
313 CGS_LOGE("%{public}s failed, err:%{public}d.", __func__, ret);
314 return false;
315 }
316 isBgtaskSubscribed_ = true;
317 CGS_LOGI("%{public}s success.", __func__);
318 #endif
319 return true;
320 }
321
UnsubscribeBackgroundTask()322 void SchedController::UnsubscribeBackgroundTask()
323 {
324 #ifdef CONFIG_BGTASK_MGR
325 if (!isBgtaskSubscribed_ || !backgroundTaskObserver_) {
326 return;
327 }
328 int32_t ret = BackgroundTaskMgrHelper::UnsubscribeBackgroundTask(*backgroundTaskObserver_);
329 if (ret == 0) {
330 CGS_LOGI("%{public}s success.", __func__);
331 } else {
332 CGS_LOGE("%{public}s failed. ret:%{public}d", __func__, ret);
333 }
334 isBgtaskSubscribed_ = false;
335 #endif
336 }
337
SubscribeWindowState()338 void SchedController::SubscribeWindowState()
339 {
340 if (!windowStateObserver_) {
341 windowStateObserver_ = new (std::nothrow)WindowStateObserver();
342 if (windowStateObserver_) {
343 OHOS::Rosen::WMError ret =
344 OHOS::Rosen::WindowManagerLite::GetInstance().RegisterFocusChangedListener(windowStateObserver_);
345 if (ret != OHOS::Rosen::WMError::WM_OK) {
346 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT",
347 HiviewDFX::HiSysEvent::EventType::FAULT,
348 "COMPONENT_NAME", "MAIN",
349 "ERR_TYPE", "register failure",
350 "ERR_MSG", "Register a listener of window focus change failed.");
351 }
352 }
353 }
354 if (!windowVisibilityObserver_) {
355 windowVisibilityObserver_ = new (std::nothrow)WindowVisibilityObserver();
356 if (windowVisibilityObserver_) {
357 OHOS::Rosen::WMError ret = OHOS::Rosen::WindowManagerLite::GetInstance().
358 RegisterVisibilityChangedListener(windowVisibilityObserver_);
359 if (ret != OHOS::Rosen::WMError::WM_OK) {
360 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT",
361 HiviewDFX::HiSysEvent::EventType::FAULT,
362 "COMPONENT_NAME", "MAIN",
363 "ERR_TYPE", "register failure",
364 "ERR_MSG", "Register a listener of window visibility change failed.");
365 }
366 }
367 }
368 if (!windowDrawingContentObserver_) {
369 windowDrawingContentObserver_ = new (std::nothrow)WindowDrawingContentObserver();
370 if (windowDrawingContentObserver_) {
371 if (OHOS::Rosen::WindowManagerLite::GetInstance().
372 RegisterDrawingContentChangedListener(windowDrawingContentObserver_) != OHOS::Rosen::WMError::WM_OK) {
373 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT",
374 HiviewDFX::HiSysEvent::EventType::FAULT,
375 "COMPONENT_NAME", "MAIN", "ERR_TYPE", "register failure",
376 "ERR_MSG", "Register a listener of window draw content change failed.");
377 }
378 }
379 }
380 SubscribeWindowModeChange();
381 CGS_LOGI("%{public}s success.", __func__);
382 }
383
SubscribeWindowModeChange()384 void SchedController::SubscribeWindowModeChange()
385 {
386 if (!windowModeObserver_) {
387 windowModeObserver_ = new (std::nothrow)WindowModeObserver();
388 if (windowModeObserver_) {
389 if (OHOS::Rosen::WindowManagerLite::GetInstance().
390 RegisterWindowModeChangedListener(windowModeObserver_) != OHOS::Rosen::WMError::WM_OK) {
391 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS,
392 "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
393 "COMPONENT_NAME", "MAIN", "ERR_TYPE", "register failure",
394 "ERR_MSG", "Register a listener of window mode content change failed.");
395 }
396 }
397 }
398 }
399
UnsubscribeWindowState()400 void SchedController::UnsubscribeWindowState()
401 {
402 if (windowStateObserver_) {
403 // unregister windowStateObserver_
404 OHOS::Rosen::WindowManagerLite::GetInstance().UnregisterFocusChangedListener(windowStateObserver_);
405 windowStateObserver_ = nullptr;
406 }
407
408 if (windowVisibilityObserver_) {
409 OHOS::Rosen::WindowManagerLite::GetInstance().UnregisterVisibilityChangedListener(windowVisibilityObserver_);
410 windowVisibilityObserver_ = nullptr;
411 }
412
413 if (windowDrawingContentObserver_) {
414 OHOS::Rosen::WindowManagerLite::GetInstance().
415 UnregisterDrawingContentChangedListener(windowDrawingContentObserver_);
416 windowDrawingContentObserver_ = nullptr;
417 }
418 UnsubscribeWindowModeChange();
419 }
420
UnsubscribeWindowModeChange()421 void SchedController::UnsubscribeWindowModeChange()
422 {
423 if (windowModeObserver_) {
424 OHOS::Rosen::WindowManagerLite::GetInstance().
425 UnregisterWindowModeChangedListener(windowModeObserver_);
426 windowModeObserver_ = nullptr;
427 }
428 CGS_LOGI("UnsubscribeWindowModeChange success");
429 }
430
431 #ifdef POWER_MANAGER_ENABLE
GetRunningLockState()432 void SchedController::GetRunningLockState()
433 {
434 if (!supervisor_) {
435 CGS_LOGE("%{public}s, supervisor nullptr.", __func__);
436 return;
437 }
438 std::map<std::string, PowerMgr::RunningLockInfo> runningLockLists;
439 bool ret = PowerMgr::PowerMgrClient::GetInstance().QueryRunningLockLists(runningLockLists);
440 if (!ret) {
441 CGS_LOGE("%{public}s get running lock list failed.", __func__);
442 return;
443 }
444 for (auto it = runningLockLists.begin(); it != runningLockLists.end(); it++) {
445 std::string bundleName = it->first;
446 PowerMgr::RunningLockInfo lockInfo = it->second;
447 std::shared_ptr<Application> app = supervisor_->GetAppRecordNonNull(lockInfo.uid);
448 std::shared_ptr<ProcessRecord> procRecord = app->GetProcessRecordNonNull(lockInfo.pid);
449 uint32_t key = static_cast<uint32_t>(lockInfo.type);
450 procRecord->runningLockState_[key] = true;
451 }
452 }
453 #endif
454
CgroupSchedInit()455 extern "C" void CgroupSchedInit()
456 {
457 SchedController::GetInstance().Init();
458 }
459
CgroupSchedDeinit()460 extern "C" void CgroupSchedDeinit()
461 {
462 SchedController::GetInstance().Deinit();
463 SchedController::GetInstance().UnregisterStateObservers();
464 }
465
GetProcessGroup(pid_t pid)466 extern "C" int GetProcessGroup(pid_t pid)
467 {
468 return SchedController::GetInstance().GetProcessGroup(pid);
469 }
470
ReportAbilityStatus(int32_t saId,const std::string & deviceId,uint32_t status)471 extern "C" void ReportAbilityStatus(int32_t saId, const std::string& deviceId, uint32_t status)
472 {
473 SchedController::GetInstance().ReportAbilityStatus(saId, deviceId, status);
474 }
475
CgroupSchedDispatch(uint32_t resType,int64_t value,const nlohmann::json & payload)476 extern "C" void CgroupSchedDispatch(uint32_t resType, int64_t value, const nlohmann::json& payload)
477 {
478 SchedController::GetInstance().DispatchResource(resType, value, payload);
479 }
480 } // namespace ResourceSchedule
481 } // namespace OHOS
482