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