1 /*
2 * Copyright (c) 2022 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 #ifdef CONFIG_BGTASK_MGR
24 #include "background_task_mgr_helper.h"
25 #include "background_task_observer.h"
26 #endif
27 #include "bundle_mgr_interface.h"
28 #include "cgroup_adjuster.h"
29 #include "cgroup_event_handler.h"
30 #include "cgroup_sched_common.h"
31 #include "cgroup_sched_log.h"
32 #include "hisysevent.h"
33 #include "ressched_utils.h"
34 #include "res_type.h"
35 #include "supervisor.h"
36 #include "window_state_observer.h"
37
38 namespace OHOS {
39 namespace ResourceSchedule {
40 namespace {
41 const std::string CG_HANDLER_THREAD = "CgroupEventHandler";
42 constexpr HiviewDFX::HiLogLabel LOG_LABEL = {LOG_CORE, LOG_TAG_DOMAIN_ID_RMS, "SchedController"};
43 }
44
45 #ifdef CONFIG_BGTASK_MGR
46 using OHOS::BackgroundTaskMgr::BackgroundTaskMgrHelper;
47 #endif
48
GetAppManagerInstance()49 OHOS::sptr<OHOS::AppExecFwk::IAppMgr> GetAppManagerInstance()
50 {
51 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
52 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
53 OHOS::sptr<OHOS::IRemoteObject> object = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID);
54 return OHOS::iface_cast<OHOS::AppExecFwk::IAppMgr>(object);
55 }
56
GetInstance()57 SchedController& SchedController::GetInstance()
58 {
59 static SchedController instance;
60 return instance;
61 }
62
Init()63 void SchedController::Init()
64 {
65 ChronoScope cs("Init SchedController.");
66 // Init supervisor which contains cached data for ccgroup controller.
67 InitSupervisor();
68 // Init cgroup handler thread
69 InitCgroupHandler();
70 // Init cgroup adjuster thread
71 InitCgroupAdjuster();
72 }
73
Deinit()74 void SchedController::Deinit()
75 {
76 if (cgHandler_) {
77 cgHandler_->RemoveAllEvents();
78 cgHandler_ = nullptr;
79 }
80 if (supervisor_) {
81 supervisor_ = nullptr;
82 }
83 }
84
UnregisterStateObservers()85 void SchedController::UnregisterStateObservers()
86 {
87 UnsubscribeAppState();
88 UnsubscribeBackgroundTask();
89 UnsubscribeWindowState();
90 }
91
GetProcessGroup(pid_t pid)92 int SchedController::GetProcessGroup(pid_t pid)
93 {
94 if (!supervisor_) {
95 CGS_LOGE("%{public}s, supervisor nullptr.", __func__);
96 return (int32_t)(SP_DEFAULT);
97 }
98 std::shared_ptr<ProcessRecord> pr = supervisor_->FindProcessRecord(pid);
99 return pr ? (int32_t)(pr->curSchedGroup_) : (int32_t)(SP_DEFAULT);
100 }
101
ReportAbilityStatus(int32_t saId,const std::string & deviceId,uint32_t status)102 void SchedController::ReportAbilityStatus(int32_t saId, const std::string& deviceId, uint32_t status)
103 {
104 CGS_LOGD("%{public}s sdId:%{public}d, status:%{public}d", __func__, saId, status);
105 auto handler = this->cgHandler_;
106 if (!handler) {
107 return;
108 }
109 handler->PostTask([handler, saId, deviceId, status] {
110 if (status > 0) {
111 handler->HandleAbilityAdded(saId, deviceId);
112 } else {
113 handler->HandleAbilityRemoved(saId, deviceId);
114 }
115 });
116 }
117
DispatchResource(uint32_t resType,int64_t value,const nlohmann::json & payload)118 void SchedController::DispatchResource(uint32_t resType, int64_t value, const nlohmann::json& payload)
119 {
120 auto handler = this->cgHandler_;
121 if (!handler) {
122 return;
123 }
124 handler->PostTask([handler, resType, value, payload] {
125 switch (resType) {
126 case ResType::RES_TYPE_REPORT_MMI_PROCESS: {
127 handler->HandleReportMMIProcess(resType, value, payload);
128 break;
129 }
130 case ResType::RES_TYPE_REPORT_RENDER_THREAD: {
131 handler->HandleReportRenderThread(resType, value, payload);
132 break;
133 }
134 default: {
135 break;
136 }
137 }
138 });
139 }
140
GetBundleNameByUid(const int32_t uid)141 std::string SchedController::GetBundleNameByUid(const int32_t uid)
142 {
143 std::string bundleName = "";
144 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
145 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
146 OHOS::sptr<OHOS::IRemoteObject> object =
147 systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
148 sptr<AppExecFwk::IBundleMgr> iBundleMgr = OHOS::iface_cast<OHOS::AppExecFwk::IBundleMgr>(object);
149 if (!iBundleMgr) {
150 CGS_LOGD("%{public}s null bundle manager.", __func__);
151 return bundleName;
152 }
153
154 ErrCode ret = iBundleMgr->GetNameForUid(uid, bundleName);
155 if (ret != ERR_OK) {
156 CGS_LOGD("%{public}s get bundle name failed for %{public}d, err_code:%{public}d.", __func__, uid, ret);
157 }
158 return bundleName;
159 }
160
InitCgroupHandler()161 inline void SchedController::InitCgroupHandler()
162 {
163 cgHandler_ = std::make_shared<CgroupEventHandler>(OHOS::AppExecFwk::EventRunner::Create(CG_HANDLER_THREAD));
164 cgHandler_->SetSupervisor(supervisor_);
165 }
166
InitCgroupAdjuster()167 inline void SchedController::InitCgroupAdjuster()
168 {
169 CgroupAdjuster::GetInstance().InitAdjuster();
170 }
171
InitSupervisor()172 inline void SchedController::InitSupervisor()
173 {
174 supervisor_ = std::make_shared<Supervisor>();
175 }
176
SubscribeAppState()177 bool SchedController::SubscribeAppState()
178 {
179 if (appStateObserver_) {
180 return true;
181 }
182 sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppManagerInstance();
183 if (!appManager) {
184 CGS_LOGE("%{public}s app manager nullptr!", __func__);
185 return false;
186 }
187 appStateObserver_ = new (std::nothrow)RmsApplicationStateObserver();
188 if (!appStateObserver_) {
189 CGS_LOGE("%{public}s allocate app state observer failed!", __func__);
190 return false;
191 }
192 int32_t err = appManager->RegisterApplicationStateObserver(appStateObserver_);
193 if (err != 0) {
194 CGS_LOGE("%{public}s register to appmanager failed. err:%{public}d", __func__, err);
195 appStateObserver_ = nullptr;
196 return false;
197 }
198 CGS_LOGI("%{public}s success.", __func__);
199 return true;
200 }
201
UnsubscribeAppState()202 void SchedController::UnsubscribeAppState()
203 {
204 if (!appStateObserver_) {
205 return;
206 }
207
208 sptr<OHOS::AppExecFwk::IAppMgr> appManager = GetAppManagerInstance();
209 if (appManager) {
210 int32_t err = appManager->UnregisterApplicationStateObserver(appStateObserver_);
211 if (err == 0) {
212 CGS_LOGI("%{public}s success.", __func__);
213 } else {
214 CGS_LOGE("%{public}s failed. err:%{public}d", __func__, err);
215 }
216 }
217 appStateObserver_ = nullptr;
218 }
219
SubscribeBackgroundTask()220 bool SchedController::SubscribeBackgroundTask()
221 {
222 #ifdef CONFIG_BGTASK_MGR
223 if (backgroundTaskObserver_) {
224 return true;
225 }
226 backgroundTaskObserver_ = std::make_shared<BackgroundTaskObserver>();
227 int ret = BackgroundTaskMgrHelper::SubscribeBackgroundTask(*backgroundTaskObserver_);
228 if (ret != 0) {
229 backgroundTaskObserver_ = nullptr;
230 CGS_LOGE("%{public}s failed, err:%{public}d.", __func__, ret);
231 return false;
232 }
233 CGS_LOGI("%{public}s success.", __func__);
234 #endif
235 return true;
236 }
237
UnsubscribeBackgroundTask()238 void SchedController::UnsubscribeBackgroundTask()
239 {
240 #ifdef CONFIG_BGTASK_MGR
241 if (!backgroundTaskObserver_) {
242 return;
243 }
244 int32_t ret = BackgroundTaskMgrHelper::UnsubscribeBackgroundTask(*backgroundTaskObserver_);
245 if (ret == 0) {
246 CGS_LOGI("%{public}s success.", __func__);
247 } else {
248 CGS_LOGE("%{public}s failed. ret:%{public}d", __func__, ret);
249 }
250 backgroundTaskObserver_ = nullptr;
251 #endif
252 }
253
SubscribeWindowState()254 void SchedController::SubscribeWindowState()
255 {
256 if (!windowStateObserver_) {
257 windowStateObserver_ = new (std::nothrow)WindowStateObserver();
258 if (windowStateObserver_) {
259 if (OHOS::Rosen::WindowManager::GetInstance().RegisterFocusChangedListener(windowStateObserver_) != OHOS::Rosen::WMError::WM_OK) {
260 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
261 "COMPONENT_NAME", "MAIN",
262 "ERR_TYPE", "register failure",
263 "ERR_MSG", "Register a listener of window focus change failed.");
264 }
265 }
266 }
267 if (!windowVisibilityObserver_) {
268 windowVisibilityObserver_ = new (std::nothrow)WindowVisibilityObserver();
269 if (windowVisibilityObserver_) {
270 if(OHOS::Rosen::WindowManager::GetInstance().RegisterVisibilityChangedListener(windowVisibilityObserver_) != OHOS::Rosen::WMError::WM_OK) {
271 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
272 "COMPONENT_NAME", "MAIN",
273 "ERR_TYPE", "register failure",
274 "ERR_MSG", "Register a listener of window visibility change failed.");
275 }
276 }
277 }
278 CGS_LOGI("%{public}s success.", __func__);
279 }
280
UnsubscribeWindowState()281 void SchedController::UnsubscribeWindowState()
282 {
283 if (windowStateObserver_) {
284 // unregister windowStateObserver_
285 OHOS::Rosen::WindowManager::GetInstance().UnregisterFocusChangedListener(windowStateObserver_);
286 windowStateObserver_ = nullptr;
287 }
288
289 if (windowVisibilityObserver_) {
290 OHOS::Rosen::WindowManager::GetInstance().UnregisterVisibilityChangedListener(windowVisibilityObserver_);
291 windowVisibilityObserver_ = nullptr;
292 }
293 }
294
CgroupSchedInit()295 extern "C" void CgroupSchedInit()
296 {
297 SchedController::GetInstance().Init();
298 }
299
CgroupSchedDeinit()300 extern "C" void CgroupSchedDeinit()
301 {
302 SchedController::GetInstance().Deinit();
303 SchedController::GetInstance().UnregisterStateObservers();
304 }
305
GetProcessGroup(pid_t pid)306 extern "C" int GetProcessGroup(pid_t pid)
307 {
308 return SchedController::GetInstance().GetProcessGroup(pid);
309 }
310
ReportAbilityStatus(int32_t saId,const std::string & deviceId,uint32_t status)311 extern "C" void ReportAbilityStatus(int32_t saId, const std::string& deviceId, uint32_t status)
312 {
313 SchedController::GetInstance().ReportAbilityStatus(saId, deviceId, status);
314 }
315
CgroupSchedDispatch(uint32_t resType,int64_t value,const nlohmann::json & payload)316 extern "C" void CgroupSchedDispatch(uint32_t resType, int64_t value, const nlohmann::json& payload)
317 {
318 SchedController::GetInstance().DispatchResource(resType, value, payload);
319 }
320 } // namespace ResourceSchedule
321 } // namespace OHOS
322