1 /*
2 * Copyright (c) 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 "fold_event_cacher.h"
17
18 #include "bundle_mgr_client.h"
19 #include "display_manager.h"
20 #include "hiview_logger.h"
21 #include "iremote_object.h"
22 #include "iservice_registry.h"
23 #include "system_ability_definition.h"
24 #include "time_util.h"
25 #include "usage_event_common.h"
26
27 namespace OHOS {
28 namespace HiviewDFX {
29 DEFINE_LOG_TAG("FoldEventCacher");
30 namespace {
31 constexpr int MAX_FOREGROUND_APPS_SIZE = 10;
32 constexpr int UNKNOWN_FOLD_STATUS = -1;
33 constexpr int ONE_HOUR_INTERVAL = 3600;
34 constexpr int MILLISEC_TO_MICROSEC = 1000;
35
GetAppManagerService()36 sptr<AppExecFwk::IAppMgr> GetAppManagerService()
37 {
38 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
39 if (systemAbilityManager == nullptr) {
40 HIVIEW_LOGI("failed to get samgr");
41 return nullptr;
42 }
43 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
44 if (remoteObject == nullptr) {
45 HIVIEW_LOGI("failed to get app manager service");
46 return nullptr;
47 }
48 return iface_cast<AppExecFwk::IAppMgr>(remoteObject);
49 }
50
GetForegroundApplications()51 std::vector<AppExecFwk::AppStateData> GetForegroundApplications()
52 {
53 sptr<AppExecFwk::IAppMgr> appManager = GetAppManagerService();
54 std::vector<AppExecFwk::AppStateData> fgList;
55 if (appManager == nullptr) {
56 HIVIEW_LOGI("appManager iface_cast is nullptr");
57 return fgList;
58 }
59 int32_t errcode = appManager->GetForegroundApplications(fgList);
60 size_t fgListSize = fgList.size();
61 HIVIEW_LOGI("errcode=%{public}d,fgListSize=%{public}zu", errcode, fgListSize);
62 return fgList;
63 }
64
GetAppVersion(const std::string & bundleName)65 std::string GetAppVersion(const std::string& bundleName)
66 {
67 AppExecFwk::BundleInfo info;
68 AppExecFwk::BundleMgrClient client;
69 if (!client.GetBundleInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, info,
70 AppExecFwk::Constants::ALL_USERID)) {
71 HIVIEW_LOGE("Failed to get the version of the bundle");
72 return "";
73 }
74 return info.versionName;
75 }
76
GetCombineScreenStatus(int foldStatus,int vhMode)77 int GetCombineScreenStatus(int foldStatus, int vhMode)
78 {
79 if (foldStatus == 1 && vhMode == 1) { // foldStatus: 1-expand status
80 return ScreenFoldStatus::EXPAND_LANDSCAPE_STATUS;
81 }
82 if (foldStatus == 1 && vhMode == 0) {
83 return ScreenFoldStatus::EXPAND_PORTRAIT_STATUS;
84 }
85 if ((foldStatus == 2 || foldStatus == 3) && vhMode == 1) { // foldStatus: 2-fold status 3- half fold status
86 return ScreenFoldStatus::FOLD_LANDSCAPE_STATUS;
87 }
88 if ((foldStatus == 2 || foldStatus == 3) && vhMode == 0) { // foldStatus: 2-fold status 3- half fold status
89 return ScreenFoldStatus::FOLD_PORTRAIT_STATUS;
90 }
91 return UNKNOWN_FOLD_STATUS;
92 }
93 } // namespace
94
FoldEventCacher(const std::string & workPath)95 FoldEventCacher::FoldEventCacher(const std::string& workPath)
96 {
97 timelyStart_ = TimeUtil::GetBootTimeMs();
98 dbHelper_ = std::make_unique<FoldAppUsageDbHelper>(workPath);
99
100 foldStatus_ = static_cast<int>(OHOS::Rosen::DisplayManager::GetInstance().GetFoldStatus());
101 auto display = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
102 if (display != nullptr) {
103 int orientation = static_cast<int>(display->GetRotation());
104 if (orientation == 0 || orientation == 2) { // 0-Portrait 2-portrait_inverted
105 vhMode_ = 0; // 0-Portrait
106 } else {
107 vhMode_ = 1; // 1-landscape
108 }
109 }
110 HIVIEW_LOGI("foldStatus=%{public}d,vhMode=%{public}d", foldStatus_, vhMode_);
111 auto fgList = GetForegroundApplications();
112 for (const auto& appData : fgList) {
113 if (FoldAppUsageEventSpace::SCENEBOARD_BUNDLE_NAME == appData.bundleName) {
114 continue;
115 }
116 foregroundApps_[appData.bundleName] = GetAppVersion(appData.bundleName);
117 }
118 }
119
TimeOut()120 void FoldEventCacher::TimeOut()
121 {
122 uint64_t bootTime = TimeUtil::GetBootTimeMs();
123 uint64_t timeInterval = bootTime - timelyStart_;
124 if (timeInterval < static_cast<uint64_t>(ONE_HOUR_INTERVAL * TimeUtil::SEC_TO_MILLISEC)) {
125 return;
126 }
127 auto fgList = GetForegroundApplications();
128 for (const auto& appData : fgList) {
129 if (FoldAppUsageEventSpace::SCENEBOARD_BUNDLE_NAME == appData.bundleName) {
130 continue;
131 }
132 auto it = foregroundApps_.find(appData.bundleName);
133 if (it == foregroundApps_.end()) {
134 AppEventRecord appEventRecord;
135 appEventRecord.rawid = FoldEventId::EVENT_APP_START;
136 appEventRecord.ts = static_cast<int64_t>(TimeUtil::GetBootTimeMs());
137 appEventRecord.bundleName = appData.bundleName;
138 int combineScreenStatus = GetCombineScreenStatus(foldStatus_, vhMode_);
139 appEventRecord.preFoldStatus = combineScreenStatus;
140 appEventRecord.foldStatus = combineScreenStatus;
141 appEventRecord.versionName = GetAppVersion(appData.bundleName);
142 appEventRecord.happenTime = static_cast<int64_t>(TimeUtil::GenerateTimestamp()) / MILLISEC_TO_MICROSEC;
143 if (combineScreenStatus != UNKNOWN_FOLD_STATUS) {
144 dbHelper_->AddAppEvent(appEventRecord);
145 }
146 }
147 }
148 timelyStart_ = bootTime;
149 }
150
ProcessEvent(std::shared_ptr<SysEvent> event)151 void FoldEventCacher::ProcessEvent(std::shared_ptr<SysEvent> event)
152 {
153 if (dbHelper_ == nullptr) {
154 HIVIEW_LOGI("dbHelper is nulptr");
155 return;
156 }
157 std::string bundleName = event->GetEventValue(AppEventSpace::KEY_OF_BUNDLE_NAME);
158 if (FoldAppUsageEventSpace::SCENEBOARD_BUNDLE_NAME == bundleName) {
159 return;
160 }
161 AppEventRecord appEventRecord;
162 std::string eventName = event->eventName_;
163 if (eventName == AppEventSpace::FOREGROUND_EVENT_NAME) {
164 ProcessForegroundEvent(event, appEventRecord);
165 } else if (eventName == AppEventSpace::BACKGROUND_EVENT_NAME) {
166 ProcessBackgroundEvent(event, appEventRecord);
167 CountLifeCycleDuration(appEventRecord);
168 } else if (eventName == FoldStateChangeEventSpace::EVENT_NAME || eventName == VhModeChangeEventSpace::EVENT_NAME) {
169 ProcessSceenStatusChangedEvent(event);
170 } else {
171 HIVIEW_LOGI("event can not process");
172 return;
173 }
174 }
175
ProcessForegroundEvent(std::shared_ptr<SysEvent> event,AppEventRecord & appEventRecord)176 void FoldEventCacher::ProcessForegroundEvent(std::shared_ptr<SysEvent> event, AppEventRecord& appEventRecord)
177 {
178 appEventRecord.rawid = FoldEventId::EVENT_APP_START;
179 appEventRecord.ts = static_cast<int64_t>(TimeUtil::GetBootTimeMs());
180 appEventRecord.bundleName = event->GetEventValue(AppEventSpace::KEY_OF_BUNDLE_NAME);
181 int combineScreenStatus = GetCombineScreenStatus(foldStatus_, vhMode_);
182 appEventRecord.preFoldStatus = combineScreenStatus;
183 appEventRecord.foldStatus = combineScreenStatus;
184 appEventRecord.versionName = event->GetEventValue(AppEventSpace::KEY_OF_VERSION_NAME);
185 appEventRecord.happenTime = static_cast<int64_t>(event->happenTime_);
186
187 if (combineScreenStatus != UNKNOWN_FOLD_STATUS) {
188 dbHelper_->AddAppEvent(appEventRecord);
189 }
190 if (foregroundApps_.size() >= MAX_FOREGROUND_APPS_SIZE) {
191 foregroundApps_.clear();
192 }
193 foregroundApps_[appEventRecord.bundleName] = appEventRecord.versionName;
194 }
195
ProcessBackgroundEvent(std::shared_ptr<SysEvent> event,AppEventRecord & appEventRecord)196 void FoldEventCacher::ProcessBackgroundEvent(std::shared_ptr<SysEvent> event, AppEventRecord& appEventRecord)
197 {
198 appEventRecord.rawid = FoldEventId::EVENT_APP_EXIT;
199 appEventRecord.ts = static_cast<int64_t>(TimeUtil::GetBootTimeMs());
200 appEventRecord.bundleName = event->GetEventValue(AppEventSpace::KEY_OF_BUNDLE_NAME);
201 int combineScreenStatus = GetCombineScreenStatus(foldStatus_, vhMode_);
202 appEventRecord.preFoldStatus = combineScreenStatus;
203 appEventRecord.foldStatus = combineScreenStatus;
204 appEventRecord.versionName = event->GetEventValue(AppEventSpace::KEY_OF_VERSION_NAME);
205 appEventRecord.happenTime = static_cast<int64_t>(event->happenTime_);
206
207 if (combineScreenStatus != UNKNOWN_FOLD_STATUS) {
208 dbHelper_->AddAppEvent(appEventRecord);
209 }
210 auto it = foregroundApps_.find(appEventRecord.bundleName);
211 if (it != foregroundApps_.end()) {
212 foregroundApps_.erase(it);
213 }
214 }
215
ProcessSceenStatusChangedEvent(std::shared_ptr<SysEvent> event)216 void FoldEventCacher::ProcessSceenStatusChangedEvent(std::shared_ptr<SysEvent> event)
217 {
218 int preFoldStatus = GetCombineScreenStatus(foldStatus_, vhMode_);
219 std::string eventName = event->eventName_;
220 if (eventName == FoldStateChangeEventSpace::EVENT_NAME) {
221 int nextFoldStatus = event->GetEventIntValue(FoldStateChangeEventSpace::KEY_OF_NEXT_STATUS);
222 UpdateFoldStatus(nextFoldStatus);
223 } else {
224 int nextMode = event->GetEventIntValue(VhModeChangeEventSpace::KEY_OF_MODE);
225 UpdateVhMode(nextMode);
226 }
227 for (auto it = foregroundApps_.begin(); it != foregroundApps_.end(); it++) {
228 AppEventRecord appEventRecord;
229 appEventRecord.rawid = FoldEventId::EVENT_SCREEN_STATUS_CHANGED;
230 appEventRecord.ts = static_cast<int64_t>(TimeUtil::GetBootTimeMs());
231 appEventRecord.bundleName = it->first;
232 appEventRecord.preFoldStatus = preFoldStatus;
233 appEventRecord.foldStatus = GetCombineScreenStatus(foldStatus_, vhMode_);
234 appEventRecord.versionName = it->second;
235 appEventRecord.happenTime = static_cast<int64_t>(event->happenTime_);
236 if ((appEventRecord.foldStatus != UNKNOWN_FOLD_STATUS)
237 && appEventRecord.preFoldStatus != appEventRecord.foldStatus) {
238 dbHelper_->AddAppEvent(appEventRecord);
239 }
240 }
241 }
242
GetFoldStatusDuration(const int foldStatus,std::map<int,uint64_t> & durations)243 int64_t FoldEventCacher::GetFoldStatusDuration(const int foldStatus, std::map<int, uint64_t>& durations)
244 {
245 auto it = durations.find(foldStatus);
246 if (it == durations.end()) {
247 return 0;
248 }
249 return static_cast<int64_t>(it->second);
250 }
251
ProcessCountDurationEvent(AppEventRecord & appEventRecord,std::map<int,uint64_t> & durations)252 void FoldEventCacher::ProcessCountDurationEvent(AppEventRecord& appEventRecord, std::map<int, uint64_t>& durations)
253 {
254 AppEventRecord newRecord;
255 newRecord.rawid = FoldEventId::EVENT_COUNT_DURATION;
256 newRecord.ts = static_cast<int64_t>(TimeUtil::GetBootTimeMs());
257 newRecord.bundleName = appEventRecord.bundleName;
258 newRecord.preFoldStatus = appEventRecord.preFoldStatus;
259 newRecord.foldStatus = appEventRecord.foldStatus;
260 newRecord.versionName = appEventRecord.versionName;
261 newRecord.happenTime = static_cast<int64_t>(TimeUtil::GenerateTimestamp()) / MILLISEC_TO_MICROSEC;
262 newRecord.foldPortraitTime = GetFoldStatusDuration(ScreenFoldStatus::FOLD_PORTRAIT_STATUS, durations);
263 newRecord.foldLandscapeTime = GetFoldStatusDuration(ScreenFoldStatus::FOLD_LANDSCAPE_STATUS, durations);
264 newRecord.expandPortraitTime = GetFoldStatusDuration(ScreenFoldStatus::EXPAND_PORTRAIT_STATUS, durations);
265 newRecord.expandLandscapeTime = GetFoldStatusDuration(ScreenFoldStatus::EXPAND_LANDSCAPE_STATUS, durations);
266 dbHelper_->AddAppEvent(newRecord);
267 }
268
CountLifeCycleDuration(AppEventRecord & appEventRecord)269 void FoldEventCacher::CountLifeCycleDuration(AppEventRecord& appEventRecord)
270 {
271 std::string bundleName = appEventRecord.bundleName;
272 int startIndex = GetStartIndex(bundleName);
273 int64_t dayStartTime = TimeUtil::Get0ClockStampMs();
274 std::vector<AppEventRecord> records;
275 dbHelper_->QueryAppEventRecords(startIndex, dayStartTime, bundleName, records);
276 std::map<int, uint64_t> durations;
277 CalCulateDuration(dayStartTime, records, durations);
278 ProcessCountDurationEvent(appEventRecord, durations);
279 }
280
CalCulateDuration(uint64_t dayStartTime,std::vector<AppEventRecord> & records,std::map<int,uint64_t> & durations)281 void FoldEventCacher::CalCulateDuration(uint64_t dayStartTime, std::vector<AppEventRecord>& records,
282 std::map<int, uint64_t>& durations)
283 {
284 if (records.empty()) {
285 return;
286 }
287 auto it = records.begin();
288 // app cross 0 clock
289 if (it->rawid == FoldEventId::EVENT_APP_EXIT || it->rawid == FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
290 int foldStatus = (it->rawid == FoldEventId::EVENT_APP_EXIT) ? it->foldStatus : it->preFoldStatus;
291 Accumulative(foldStatus, (it->happenTime - dayStartTime), durations);
292 }
293 auto preIt = it;
294 // app running from 0 clock to current time, calculate durations
295 it++;
296 for (; it != records.end(); it++) {
297 if (CanCalcDuration(preIt->rawid, it->rawid)) {
298 uint64_t duration = (it->ts > preIt->ts) ? static_cast<uint64_t>(it->ts - preIt->ts) : 0;
299 Accumulative(preIt->foldStatus, duration, durations);
300 }
301 preIt = it;
302 }
303 }
304
CanCalcDuration(uint32_t preId,uint32_t id)305 bool FoldEventCacher::CanCalcDuration(uint32_t preId, uint32_t id)
306 {
307 if (id == FoldEventId::EVENT_APP_EXIT && preId == FoldEventId::EVENT_APP_START) {
308 return true;
309 }
310 if (id == FoldEventId::EVENT_SCREEN_STATUS_CHANGED && preId == FoldEventId::EVENT_APP_START) {
311 return true;
312 }
313 if (id == FoldEventId::EVENT_SCREEN_STATUS_CHANGED && preId == FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
314 return true;
315 }
316 if (id == FoldEventId::EVENT_APP_EXIT && preId == FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
317 return true;
318 }
319 return false;
320 }
321
Accumulative(int foldStatus,uint64_t duration,std::map<int,uint64_t> & durations)322 void FoldEventCacher::Accumulative(int foldStatus, uint64_t duration, std::map<int, uint64_t>& durations)
323 {
324 if (durations.find(foldStatus) == durations.end()) {
325 durations[foldStatus] = duration;
326 } else {
327 durations[foldStatus] += duration;
328 }
329 }
330
GetStartIndex(const std::string & bundleName)331 int FoldEventCacher::GetStartIndex(const std::string& bundleName)
332 {
333 return dbHelper_->QueryRawEventIndex(bundleName, FoldEventId::EVENT_APP_START);
334 }
335
UpdateFoldStatus(int status)336 void FoldEventCacher::UpdateFoldStatus(int status)
337 {
338 foldStatus_ = status;
339 }
340
UpdateVhMode(int mode)341 void FoldEventCacher::UpdateVhMode(int mode)
342 {
343 vhMode_ = mode;
344 }
345
346 } // namespace HiviewDFX
347 } // namespace OHOS
348