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_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("FoldAppUsage");
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     return status;
332 }
333 
QueryStatisticEventsInPeriod(uint64_t startTime,uint64_t endTime,std::unordered_map<std::string,FoldAppUsageInfo> & infos)334 void FoldAppUsageDbHelper::QueryStatisticEventsInPeriod(uint64_t startTime, uint64_t endTime,
335     std::unordered_map<std::string, FoldAppUsageInfo> &infos)
336 {
337     std::lock_guard<std::mutex> lockGuard(dbMutex_);
338     if (rdbStore_ == nullptr) {
339         HIVIEW_LOGE("db is nullptr");
340         return;
341     }
342     std::string sqlCmd = "SELECT " + FoldEventTable::FIELD_BUNDLE_NAME + ", " + FoldEventTable::FIELD_VERSION_NAME +
343         ", SUM(" + FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION + ") AS " +
344         FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION +
345         ", SUM(" + FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION + ") AS " +
346         FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION +
347         ", SUM(" + FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION + ") AS " +
348         FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION +
349         ", SUM(" + FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION + ") AS " +
350         FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION +
351         ", COUNT(*) AS start_num FROM " + LOG_DB_TABLE_NAME + " WHERE " + FoldEventTable::FIELD_EVENT_ID + "=" +
352         std::to_string(FoldEventId::EVENT_COUNT_DURATION) + " AND " + FoldEventTable::FIELD_HAPPEN_TIME + " BETWEEN " +
353         std::to_string(startTime) + " AND " + std::to_string(endTime) +
354         " GROUP BY " + FoldEventTable::FIELD_BUNDLE_NAME + ", " + FoldEventTable::FIELD_VERSION_NAME;
355     auto resultSet = rdbStore_->QuerySql(sqlCmd);
356     if (resultSet == nullptr) {
357         HIVIEW_LOGE("resultSet is nullptr");
358         return;
359     }
360     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
361         FoldAppUsageInfo usageInfo;
362         if (GetStringFromResultSet(resultSet, FoldEventTable::FIELD_BUNDLE_NAME, usageInfo.package) &&
363             GetStringFromResultSet(resultSet, FoldEventTable::FIELD_VERSION_NAME, usageInfo.version) &&
364             GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_PORTRAIT_DURATION, usageInfo.foldVer) &&
365             GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_LANDSCAPE_DURATION, usageInfo.foldHor) &&
366             GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EXPAND_PORTRAIT_DURATION, usageInfo.expdVer) &&
367             GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EXPAND_LANDSCAPE_DURATION, usageInfo.expdHor) &&
368             GetIntFromResultSet(resultSet, "start_num", usageInfo.startNum)) {
369             infos[usageInfo.package + usageInfo.version] = usageInfo;
370         } else {
371             HIVIEW_LOGE("fail to get appusage info!");
372         }
373     }
374 }
375 
QueryForegroundAppsInfo(uint64_t startTime,uint64_t endTime,int screenStatus,FoldAppUsageInfo & info)376 void FoldAppUsageDbHelper::QueryForegroundAppsInfo(uint64_t startTime, uint64_t endTime, int screenStatus,
377     FoldAppUsageInfo &info)
378 {
379     std::lock_guard<std::mutex> lockGuard(dbMutex_);
380     if (rdbStore_ == nullptr) {
381         HIVIEW_LOGE("db is nullptr");
382         return;
383     }
384     NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
385     predicates.EqualTo(FoldEventTable::FIELD_BUNDLE_NAME, info.package);
386     predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, static_cast<int64_t>(startTime),
387         static_cast<int64_t>(endTime));
388     predicates.OrderByDesc(FoldEventTable::FIELD_ID);
389     auto resultSet = rdbStore_->Query(predicates, {FoldEventTable::FIELD_ID, FoldEventTable::FIELD_EVENT_ID,
390         FoldEventTable::FIELD_BUNDLE_NAME, FoldEventTable::FIELD_VERSION_NAME, FoldEventTable::FIELD_HAPPEN_TIME,
391         FoldEventTable::FIELD_FOLD_STATUS, FoldEventTable::FIELD_PRE_FOLD_STATUS, FoldEventTable::FIELD_TS});
392     if (resultSet == nullptr) {
393         HIVIEW_LOGE("resultSet is nullptr");
394         return;
395     }
396     std::vector<FoldAppUsageRawEvent> events;
397     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
398         FoldAppUsageRawEvent event;
399         if (!GetLongFromResultSet(resultSet, FoldEventTable::FIELD_ID, event.id) ||
400             !GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EVENT_ID, event.rawId) ||
401             !GetStringFromResultSet(resultSet, FoldEventTable::FIELD_BUNDLE_NAME, event.package) ||
402             !GetStringFromResultSet(resultSet, FoldEventTable::FIELD_VERSION_NAME, event.version) ||
403             !GetLongFromResultSet(resultSet, FoldEventTable::FIELD_HAPPEN_TIME, event.happenTime) ||
404             !GetIntFromResultSet(resultSet, FoldEventTable::FIELD_FOLD_STATUS, event.screenStatusAfter) ||
405             !GetIntFromResultSet(resultSet, FoldEventTable::FIELD_PRE_FOLD_STATUS, event.screenStatusBefore) ||
406             !GetLongFromResultSet(resultSet, FoldEventTable::FIELD_TS, event.ts)) {
407             HIVIEW_LOGE("fail to get db event!");
408             return;
409         }
410         if (event.rawId != FoldEventId::EVENT_APP_START && event.rawId != FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
411             HIVIEW_LOGE("can not find foreground event, latest raw id: %{public}d", event.rawId);
412             return;
413         }
414         events.emplace_back(event);
415         if (event.rawId == FoldEventId::EVENT_APP_START) {
416             break;
417         }
418     }
419     info = CaculateForegroundAppUsage(events, startTime, endTime, info.package, screenStatus);
420 }
421 
DeleteEventsByTime(uint64_t clearDataTime)422 int FoldAppUsageDbHelper::DeleteEventsByTime(uint64_t clearDataTime)
423 {
424     std::lock_guard<std::mutex> lockGuard(dbMutex_);
425     if (rdbStore_ == nullptr) {
426         HIVIEW_LOGE("db is nullptr");
427         return 0;
428     }
429     NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
430     predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, 0, static_cast<int64_t>(clearDataTime));
431     int seq = 0;
432     int ret = rdbStore_->Delete(seq, predicates);
433     HIVIEW_LOGI("rows are deleted: %{public}d, ret: %{public}d", seq, ret);
434     return seq;
435 }
436 
CaculateForegroundAppUsage(const std::vector<FoldAppUsageRawEvent> & events,uint64_t startTime,uint64_t endTime,const std::string & appName,int screenStatus)437 FoldAppUsageInfo FoldAppUsageDbHelper::CaculateForegroundAppUsage(const std::vector<FoldAppUsageRawEvent> &events,
438     uint64_t startTime, uint64_t endTime, const std::string &appName, int screenStatus)
439 {
440     FoldAppUsageInfo info;
441     info.package = appName;
442     // no event means: app is foreground for whole day.
443     if (events.size() == 0) {
444         UpdateScreenStatInfo(info, static_cast<uint32_t>(endTime - startTime), screenStatus);
445         return info;
446     }
447     uint32_t size = events.size();
448     // first event is screen changed, means app is started befor statistic period.
449     if (events[size - 1].rawId == FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
450         UpdateScreenStatInfo(info, static_cast<uint32_t>(events[size - 1].happenTime - startTime),
451             events[size - 1].screenStatusBefore);
452     }
453     // caculate all period between screen status changed events, till endTime.
454     for (uint32_t i = size - 1; i > 0; --i) {
455         if (events[i - 1].ts > events[i].ts) {
456             UpdateScreenStatInfo(info, static_cast<uint32_t>(events[i - 1].ts - events[i].ts),
457                 events[i].screenStatusAfter);
458         }
459     }
460     UpdateScreenStatInfo(info, static_cast<uint32_t>(endTime - events[0].happenTime), events[0].screenStatusAfter);
461     return info;
462 }
463 
QueryEventAfterEndTime(uint64_t endTime,uint64_t nowTime)464 std::vector<std::pair<int, std::string>> FoldAppUsageDbHelper::QueryEventAfterEndTime(
465     uint64_t endTime, uint64_t nowTime)
466 {
467     std::vector<std::pair<int, std::string>> retEvents = {};
468     std::lock_guard<std::mutex> lockGuard(dbMutex_);
469     if (rdbStore_ == nullptr) {
470         HIVIEW_LOGE("db is nullptr");
471         return retEvents;
472     }
473     NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
474     predicates.Between(FoldEventTable::FIELD_HAPPEN_TIME, static_cast<int64_t>(endTime),
475         static_cast<int64_t>(nowTime))->BeginWrap()->
476         EqualTo(FoldEventTable::FIELD_EVENT_ID, FoldEventId::EVENT_APP_START)->Or()->
477         EqualTo(FoldEventTable::FIELD_EVENT_ID, FoldEventId::EVENT_APP_EXIT)->EndWrap();
478     predicates.OrderByDesc(FoldEventTable::FIELD_ID);
479     auto resultSet = rdbStore_->Query(predicates, { FoldEventTable::FIELD_EVENT_ID,
480         FoldEventTable::FIELD_BUNDLE_NAME});
481     if (resultSet == nullptr) {
482         HIVIEW_LOGE("resultSet is nullptr");
483         return retEvents;
484     }
485     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
486         std::pair<int, std::string> appSwitchEvent;
487         if (!GetIntFromResultSet(resultSet, FoldEventTable::FIELD_EVENT_ID, appSwitchEvent.first) ||
488             !GetStringFromResultSet(resultSet, FoldEventTable::FIELD_BUNDLE_NAME, appSwitchEvent.second)) {
489             continue;
490         }
491         retEvents.emplace_back(appSwitchEvent);
492     }
493     return retEvents;
494 }
495 } // namespace HiviewDFX
496 } // namespace OHOS