1 /*
2  * Copyright (c) 2022-2024 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 "app_state_observer.h"
17 
18 #include "sched_controller.h"
19 #include "cgroup_event_handler.h"
20 #include "cgroup_sched_log.h"
21 #include "ressched_utils.h"
22 #include "res_type.h"
23 #include "ffrt.h"
24 #include "app_startup_scene_rec.h"
25 #include "supervisor.h"
26 
27 #undef LOG_TAG
28 #define LOG_TAG "RmsAppStateObserver"
29 
30 namespace OHOS {
31 namespace ResourceSchedule {
OnForegroundApplicationChanged(const AppStateData & appStateData)32 void RmsApplicationStateObserver::OnForegroundApplicationChanged(const AppStateData &appStateData)
33 {
34     if (!ValidateAppStateData(appStateData)) {
35         CGS_LOGE("%{public}s : validate app state data failed!", __func__);
36         return;
37     }
38     nlohmann::json payload;
39     payload["pid"] = std::to_string(appStateData.pid);
40     payload["uid"] = std::to_string(appStateData.uid);
41     payload["bundleName"] = appStateData.bundleName;
42     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_APP_STATE_CHANGE, appStateData.state, payload);
43 }
44 
OnAbilityStateChanged(const AbilityStateData & abilityStateData)45 void RmsApplicationStateObserver::OnAbilityStateChanged(const AbilityStateData &abilityStateData)
46 {
47     if (!ValidateAbilityStateData(abilityStateData)) {
48         CGS_LOGE("%{public}s : validate ability state data failed!", __func__);
49         return;
50     }
51     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
52     std::string bundleName = abilityStateData.bundleName;
53     int32_t abilityState = abilityStateData.abilityState;
54     if (cgHandler) {
55         auto uid = abilityStateData.uid;
56         auto pid = abilityStateData.pid;
57         auto abilityName = abilityStateData.abilityName;
58         auto token = reinterpret_cast<uintptr_t>(abilityStateData.token.GetRefPtr());
59         auto abilityType = abilityStateData.abilityType;
60 
61         cgHandler->PostTask([cgHandler, uid, pid, bundleName, abilityName, token, abilityState, abilityType] {
62             cgHandler->HandleAbilityStateChanged(uid, pid, bundleName, abilityName,
63                 token, abilityState, abilityType);
64         });
65     }
66 
67     nlohmann::json payload;
68     std::string uid = std::to_string(abilityStateData.uid);
69     payload["pid"] = std::to_string(abilityStateData.pid);
70     payload["uid"] = uid;
71     payload["bundleName"] = bundleName;
72     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_ABILITY_STATE_CHANGE,
73         abilityState, payload);
74     ffrt::submit([abilityState, uid, bundleName, this]() {
75         AppStartupSceneRec::GetInstance().RecordIsContinuousStartup(
76             abilityState, uid, bundleName);
77     });
78 }
79 
OnExtensionStateChanged(const AbilityStateData & abilityStateData)80 void RmsApplicationStateObserver::OnExtensionStateChanged(const AbilityStateData &abilityStateData)
81 {
82     if (!ValidateAbilityStateData(abilityStateData)) {
83         CGS_LOGE("%{public}s : validate extension state data failed!", __func__);
84         return;
85     }
86     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
87     if (cgHandler) {
88         auto uid = abilityStateData.uid;
89         auto pid = abilityStateData.pid;
90         auto bundleName = abilityStateData.bundleName;
91         auto abilityName = abilityStateData.abilityName;
92         auto token = reinterpret_cast<uintptr_t>(abilityStateData.token.GetRefPtr());
93         auto abilityState = abilityStateData.abilityState;
94         auto abilityType = abilityStateData.abilityType;
95 
96         cgHandler->PostTask([cgHandler, uid, pid, bundleName, abilityName, token, abilityState, abilityType] {
97             cgHandler->HandleExtensionStateChanged(uid, pid, bundleName, abilityName,
98                 token, abilityState, abilityType);
99         });
100     }
101 
102     nlohmann::json payload;
103     payload["pid"] = std::to_string(abilityStateData.pid);
104     payload["uid"] = std::to_string(abilityStateData.uid);
105     payload["bundleName"] = abilityStateData.bundleName;
106     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_EXTENSION_STATE_CHANGE,
107         abilityStateData.abilityState, payload);
108 }
109 
MarshallingProcessData(const ProcessData & processData,nlohmann::json & payload)110 void RmsApplicationStateObserver::MarshallingProcessData(const ProcessData &processData, nlohmann::json &payload)
111 {
112     payload["pid"] = std::to_string(processData.pid);
113     payload["uid"] = std::to_string(processData.uid);
114     payload["processType"] = std::to_string(static_cast<int32_t>(processData.processType));
115     payload["renderUid"] = std::to_string(processData.renderUid);
116     payload["bundleName"] = processData.bundleName;
117     payload["state"] = std::to_string(static_cast<uint32_t>(processData.state));
118     payload["extensionType"] = std::to_string(static_cast<uint32_t>(processData.extensionType));
119     payload["isKeepAlive"] = std::to_string(processData.isKeepAlive);
120     payload["isTestMode"] = std::to_string(processData.isTestMode);
121     payload["processName"] = processData.processName;
122     payload["exitReason"] = std::to_string(processData.exitReason);
123     payload["hostPid"] = std::to_string(processData.hostPid);
124 }
125 
OnProcessCreated(const ProcessData & processData)126 void RmsApplicationStateObserver::OnProcessCreated(const ProcessData &processData)
127 {
128     if (!ValidateProcessData(processData)) {
129         CGS_LOGE("%{public}s : validate process data failed!", __func__);
130         return;
131     }
132     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
133     if (cgHandler) {
134         auto uid = processData.uid;
135         auto pid = processData.pid;
136         auto hostPid = processData.hostPid;
137         auto bundleName = processData.bundleName;
138         auto processType = static_cast<int32_t>(processData.processType);
139         auto extensionType = static_cast<int32_t>(processData.extensionType);
140         cgHandler->PostTask([cgHandler, uid, pid, hostPid, processType, bundleName, extensionType] {
141             cgHandler->HandleProcessCreated(uid, pid, hostPid, processType, bundleName, extensionType);
142         });
143     }
144 
145     nlohmann::json payload;
146     MarshallingProcessData(processData, payload);
147     ResSchedUtils::GetInstance().ReportDataInProcess(
148         ResType::RES_TYPE_PROCESS_STATE_CHANGE, ResType::ProcessStatus::PROCESS_CREATED, payload);
149 }
150 
OnProcessDied(const ProcessData & processData)151 void RmsApplicationStateObserver::OnProcessDied(const ProcessData &processData)
152 {
153     if (!ValidateProcessData(processData)) {
154         CGS_LOGE("%{public}s : validate process data failed!", __func__);
155         return;
156     }
157     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
158     if (cgHandler) {
159         auto uid = processData.uid;
160         auto pid = processData.pid;
161         auto bundleName = processData.bundleName;
162 
163         cgHandler->PostTask([cgHandler, uid, pid, bundleName] {
164             cgHandler->HandleProcessDied(uid, pid, bundleName);
165         });
166     }
167 
168     nlohmann::json payload;
169     MarshallingProcessData(processData, payload);
170     ResSchedUtils::GetInstance().ReportDataInProcess(
171         ResType::RES_TYPE_PROCESS_STATE_CHANGE, ResType::ProcessStatus::PROCESS_DIED, payload);
172 }
173 
OnApplicationStateChanged(const AppStateData & appStateData)174 void RmsApplicationStateObserver::OnApplicationStateChanged(const AppStateData &appStateData)
175 {
176     if (!ValidateAppStateData(appStateData)) {
177         CGS_LOGE("%{public}s : validate app state data failed!", __func__);
178         return;
179     }
180 
181     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
182     if (cgHandler) {
183         auto uid = appStateData.uid;
184         auto pid = appStateData.pid;
185         auto bundleName = appStateData.bundleName;
186         auto state = appStateData.state;
187 
188         cgHandler->PostTask([cgHandler, uid, pid, bundleName, state] {
189             cgHandler->HandleApplicationStateChanged(uid, pid, bundleName, state);
190         });
191     }
192 
193     nlohmann::json payload;
194     payload["pid"] = std::to_string(appStateData.pid);
195     payload["uid"] = std::to_string(appStateData.uid);
196     payload["bundleName"] = appStateData.bundleName;
197     payload["extensionType"] = std::to_string(static_cast<uint32_t>(appStateData.extensionType));
198     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_APP_STATE_CHANGE, appStateData.state, payload);
199     ResSchedUtils::GetInstance().ReportAppStateInProcess(appStateData.state, appStateData.pid);
200 }
201 
MarshallingAppStateData(const AppStateData & appStateData,nlohmann::json & payload)202 void RmsApplicationStateObserver::MarshallingAppStateData(const AppStateData &appStateData, nlohmann::json &payload)
203 {
204     payload["pid"] = appStateData.pid;
205     payload["uid"] = appStateData.uid;
206     payload["bundleName"] = appStateData.bundleName;
207     payload["state"] = static_cast<uint32_t>(appStateData.state);
208     payload["extensionType"] = static_cast<uint32_t>(appStateData.extensionType);
209     payload["isFocused"] = static_cast<bool>(appStateData.isFocused);
210 }
211 
OnAppStateChanged(const AppStateData & appStateData)212 void RmsApplicationStateObserver::OnAppStateChanged(const AppStateData &appStateData)
213 {
214     if (!ValidateAppStateData(appStateData)) {
215         CGS_LOGE("%{public}s : validate app state data failed!", __func__);
216         return;
217     }
218 
219     nlohmann::json payload;
220     MarshallingAppStateData(appStateData, payload);
221     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_ON_APP_STATE_CHANGED, appStateData.state,
222         payload);
223     ResSchedUtils::GetInstance().ReportAppStateInProcess(appStateData.state, appStateData.pid);
224 }
225 
OnAppCacheStateChanged(const AppStateData & appStateData)226 void RmsApplicationStateObserver::OnAppCacheStateChanged(const AppStateData &appStateData)
227 {
228     if (!ValidateAppStateData(appStateData)) {
229         CGS_LOGE("%{public}s : validate app state data failed!", __func__);
230         return;
231     }
232 
233     nlohmann::json payload;
234     MarshallingAppStateData(appStateData, payload);
235     const int RES_TYPE_EXT_ON_APP_CACHED_STATE_CHANGED = 10008;
236     payload["extType"] = std::to_string(RES_TYPE_EXT_ON_APP_CACHED_STATE_CHANGED);
237     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_KEY_PERF_SCENE, appStateData.state, payload);
238 }
239 
OnProcessStateChanged(const ProcessData & processData)240 void RmsApplicationStateObserver::OnProcessStateChanged(const ProcessData &processData)
241 {
242     if (!ValidateProcessData(processData)) {
243         CGS_LOGE("%{public}s : validate process data failed!", __func__);
244         return;
245     }
246     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
247     if (cgHandler) {
248         auto uid = processData.uid;
249         auto pid = processData.pid;
250         auto bundleName = processData.bundleName;
251         auto state = static_cast<int32_t>(processData.state);
252 
253         cgHandler->PostTask([cgHandler, uid, pid, bundleName, state] {
254             cgHandler->HandleProcessStateChanged(uid, pid, bundleName, state);
255         });
256     }
257 
258     nlohmann::json payload;
259     MarshallingProcessData(processData, payload);
260     ResSchedUtils::GetInstance().ReportDataInProcess(
261         ResType::RES_TYPE_PROCESS_STATE_CHANGE, static_cast<int32_t>(processData.state), payload);
262 }
263 
OnAppStopped(const AppStateData & appStateData)264 void RmsApplicationStateObserver::OnAppStopped(const AppStateData &appStateData)
265 {
266     if (!ValidateAppStateData(appStateData)) {
267         CGS_LOGE("%{public}s : validate app state data failed!", __func__);
268         return;
269     }
270 
271     auto cgHandler = SchedController::GetInstance().GetCgroupEventHandler();
272     if (cgHandler) {
273         auto uid = appStateData.uid;
274         auto bundleName = appStateData.bundleName;
275 
276         cgHandler->PostTask([cgHandler, uid, bundleName] {
277             cgHandler->HandleOnAppStopped(uid, bundleName);
278         });
279     }
280 
281     nlohmann::json payload;
282     MarshallingAppStateData(appStateData, payload);
283     ResSchedUtils::GetInstance().ReportDataInProcess(ResType::RES_TYPE_APP_STOPPED, appStateData.state, payload);
284 }
285 } // namespace ResourceSchedule
286 } // namespace OHOS
287