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