1 /*
2 * Copyright (c) 2024-2025 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_app_usage_db_helper.h"
17
18 #include "event_db_helper.h"
19 #include "file_util.h"
20 #include "hiview_logger.h"
21 #include "rdb_helper.h"
22 #include "rdb_predicates.h"
23 #include "sql_util.h"
24 #include "usage_event_common.h"
25
26 namespace OHOS {
27 namespace HiviewDFX {
28 DEFINE_LOG_TAG("FoldAppUsageHelper");
29 namespace {
30 const std::string LOG_DB_PATH = "sys_event_logger/";
31 const std::string LOG_DB_NAME = "log.db";
32 const std::string LOG_DB_TABLE_NAME = "app_events";
33 constexpr int DB_VERSION = 1;
34
35 const std::string SQL_TYPE_INTEGER_NOT_NULL = "INTEGER NOT NULL";
36 const std::string SQL_TYPE_INTEGER = "INTEGER";
37 const std::string SQL_TYPE_REAL = "REAL";
38 const std::string SQL_TYPE_TEXT_NOT_NULL = "TEXT NOT NULL";
39 const std::string SQL_TYPE_TEXT = "TEXT";
40
41 constexpr int DB_SUCC = 0;
42 constexpr int DB_FAILED = -1;
43
UpdateScreenStatInfo(FoldAppUsageInfo & info,uint32_t time,int screenStatus)44 void UpdateScreenStatInfo(FoldAppUsageInfo &info, uint32_t time, int screenStatus)
45 {
46 switch (screenStatus) {
47 case ScreenFoldStatus::EXPAND_PORTRAIT_STATUS:
48 info.expdHor += static_cast<int32_t>(time);
49 break;
50 case ScreenFoldStatus::EXPAND_LANDSCAPE_STATUS:
51 info.expdVer += static_cast<int32_t>(time);
52 break;
53 case ScreenFoldStatus::FOLD_PORTRAIT_STATUS:
54 info.foldHor += static_cast<int32_t>(time);
55 break;
56 case ScreenFoldStatus::FOLD_LANDSCAPE_STATUS:
57 info.foldVer += static_cast<int32_t>(time);
58 break;
59 default:
60 return;
61 }
62 }
63
GetStringFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,std::string & value)64 bool GetStringFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
65 const std::string& colName, std::string &value)
66 {
67 int colIndex = 0;
68 if (resultSet->GetColumnIndex(colName, colIndex) != NativeRdb::E_OK) {
69 HIVIEW_LOGE("failed to get column index, column = %{public}s", colName.c_str());
70 return false;
71 }
72 if (resultSet->GetString(colIndex, value) != NativeRdb::E_OK) {
73 HIVIEW_LOGE("failed to get string value, column = %{public}s", colName.c_str());
74 return false;
75 }
76 return true;
77 }
78
GetIntFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,int & value)79 bool GetIntFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
80 const std::string& colName, int &value)
81 {
82 int colIndex = 0;
83 if (resultSet->GetColumnIndex(colName, colIndex) != NativeRdb::E_OK) {
84 HIVIEW_LOGE("failed to get column index, column = %{public}s", colName.c_str());
85 return false;
86 }
87 if (resultSet->GetInt(colIndex, value) != NativeRdb::E_OK) {
88 HIVIEW_LOGE("failed to get int value, column = %{public}s", colName.c_str());
89 return false;
90 }
91 return true;
92 }
93
GetLongFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,int64_t & value)94 bool GetLongFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
95 const std::string& colName, int64_t &value)
96 {
97 int colIndex = 0;
98 if (resultSet->GetColumnIndex(colName, colIndex) != NativeRdb::E_OK) {
99 HIVIEW_LOGE("failed to get column index, column = %{public}s", colName.c_str());
100 return false;
101 }
102 if (resultSet->GetLong(colIndex, value) != NativeRdb::E_OK) {
103 HIVIEW_LOGE("failed to get long value, column = %{public}s", colName.c_str());
104 return false;
105 }
106 return true;
107 }
108 }
109
110 class FoldDbStoreCallback : public NativeRdb::RdbOpenCallback {
111 public:
112 int OnCreate(NativeRdb::RdbStore& rdbStore) override;
113 int OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion) override;
114 };
115
OnCreate(NativeRdb::RdbStore & rdbStore)116 int FoldDbStoreCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
117 {
118 HIVIEW_LOGD("create dbStore");
119 return NativeRdb::E_OK;
120 }
121
OnUpgrade(NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)122 int FoldDbStoreCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion)
123 {
124 HIVIEW_LOGD("oldVersion = %{public}d, newVersion = %{public}d", oldVersion, newVersion);
125 return NativeRdb::E_OK;
126 }
127
FoldAppUsageDbHelper(const std::string & workPath)128 FoldAppUsageDbHelper::FoldAppUsageDbHelper(const std::string& workPath)
129 {
130 dbPath_ = workPath;
131 if (workPath.back() != '/') {
132 dbPath_ = workPath + "/";
133 }
134 dbPath_ += LOG_DB_PATH;
135 CreateDbStore(dbPath_, LOG_DB_NAME);
136 if (int ret = CreateAppEventsTable(LOG_DB_TABLE_NAME); ret != DB_SUCC) {
137 HIVIEW_LOGI("failed to create table");
138 }
139 }
140
~FoldAppUsageDbHelper()141 FoldAppUsageDbHelper::~FoldAppUsageDbHelper()
142 {}
143
CreateDbStore(const std::string & dbPath,const std::string & dbName)144 void FoldAppUsageDbHelper::CreateDbStore(const std::string& dbPath, const std::string& dbName)
145 {
146 std::string dbFile = dbPath + dbName;
147 if (!FileUtil::FileExists(dbPath) && FileUtil::ForceCreateDirectory(dbPath, FileUtil::FILE_PERM_770)) {
148 HIVIEW_LOGI("failed to create db path, use default path");
149 return;
150 }
151 NativeRdb::RdbStoreConfig config(dbFile);
152 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
153 FoldDbStoreCallback callback;
154 int ret = NativeRdb::E_OK;
155 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, DB_VERSION, callback, ret);
156 if (ret != NativeRdb::E_OK || rdbStore_ == nullptr) {
157 HIVIEW_LOGI("failed to create db store, dbFile = %{public}s, ret = %{public}d", dbFile.c_str(), ret);
158 }
159 }
160
CreateAppEventsTable(const std::string & table)161 int FoldAppUsageDbHelper::CreateAppEventsTable(const std::string& table)
162 {
163 std::lock_guard<std::mutex> lockGuard(dbMutex_);
164 if (rdbStore_ == nullptr) {
165 HIVIEW_LOGI("dbstore is nullptr");
166 return DB_FAILED;
167 }
168 std::vector<std::pair<std::string, std::string>> fields = {
169 {FoldEventTable::FIELD_UID, SQL_TYPE_INTEGER_NOT_NULL},
170 {FoldEventTable::FIELD_EVENT_ID, SQL_TYPE_INTEGER_NOT_NULL},
171 {FoldEventTable::FIELD_TS, SQL_TYPE_INTEGER_NOT_NULL},
172 {FoldEventTable::FIELD_FOLD_STATUS, SQL_TYPE_INTEGER},
173 {FoldEventTable::FIELD_PRE_FOLD_STATUS, SQL_TYPE_INTEGER},
174 {FoldEventTable::FIELD_VERSION_NAME, SQL_TYPE_TEXT},
175 {FoldEventTable::FIELD_HAPPEN_TIME, SQL_TYPE_INTEGER},
176 {FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION, SQL_TYPE_INTEGER},
177 {FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION, SQL_TYPE_INTEGER},
178 {FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION, SQL_TYPE_INTEGER},
179 {FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION, SQL_TYPE_INTEGER},
180 {FoldEventTable::FIELD_BUNDLE_NAME, SQL_TYPE_TEXT_NOT_NULL}
181 };
182 std::string sql = SqlUtil::GenerateCreateSql(table, fields);
183 if (rdbStore_->ExecuteSql(sql) != NativeRdb::E_OK) {
184 return DB_FAILED;
185 }
186 return DB_SUCC;
187 }
188
AddAppEvent(const AppEventRecord & appEventRecord)189 int FoldAppUsageDbHelper::AddAppEvent(const AppEventRecord& appEventRecord)
190 {
191 std::lock_guard<std::mutex> lockGuard(dbMutex_);
192 if (rdbStore_ == nullptr) {
193 HIVIEW_LOGE("dbStore is nullptr");
194 return DB_FAILED;
195 }
196 NativeRdb::ValuesBucket valuesBucket;
197 valuesBucket.PutInt(FoldEventTable::FIELD_UID, -1);
198 valuesBucket.PutInt(FoldEventTable::FIELD_EVENT_ID, appEventRecord.rawid);
199 valuesBucket.PutLong(FoldEventTable::FIELD_TS, appEventRecord.ts);
200 valuesBucket.PutInt(FoldEventTable::FIELD_FOLD_STATUS, appEventRecord.foldStatus);
201 valuesBucket.PutInt(FoldEventTable::FIELD_PRE_FOLD_STATUS, appEventRecord.preFoldStatus);
202 valuesBucket.PutString(FoldEventTable::FIELD_VERSION_NAME, appEventRecord.versionName);
203 valuesBucket.PutLong(FoldEventTable::FIELD_HAPPEN_TIME, appEventRecord.happenTime);
204 valuesBucket.PutLong(FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION, appEventRecord.foldPortraitTime);
205 valuesBucket.PutLong(FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION, appEventRecord.foldLandscapeTime);
206 valuesBucket.PutLong(FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION, appEventRecord.expandPortraitTime);
207 valuesBucket.PutLong(FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION, appEventRecord.expandLandscapeTime);
208 valuesBucket.PutString(FoldEventTable::FIELD_BUNDLE_NAME, appEventRecord.bundleName);
209 int64_t seq = 0;
210 if (int ret = rdbStore_->Insert(seq, LOG_DB_TABLE_NAME, valuesBucket); ret != NativeRdb::E_OK) {
211 HIVIEW_LOGI("failed to add app event");
212 return DB_FAILED;
213 }
214 return DB_SUCC;
215 }
216
QueryRawEventIndex(const std::string & bundleName,int rawId)217 int FoldAppUsageDbHelper::QueryRawEventIndex(const std::string& bundleName, int rawId)
218 {
219 std::lock_guard<std::mutex> lockGuard(dbMutex_);
220 if (rdbStore_ == nullptr) {
221 HIVIEW_LOGE("dbStore is nullptr");
222 return 0;
223 }
224 NativeRdb::RdbPredicates predicates(LOG_DB_TABLE_NAME);
225 predicates.EqualTo(FoldEventTable::FIELD_BUNDLE_NAME, bundleName);
226 predicates.EqualTo(FoldEventTable::FIELD_EVENT_ID, rawId);
227 predicates.OrderByDesc(FoldEventTable::FIELD_ID);
228 predicates.Limit(1); // query the nearest one event
229 auto resultSet = rdbStore_->Query(predicates, {FoldEventTable::FIELD_ID});
230 int index = 0;
231 if (resultSet == nullptr) {
232 HIVIEW_LOGI("failed to query raw event index");
233 return index;
234 }
235 if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
236 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_ID, index);
237 }
238 resultSet->Close();
239 return index;
240 }
241
QueryAppEventRecords(int startIndex,int64_t dayStartTime,const std::string & bundleName,std::vector<AppEventRecord> & records)242 void FoldAppUsageDbHelper::QueryAppEventRecords(int startIndex, int64_t dayStartTime, const std::string& bundleName,
243 std::vector<AppEventRecord>& records)
244 {
245 std::lock_guard<std::mutex> lockGuard(dbMutex_);
246 if (rdbStore_ == nullptr) {
247 HIVIEW_LOGE("dbStore is nullptr");
248 return;
249 }
250 NativeRdb::RdbPredicates predicates(LOG_DB_TABLE_NAME);
251 predicates.EqualTo(FoldEventTable::FIELD_BUNDLE_NAME, bundleName);
252 predicates.GreaterThanOrEqualTo(FoldEventTable::FIELD_ID, startIndex);
253 predicates.GreaterThanOrEqualTo(FoldEventTable::FIELD_HAPPEN_TIME, dayStartTime);
254 predicates.OrderByAsc(FoldEventTable::FIELD_ID);
255
256 std::vector<std::string> columns;
257 columns.emplace_back(FoldEventTable::FIELD_EVENT_ID);
258 columns.emplace_back(FoldEventTable::FIELD_TS);
259 columns.emplace_back(FoldEventTable::FIELD_FOLD_STATUS);
260 columns.emplace_back(FoldEventTable::FIELD_PRE_FOLD_STATUS);
261 columns.emplace_back(FoldEventTable::FIELD_VERSION_NAME);
262 columns.emplace_back(FoldEventTable::FIELD_HAPPEN_TIME);
263 columns.emplace_back(FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION);
264 columns.emplace_back(FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION);
265 columns.emplace_back(FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION);
266 columns.emplace_back(FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION);
267 columns.emplace_back(FoldEventTable::FIELD_BUNDLE_NAME);
268 auto resultSet = rdbStore_->Query(predicates, columns);
269 if (resultSet == nullptr) {
270 HIVIEW_LOGI("failed to query event event");
271 return;
272 }
273 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
274 NativeRdb::RowEntity entity;
275 if (resultSet->GetRow(entity) != NativeRdb::E_OK) {
276 HIVIEW_LOGI("failed to read row entity from result set");
277 resultSet->Close();
278 return;
279 }
280 AppEventRecord record;
281 ParseEntity(entity, record);
282 if (record.rawid == FoldEventId::EVENT_COUNT_DURATION) {
283 records.clear();
284 continue;
285 }
286 records.emplace_back(record);
287 }
288 resultSet->Close();
289 }
290
ParseEntity(NativeRdb::RowEntity & entity,AppEventRecord & record)291 void FoldAppUsageDbHelper::ParseEntity(NativeRdb::RowEntity& entity, AppEventRecord& record)
292 {
293 entity.Get(FoldEventTable::FIELD_EVENT_ID).GetInt(record.rawid);
294 entity.Get(FoldEventTable::FIELD_TS).GetLong(record.ts);
295 entity.Get(FoldEventTable::FIELD_FOLD_STATUS).GetInt(record.foldStatus);
296 entity.Get(FoldEventTable::FIELD_PRE_FOLD_STATUS).GetInt(record.preFoldStatus);
297 entity.Get(FoldEventTable::FIELD_VERSION_NAME).GetString(record.versionName);
298 entity.Get(FoldEventTable::FIELD_HAPPEN_TIME).GetLong(record.happenTime);
299 entity.Get(FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION).GetLong(record.foldPortraitTime);
300 entity.Get(FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION).GetLong(record.foldLandscapeTime);
301 entity.Get(FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION).GetLong(record.expandPortraitTime);
302 entity.Get(FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION).GetLong(record.expandLandscapeTime);
303 entity.Get(FoldEventTable::FIELD_BUNDLE_NAME).GetString(record.bundleName);
304 }
305
QueryFinalScreenStatus(uint64_t endTime)306 int FoldAppUsageDbHelper::QueryFinalScreenStatus(uint64_t endTime)
307 {
308 std::lock_guard<std::mutex> lockGuard(dbMutex_);
309 if (rdbStore_ == nullptr) {
310 HIVIEW_LOGE("db is nullptr");
311 return 0;
312 }
313 NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
314 predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, 0, static_cast<int64_t>(endTime));
315 predicates.OrderByDesc(FoldEventTable::FIELD_ID);
316 predicates.Limit(1);
317 auto resultSet = rdbStore_->Query(predicates, {FoldEventTable::FIELD_ID, FoldEventTable::FIELD_FOLD_STATUS});
318 if (resultSet == nullptr) {
319 HIVIEW_LOGE("resultSet is nullptr");
320 return 0;
321 }
322 int id = 0;
323 int status = 0;
324 if (resultSet->GoToNextRow() == NativeRdb::E_OK &&
325 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_ID, id) &&
326 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_STATUS, status) == NativeRdb::E_OK) {
327 HIVIEW_LOGI("get handle seq: %{public}d, screen stat: %{public}d", id, status);
328 } else {
329 HIVIEW_LOGE("get handle seq and screen stat failed");
330 }
331 resultSet->Close();
332 return status;
333 }
334
QueryStatisticEventsInPeriod(uint64_t startTime,uint64_t endTime,std::unordered_map<std::string,FoldAppUsageInfo> & infos)335 void FoldAppUsageDbHelper::QueryStatisticEventsInPeriod(uint64_t startTime, uint64_t endTime,
336 std::unordered_map<std::string, FoldAppUsageInfo> &infos)
337 {
338 std::lock_guard<std::mutex> lockGuard(dbMutex_);
339 if (rdbStore_ == nullptr) {
340 HIVIEW_LOGE("db is nullptr");
341 return;
342 }
343 std::string sqlCmd = "SELECT " + FoldEventTable::FIELD_BUNDLE_NAME + ", " + FoldEventTable::FIELD_VERSION_NAME +
344 ", SUM(" + FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION + ") AS " +
345 FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION +
346 ", SUM(" + FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION + ") AS " +
347 FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION +
348 ", SUM(" + FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION + ") AS " +
349 FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION +
350 ", SUM(" + FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION + ") AS " +
351 FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION +
352 ", COUNT(*) AS start_num FROM " + LOG_DB_TABLE_NAME + " WHERE " + FoldEventTable::FIELD_EVENT_ID + "=" +
353 std::to_string(FoldEventId::EVENT_COUNT_DURATION) + " AND " + FoldEventTable::FIELD_HAPPEN_TIME + " BETWEEN " +
354 std::to_string(startTime) + " AND " + std::to_string(endTime) +
355 " GROUP BY " + FoldEventTable::FIELD_BUNDLE_NAME + ", " + FoldEventTable::FIELD_VERSION_NAME;
356 auto resultSet = rdbStore_->QuerySql(sqlCmd);
357 if (resultSet == nullptr) {
358 HIVIEW_LOGE("resultSet is nullptr");
359 return;
360 }
361 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
362 FoldAppUsageInfo usageInfo;
363 if (GetStringFromResultSet(resultSet, FoldEventTable::FIELD_BUNDLE_NAME, usageInfo.package) &&
364 GetStringFromResultSet(resultSet, FoldEventTable::FIELD_VERSION_NAME, usageInfo.version) &&
365 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION, usageInfo.foldVer) &&
366 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION, usageInfo.foldHor) &&
367 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION, usageInfo.expdVer) &&
368 GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION, usageInfo.expdHor) &&
369 GetIntFromResultSet(resultSet, "start_num", usageInfo.startNum)) {
370 infos[usageInfo.package + usageInfo.version] = usageInfo;
371 } else {
372 HIVIEW_LOGE("fail to get appusage info!");
373 }
374 }
375 resultSet->Close();
376 }
377
QueryForegroundAppsInfo(uint64_t startTime,uint64_t endTime,int screenStatus,FoldAppUsageInfo & info)378 void FoldAppUsageDbHelper::QueryForegroundAppsInfo(uint64_t startTime, uint64_t endTime, int screenStatus,
379 FoldAppUsageInfo &info)
380 {
381 std::lock_guard<std::mutex> lockGuard(dbMutex_);
382 if (rdbStore_ == nullptr) {
383 HIVIEW_LOGE("db is nullptr");
384 return;
385 }
386 NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
387 predicates.EqualTo(FoldEventTable::FIELD_BUNDLE_NAME, info.package);
388 predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, static_cast<int64_t>(startTime),
389 static_cast<int64_t>(endTime));
390 predicates.OrderByDesc(FoldEventTable::FIELD_ID);
391 auto resultSet = rdbStore_->Query(predicates, {FoldEventTable::FIELD_ID, FoldEventTable::FIELD_EVENT_ID,
392 FoldEventTable::FIELD_BUNDLE_NAME, FoldEventTable::FIELD_VERSION_NAME, FoldEventTable::FIELD_HAPPEN_TIME,
393 FoldEventTable::FIELD_FOLD_STATUS, FoldEventTable::FIELD_PRE_FOLD_STATUS, FoldEventTable::FIELD_TS});
394 if (resultSet == nullptr) {
395 HIVIEW_LOGE("resultSet is nullptr");
396 return;
397 }
398 std::vector<FoldAppUsageRawEvent> events;
399 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
400 FoldAppUsageRawEvent event;
401 if (!GetLongFromResultSet(resultSet, FoldEventTable::FIELD_ID, event.id) ||
402 !GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EVENT_ID, event.rawId) ||
403 !GetStringFromResultSet(resultSet, FoldEventTable::FIELD_BUNDLE_NAME, event.package) ||
404 !GetStringFromResultSet(resultSet, FoldEventTable::FIELD_VERSION_NAME, event.version) ||
405 !GetLongFromResultSet(resultSet, FoldEventTable::FIELD_HAPPEN_TIME, event.happenTime) ||
406 !GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_STATUS, event.screenStatusAfter) ||
407 !GetIntFromResultSet(resultSet, FoldEventTable::FIELD_PRE_FOLD_STATUS, event.screenStatusBefore) ||
408 !GetLongFromResultSet(resultSet, FoldEventTable::FIELD_TS, event.ts)) {
409 HIVIEW_LOGE("fail to get db event!");
410 resultSet->Close();
411 return;
412 }
413 if (event.rawId != FoldEventId::EVENT_APP_START && event.rawId != FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
414 HIVIEW_LOGE("can not find foreground event, latest raw id: %{public}d", event.rawId);
415 resultSet->Close();
416 return;
417 }
418 events.emplace_back(event);
419 if (event.rawId == FoldEventId::EVENT_APP_START) {
420 break;
421 }
422 }
423 info = CaculateForegroundAppUsage(events, startTime, endTime, info.package, screenStatus);
424 resultSet->Close();
425 }
426
DeleteEventsByTime(uint64_t clearDataTime)427 int FoldAppUsageDbHelper::DeleteEventsByTime(uint64_t clearDataTime)
428 {
429 std::lock_guard<std::mutex> lockGuard(dbMutex_);
430 if (rdbStore_ == nullptr) {
431 HIVIEW_LOGE("db is nullptr");
432 return 0;
433 }
434 NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
435 predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, 0, static_cast<int64_t>(clearDataTime));
436 int seq = 0;
437 int ret = rdbStore_->Delete(seq, predicates);
438 HIVIEW_LOGI("rows are deleted: %{public}d, ret: %{public}d", seq, ret);
439 return seq;
440 }
441
CaculateForegroundAppUsage(const std::vector<FoldAppUsageRawEvent> & events,uint64_t startTime,uint64_t endTime,const std::string & appName,int screenStatus)442 FoldAppUsageInfo FoldAppUsageDbHelper::CaculateForegroundAppUsage(const std::vector<FoldAppUsageRawEvent> &events,
443 uint64_t startTime, uint64_t endTime, const std::string &appName, int screenStatus)
444 {
445 FoldAppUsageInfo info;
446 info.package = appName;
447 // no event means: app is foreground for whole day.
448 if (events.size() == 0) {
449 UpdateScreenStatInfo(info, static_cast<uint32_t>(endTime - startTime), screenStatus);
450 return info;
451 }
452 uint32_t size = events.size();
453 // first event is screen changed, means app is started befor statistic period.
454 if (events[size - 1].rawId == FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
455 UpdateScreenStatInfo(info, static_cast<uint32_t>(events[size - 1].happenTime - startTime),
456 events[size - 1].screenStatusBefore);
457 }
458 // caculate all period between screen status changed events, till endTime.
459 for (uint32_t i = size - 1; i > 0; --i) {
460 if (events[i - 1].ts > events[i].ts) {
461 UpdateScreenStatInfo(info, static_cast<uint32_t>(events[i - 1].ts - events[i].ts),
462 events[i].screenStatusAfter);
463 }
464 }
465 UpdateScreenStatInfo(info, static_cast<uint32_t>(endTime - events[0].happenTime), events[0].screenStatusAfter);
466 return info;
467 }
468
QueryEventAfterEndTime(uint64_t endTime,uint64_t nowTime)469 std::vector<std::pair<int, std::string>> FoldAppUsageDbHelper::QueryEventAfterEndTime(
470 uint64_t endTime, uint64_t nowTime)
471 {
472 std::vector<std::pair<int, std::string>> retEvents = {};
473 std::lock_guard<std::mutex> lockGuard(dbMutex_);
474 if (rdbStore_ == nullptr) {
475 HIVIEW_LOGE("db is nullptr");
476 return retEvents;
477 }
478 NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
479 predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, static_cast<int64_t>(endTime),
480 static_cast<int64_t>(nowTime))->BeginWrap()->
481 EqualTo(FoldEventTable::FIELD_EVENT_ID, FoldEventId::EVENT_APP_START)->Or()->
482 EqualTo(FoldEventTable::FIELD_EVENT_ID, FoldEventId::EVENT_APP_EXIT)->EndWrap();
483 predicates.OrderByDesc(FoldEventTable::FIELD_ID);
484 auto resultSet = rdbStore_->Query(predicates, { FoldEventTable::FIELD_EVENT_ID,
485 FoldEventTable::FIELD_BUNDLE_NAME});
486 if (resultSet == nullptr) {
487 HIVIEW_LOGE("resultSet is nullptr");
488 return retEvents;
489 }
490 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
491 std::pair<int, std::string> appSwitchEvent;
492 if (!GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EVENT_ID, appSwitchEvent.first) ||
493 !GetStringFromResultSet(resultSet, FoldEventTable::FIELD_BUNDLE_NAME, appSwitchEvent.second)) {
494 continue;
495 }
496 retEvents.emplace_back(appSwitchEvent);
497 }
498 resultSet->Close();
499 return retEvents;
500 }
501 } // namespace HiviewDFX
502 } // namespace OHOS