• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 using namespace OHOS::HiviewDFX::FoldEventTable;
27 using namespace OHOS::HiviewDFX::ScreenFoldStatus;
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 DEFINE_LOG_TAG("FoldAppUsageHelper");
32 namespace {
33 constexpr char LOG_DB_PATH[] = "sys_event_logger/";
34 constexpr char LOG_DB_NAME[] = "log.db";
35 constexpr char LOG_DB_TABLE_NAME[] = "app_events";
36 constexpr char LOG_DB_APP_EVENTS_TMP[] = "app_events_tmp";
37 constexpr int DB_VERSION_1 = 1;
38 constexpr int DB_VERSION_2 = 2;
39 
40 constexpr char SQL_TYPE_INTEGER_NOT_NULL[] = "INTEGER NOT NULL";
41 constexpr char SQL_TYPE_INTEGER_DEFAULT_0[] = "INTEGER DEFAULT 0";
42 constexpr char SQL_TYPE_INTEGER[] = "INTEGER";
43 constexpr char SQL_TYPE_REAL[] = "REAL";
44 constexpr char SQL_TYPE_TEXT_NOT_NULL[] = "TEXT NOT NULL";
45 constexpr char SQL_TYPE_TEXT[] = "TEXT";
46 
47 constexpr int DB_SUCC = 0;
48 constexpr int DB_FAILED = -1;
49 
UpdateScreenStatInfo(FoldAppUsageInfo & info,uint32_t time,int screenStatus)50 void UpdateScreenStatInfo(FoldAppUsageInfo &info, uint32_t time, int screenStatus)
51 {
52     std::map<int, std::function<void(FoldAppUsageInfo&, uint32_t)>> updateHandlers = {
53         {EXPAND_PORTRAIT_FULL_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdVer += time;} },
54         {EXPAND_PORTRAIT_SPLIT_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdVerSplit += time;} },
55         {EXPAND_PORTRAIT_FLOATING_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdVerFloating += time;} },
56         {EXPAND_PORTRAIT_MIDSCENE_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdVerMidscene += time;} },
57         {EXPAND_LANDSCAPE_FULL_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdHor += time;} },
58         {EXPAND_LANDSCAPE_SPLIT_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdHorSplit += time;} },
59         {EXPAND_LANDSCAPE_FLOATING_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdHorFloating += time;} },
60         {EXPAND_LANDSCAPE_MIDSCENE_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.expdHorMidscene += time;} },
61         {FOLD_PORTRAIT_FULL_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldVer += time;} },
62         {FOLD_PORTRAIT_SPLIT_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldVerSplit += time;} },
63         {FOLD_PORTRAIT_FLOATING_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldVerFloating += time;} },
64         {FOLD_PORTRAIT_MIDSCENE_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldVerMidscene += time;} },
65         {FOLD_LANDSCAPE_FULL_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldHor += time;} },
66         {FOLD_LANDSCAPE_SPLIT_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldHorSplit += time;} },
67         {FOLD_LANDSCAPE_FLOATING_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldHorFloating += time;} },
68         {FOLD_LANDSCAPE_MIDSCENE_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.foldHorMidscene += time;} },
69         {G_PORTRAIT_FULL_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gVer += time;} },
70         {G_PORTRAIT_SPLIT_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gVerSplit += time;} },
71         {G_PORTRAIT_FLOATING_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gVerFloating += time;} },
72         {G_PORTRAIT_MIDSCENE_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gVerMidscene += time;} },
73         {G_LANDSCAPE_FULL_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gHor += time;} },
74         {G_LANDSCAPE_SPLIT_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gHorSplit += time;} },
75         {G_LANDSCAPE_FLOATING_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gHorFloating += time;} },
76         {G_LANDSCAPE_MIDSCENE_STATUS, [] (FoldAppUsageInfo& info, uint32_t time) {info.gHorMidscene += time;} },
77     };
78     if (updateHandlers.find(screenStatus) != updateHandlers.end()) {
79         updateHandlers[screenStatus](info, time);
80     }
81 }
82 
CaculateForegroundAppUsage(const std::vector<FoldAppUsageRawEvent> & events,uint64_t startTime,uint64_t endTime,const std::string & appName,int screenStatus)83 FoldAppUsageInfo CaculateForegroundAppUsage(const std::vector<FoldAppUsageRawEvent> &events,
84     uint64_t startTime, uint64_t endTime, const std::string &appName, int screenStatus)
85 {
86     FoldAppUsageInfo info;
87     info.package = appName;
88     // no event means: app is foreground for whole day.
89     if (events.size() == 0) {
90         UpdateScreenStatInfo(info, static_cast<uint32_t>(endTime - startTime), screenStatus);
91         return info;
92     }
93     uint32_t size = events.size();
94     // first event is screen changed, means app is started befor statistic period.
95     if (events[size - 1].rawId == FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
96         UpdateScreenStatInfo(info, static_cast<uint32_t>(events[size - 1].happenTime - startTime),
97             events[size - 1].screenStatusBefore);
98     }
99     // caculate all period between screen status changed events, till endTime.
100     for (uint32_t i = size - 1; i > 0; --i) {
101         if (events[i - 1].ts > events[i].ts) {
102             UpdateScreenStatInfo(info, static_cast<uint32_t>(events[i - 1].ts - events[i].ts),
103                 events[i].screenStatusAfter);
104         }
105     }
106     UpdateScreenStatInfo(info, static_cast<uint32_t>(endTime - events[0].happenTime), events[0].screenStatusAfter);
107     return info;
108 }
109 
GetStringFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,std::string & value)110 bool GetStringFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
111     const std::string& colName, std::string &value)
112 {
113     int colIndex = 0;
114     if (resultSet->GetColumnIndex(colName, colIndex) != NativeRdb::E_OK) {
115         HIVIEW_LOGE("failed to get column index, column = %{public}s", colName.c_str());
116         return false;
117     }
118     if (resultSet->GetString(colIndex, value) != NativeRdb::E_OK) {
119         HIVIEW_LOGE("failed to get string value, column = %{public}s", colName.c_str());
120         return false;
121     }
122     return true;
123 }
124 
GetIntFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,int & value)125 bool GetIntFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
126     const std::string& colName, int &value)
127 {
128     int colIndex = 0;
129     if (resultSet->GetColumnIndex(colName, colIndex) != NativeRdb::E_OK) {
130         HIVIEW_LOGE("failed to get column index, column = %{public}s", colName.c_str());
131         return false;
132     }
133     if (resultSet->GetInt(colIndex, value) != NativeRdb::E_OK) {
134         HIVIEW_LOGE("failed to get int value, column = %{public}s", colName.c_str());
135         return false;
136     }
137     return true;
138 }
139 
GetUIntFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,uint32_t & value)140 bool GetUIntFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
141     const std::string& colName, uint32_t &value)
142 {
143     int tmpValue = 0;
144     bool ret = GetIntFromResultSet(resultSet, colName, tmpValue);
145     value = static_cast<uint32_t>(tmpValue);
146     return ret;
147 }
148 
GetLongFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,const std::string & colName,int64_t & value)149 bool GetLongFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
150     const std::string& colName, int64_t &value)
151 {
152     int colIndex = 0;
153     if (resultSet->GetColumnIndex(colName, colIndex) != NativeRdb::E_OK) {
154         HIVIEW_LOGE("failed to get column index, column = %{public}s", colName.c_str());
155         return false;
156     }
157     if (resultSet->GetLong(colIndex, value) != NativeRdb::E_OK) {
158         HIVIEW_LOGE("failed to get long value, column = %{public}s", colName.c_str());
159         return false;
160     }
161     return true;
162 }
163 
GenerateRenameTableSql(const std::string & oldTable,const std::string & newTable)164 std::string GenerateRenameTableSql(const std::string& oldTable, const std::string& newTable)
165 {
166     std::string sql = "ALTER TABLE " + oldTable + " RENAME TO " + newTable;
167     return sql;
168 }
169 
GenerateCreateAppEventsSql()170 std::string GenerateCreateAppEventsSql()
171 {
172     std::vector<std::pair<std::string, std::string>> fields = {
173         {FIELD_UID, SQL_TYPE_INTEGER_NOT_NULL},
174         {FIELD_EVENT_ID, SQL_TYPE_INTEGER_NOT_NULL},
175         {FIELD_TS, SQL_TYPE_INTEGER_NOT_NULL},
176         {FIELD_FOLD_STATUS, SQL_TYPE_INTEGER},
177         {FIELD_PRE_FOLD_STATUS, SQL_TYPE_INTEGER},
178         {FIELD_VERSION_NAME, SQL_TYPE_TEXT},
179         {FIELD_HAPPEN_TIME, SQL_TYPE_INTEGER},
180         {FIELD_FOLD_PORTRAIT_DURATION, SQL_TYPE_INTEGER},
181         {FIELD_FOLD_LANDSCAPE_DURATION, SQL_TYPE_INTEGER},
182         {FIELD_EXPAND_PORTRAIT_DURATION, SQL_TYPE_INTEGER},
183         {FIELD_EXPAND_LANDSCAPE_DURATION, SQL_TYPE_INTEGER},
184         {FIELD_BUNDLE_NAME, SQL_TYPE_TEXT_NOT_NULL},
185         {FIELD_FOLD_PORTRAIT_SPLIT_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
186         {FIELD_FOLD_PORTRAIT_FLOATING_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
187         {FIELD_FOLD_PORTRAIT_MIDSCENE_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
188         {FIELD_FOLD_LANDSCAPE_SPLIT_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
189         {FIELD_FOLD_LANDSCAPE_FLOATING_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
190         {FIELD_FOLD_LANDSCAPE_MIDSCENE_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
191         {FIELD_EXPAND_PORTRAIT_SPLIT_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
192         {FIELD_EXPAND_PORTRAIT_FLOATING_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
193         {FIELD_EXPAND_PORTRAIT_MIDSCENE_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
194         {FIELD_EXPAND_LANDSCAPE_SPLIT_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
195         {FIELD_EXPAND_LANDSCAPE_FLOATING_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
196         {FIELD_EXPAND_LANDSCAPE_MIDSCENE_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
197         {FIELD_G_PORTRAIT_FULL_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
198         {FIELD_G_PORTRAIT_SPLIT_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
199         {FIELD_G_PORTRAIT_FLOATING_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
200         {FIELD_G_PORTRAIT_MIDSCENE_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
201         {FIELD_G_LANDSCAPE_FULL_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
202         {FIELD_G_LANDSCAPE_SPLIT_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
203         {FIELD_G_LANDSCAPE_FLOATING_DURATION, SQL_TYPE_INTEGER_DEFAULT_0},
204         {FIELD_G_LANDSCAPE_MIDSCENE_DURATION, SQL_TYPE_INTEGER_DEFAULT_0}
205     };
206     return SqlUtil::GenerateCreateSql(LOG_DB_TABLE_NAME, fields);
207 }
208 
GenerateInsertSql(const std::string & newTable,const std::string & oldTable)209 std::string GenerateInsertSql(const std::string& newTable, const std::string& oldTable)
210 {
211     std::vector<std::string> fields = {
212         FIELD_ID, FIELD_UID, FIELD_EVENT_ID,
213         FIELD_TS, FIELD_FOLD_STATUS, FIELD_PRE_FOLD_STATUS,
214         FIELD_VERSION_NAME, FIELD_HAPPEN_TIME,
215         FIELD_FOLD_PORTRAIT_DURATION, FIELD_FOLD_LANDSCAPE_DURATION,
216         FIELD_EXPAND_PORTRAIT_DURATION, FIELD_EXPAND_LANDSCAPE_DURATION,
217         FIELD_BUNDLE_NAME
218     };
219     size_t fieldsSize = fields.size();
220     std::string insertSql = "INSERT INTO ";
221     insertSql.append(newTable).append("(");
222     std::string values = "";
223     for (size_t i = 0; i < fieldsSize; ++i) {
224         insertSql.append(fields[i]);
225         values.append(fields[i]);
226         if (fields[i] == FIELD_FOLD_STATUS || fields[i] == FIELD_PRE_FOLD_STATUS) {
227             // ScreenFoldStatus: change the historical status value from two digits to three digits
228             values.append(" * 10 AS ").append(fields[i]);
229         }
230         if (i != (fieldsSize - 1)) { // -1 for last field
231             insertSql.append(", ");
232             values.append(", ");
233         }
234     }
235     insertSql.append(") SELECT ").append(values).append(" FROM ").append(oldTable);
236     return insertSql;
237 }
238 
239 /*
240  * step1. rename app_events to app_events_tmp
241  * step2. create new table app_events
242  * step3. insert into app_events from app_events_tmp
243  * step4. drop table app_events_tmp
244  */
UpgradeDbFromV1ToV2(NativeRdb::RdbStore & rdbStore)245 int UpgradeDbFromV1ToV2(NativeRdb::RdbStore& rdbStore)
246 {
247     std::vector<std::string> sqls = {
248         GenerateRenameTableSql(LOG_DB_TABLE_NAME, LOG_DB_APP_EVENTS_TMP),
249         GenerateCreateAppEventsSql(),
250         GenerateInsertSql(LOG_DB_TABLE_NAME, LOG_DB_APP_EVENTS_TMP),
251         SqlUtil::GenerateDropSql(LOG_DB_APP_EVENTS_TMP)
252     };
253     if (int ret = rdbStore.BeginTransaction(); ret != NativeRdb::E_OK) {
254         HIVIEW_LOGE("failed to begin transaction, ret=%{public}d", ret);
255         return ret;
256     }
257     for (const auto& sql : sqls) {
258         if (int ret = rdbStore.ExecuteSql(sql); ret != NativeRdb::E_OK) {
259             HIVIEW_LOGE("failed to upgrade db version from 1 to 2, ret=%{public}d", ret);
260             rdbStore.RollBack();
261             return ret;
262         }
263     }
264     return rdbStore.Commit();
265 }
266 
GetDuration(const int foldStatus,const std::map<int,uint64_t> & durations)267 int64_t GetDuration(const int foldStatus, const std::map<int, uint64_t>& durations)
268 {
269     auto it = durations.find(foldStatus);
270     if (it == durations.end()) {
271         return 0;
272     }
273     return static_cast<int64_t>(it->second);
274 }
275 
SetValuesBucket(NativeRdb::ValuesBucket & bucket,const std::map<int,uint64_t> & durations)276 void SetValuesBucket(NativeRdb::ValuesBucket& bucket, const std::map<int, uint64_t>& durations)
277 {
278     bucket.PutLong(FIELD_FOLD_PORTRAIT_DURATION, GetDuration(FOLD_PORTRAIT_FULL_STATUS, durations));
279     bucket.PutLong(FIELD_FOLD_LANDSCAPE_DURATION, GetDuration(FOLD_LANDSCAPE_FULL_STATUS, durations));
280     bucket.PutLong(FIELD_EXPAND_PORTRAIT_DURATION, GetDuration(EXPAND_PORTRAIT_FULL_STATUS, durations));
281     bucket.PutLong(FIELD_EXPAND_LANDSCAPE_DURATION, GetDuration(EXPAND_LANDSCAPE_FULL_STATUS, durations));
282     bucket.PutLong(FIELD_FOLD_PORTRAIT_SPLIT_DURATION, GetDuration(FOLD_PORTRAIT_SPLIT_STATUS, durations));
283     bucket.PutLong(FIELD_FOLD_PORTRAIT_FLOATING_DURATION, GetDuration(FOLD_PORTRAIT_FLOATING_STATUS, durations));
284     bucket.PutLong(FIELD_FOLD_PORTRAIT_MIDSCENE_DURATION, GetDuration(FOLD_PORTRAIT_MIDSCENE_STATUS, durations));
285     bucket.PutLong(FIELD_FOLD_LANDSCAPE_SPLIT_DURATION, GetDuration(FOLD_LANDSCAPE_SPLIT_STATUS, durations));
286     bucket.PutLong(FIELD_FOLD_LANDSCAPE_FLOATING_DURATION, GetDuration(FOLD_LANDSCAPE_FLOATING_STATUS, durations));
287     bucket.PutLong(FIELD_FOLD_LANDSCAPE_MIDSCENE_DURATION, GetDuration(FOLD_LANDSCAPE_MIDSCENE_STATUS, durations));
288     bucket.PutLong(FIELD_EXPAND_PORTRAIT_SPLIT_DURATION, GetDuration(EXPAND_PORTRAIT_SPLIT_STATUS, durations));
289     bucket.PutLong(FIELD_EXPAND_PORTRAIT_FLOATING_DURATION, GetDuration(EXPAND_PORTRAIT_FLOATING_STATUS, durations));
290     bucket.PutLong(FIELD_EXPAND_PORTRAIT_MIDSCENE_DURATION, GetDuration(EXPAND_PORTRAIT_MIDSCENE_STATUS, durations));
291     bucket.PutLong(FIELD_EXPAND_LANDSCAPE_SPLIT_DURATION, GetDuration(EXPAND_LANDSCAPE_SPLIT_STATUS, durations));
292     bucket.PutLong(FIELD_EXPAND_LANDSCAPE_FLOATING_DURATION, GetDuration(EXPAND_LANDSCAPE_FLOATING_STATUS, durations));
293     bucket.PutLong(FIELD_EXPAND_LANDSCAPE_MIDSCENE_DURATION, GetDuration(EXPAND_LANDSCAPE_MIDSCENE_STATUS, durations));
294     bucket.PutLong(FIELD_G_PORTRAIT_FULL_DURATION, GetDuration(G_PORTRAIT_FULL_STATUS, durations));
295     bucket.PutLong(FIELD_G_PORTRAIT_SPLIT_DURATION, GetDuration(G_PORTRAIT_SPLIT_STATUS, durations));
296     bucket.PutLong(FIELD_G_PORTRAIT_FLOATING_DURATION, GetDuration(G_PORTRAIT_FLOATING_STATUS, durations));
297     bucket.PutLong(FIELD_G_PORTRAIT_MIDSCENE_DURATION, GetDuration(G_PORTRAIT_MIDSCENE_STATUS, durations));
298     bucket.PutLong(FIELD_G_LANDSCAPE_FULL_DURATION, GetDuration(G_LANDSCAPE_FULL_STATUS, durations));
299     bucket.PutLong(FIELD_G_LANDSCAPE_SPLIT_DURATION, GetDuration(G_LANDSCAPE_SPLIT_STATUS, durations));
300     bucket.PutLong(FIELD_G_LANDSCAPE_FLOATING_DURATION, GetDuration(G_LANDSCAPE_FLOATING_STATUS, durations));
301     bucket.PutLong(FIELD_G_LANDSCAPE_MIDSCENE_DURATION, GetDuration(G_LANDSCAPE_MIDSCENE_STATUS, durations));
302 }
303 
ParseEntity(NativeRdb::RowEntity & entity,AppEventRecord & record)304 void ParseEntity(NativeRdb::RowEntity& entity, AppEventRecord& record)
305 {
306     entity.Get(FIELD_EVENT_ID).GetInt(record.rawid);
307     entity.Get(FIELD_TS).GetLong(record.ts);
308     entity.Get(FIELD_FOLD_STATUS).GetInt(record.foldStatus);
309     entity.Get(FIELD_PRE_FOLD_STATUS).GetInt(record.preFoldStatus);
310     entity.Get(FIELD_VERSION_NAME).GetString(record.versionName);
311     entity.Get(FIELD_HAPPEN_TIME).GetLong(record.happenTime);
312     entity.Get(FIELD_BUNDLE_NAME).GetString(record.bundleName);
313 }
314 
GetUsageDurationFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,FoldAppUsageInfo & usageInfo)315 bool GetUsageDurationFromResultSet(std::shared_ptr<NativeRdb::AbsSharedResultSet> resultSet,
316     FoldAppUsageInfo& usageInfo)
317 {
318     bool res = GetUIntFromResultSet(resultSet, FIELD_FOLD_PORTRAIT_DURATION, usageInfo.foldVer);
319     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_LANDSCAPE_DURATION, usageInfo.foldHor);
320     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_PORTRAIT_DURATION, usageInfo.expdVer);
321     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_LANDSCAPE_DURATION, usageInfo.expdHor);
322     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_PORTRAIT_SPLIT_DURATION, usageInfo.foldVerSplit);
323     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_PORTRAIT_FLOATING_DURATION, usageInfo.foldVerFloating);
324     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_PORTRAIT_MIDSCENE_DURATION, usageInfo.foldVerMidscene);
325     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_LANDSCAPE_SPLIT_DURATION, usageInfo.foldHorSplit);
326     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_LANDSCAPE_FLOATING_DURATION, usageInfo.foldHorFloating);
327     res &= GetUIntFromResultSet(resultSet, FIELD_FOLD_LANDSCAPE_MIDSCENE_DURATION, usageInfo.foldHorMidscene);
328     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_PORTRAIT_SPLIT_DURATION, usageInfo.expdVerSplit);
329     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_PORTRAIT_FLOATING_DURATION, usageInfo.expdVerFloating);
330     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_PORTRAIT_MIDSCENE_DURATION, usageInfo.expdVerMidscene);
331     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_LANDSCAPE_SPLIT_DURATION, usageInfo.expdHorSplit);
332     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_LANDSCAPE_FLOATING_DURATION, usageInfo.expdHorFloating);
333     res &= GetUIntFromResultSet(resultSet, FIELD_EXPAND_LANDSCAPE_MIDSCENE_DURATION, usageInfo.expdHorMidscene);
334     res &= GetUIntFromResultSet(resultSet, FIELD_G_PORTRAIT_FULL_DURATION, usageInfo.gVer);
335     res &= GetUIntFromResultSet(resultSet, FIELD_G_PORTRAIT_SPLIT_DURATION, usageInfo.gVerSplit);
336     res &= GetUIntFromResultSet(resultSet, FIELD_G_PORTRAIT_FLOATING_DURATION, usageInfo.gVerFloating);
337     res &= GetUIntFromResultSet(resultSet, FIELD_G_PORTRAIT_MIDSCENE_DURATION, usageInfo.gVerMidscene);
338     res &= GetUIntFromResultSet(resultSet, FIELD_G_LANDSCAPE_FULL_DURATION, usageInfo.gHor);
339     res &= GetUIntFromResultSet(resultSet, FIELD_G_LANDSCAPE_SPLIT_DURATION, usageInfo.gHorSplit);
340     res &= GetUIntFromResultSet(resultSet, FIELD_G_LANDSCAPE_FLOATING_DURATION, usageInfo.gHorFloating);
341     res &= GetUIntFromResultSet(resultSet, FIELD_G_LANDSCAPE_MIDSCENE_DURATION, usageInfo.gHorMidscene);
342     return res;
343 }
344 }
345 
operator +=(const FoldAppUsageInfo & info)346 FoldAppUsageInfo& FoldAppUsageInfo::operator+=(const FoldAppUsageInfo& info)
347 {
348     foldVer += info.foldVer;
349     foldHor += info.foldHor;
350     expdVer += info.expdVer;
351     expdHor += info.expdHor;
352     gVer += info.gVer;
353     gHor += info.gHor;
354     foldVerSplit += info.foldVerSplit;
355     foldVerFloating += info.foldVerFloating;
356     foldVerMidscene += info.foldVerMidscene;
357     foldHorSplit += info.foldHorSplit;
358     foldHorFloating += info.foldHorFloating;
359     foldHorMidscene += info.foldHorMidscene;
360     expdVerSplit += info.expdVerSplit;
361     expdVerFloating += info.expdVerFloating;
362     expdVerMidscene += info.expdVerMidscene;
363     expdHorSplit += info.expdHorSplit;
364     expdHorFloating += info.expdHorFloating;
365     expdHorMidscene += info.expdHorMidscene;
366     gVerSplit += info.gVerSplit;
367     gVerFloating += info.gVerFloating;
368     gVerMidscene += info.gVerMidscene;
369     gHorSplit += info.gHorSplit;
370     gHorFloating += info.gHorFloating;
371     gHorMidscene += info.gHorMidscene;
372     startNum += info.startNum;
373     return *this;
374 }
375 
GetAppUsage() const376 uint32_t FoldAppUsageInfo::GetAppUsage() const
377 {
378     return foldVer + foldHor + expdVer + expdHor + gVer + gHor + foldVerSplit + foldVerFloating + foldVerMidscene +
379         foldHorSplit + foldHorFloating + foldHorMidscene + expdVerSplit + expdVerFloating + expdVerMidscene +
380         expdHorSplit + expdHorFloating + expdHorMidscene + gVerSplit + gVerFloating + gVerMidscene +
381         gHorSplit + gHorFloating + gHorMidscene;
382 }
383 
384 class FoldDbStoreCallback : public NativeRdb::RdbOpenCallback {
385 public:
386     int OnCreate(NativeRdb::RdbStore& rdbStore) override;
387     int OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion) override;
388 };
389 
OnCreate(NativeRdb::RdbStore & rdbStore)390 int FoldDbStoreCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
391 {
392     HIVIEW_LOGD("create dbStore");
393     return NativeRdb::E_OK;
394 }
395 
OnUpgrade(NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)396 int FoldDbStoreCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore, int oldVersion, int newVersion)
397 {
398     HIVIEW_LOGI("oldVersion = %{public}d, newVersion = %{public}d", oldVersion, newVersion);
399     if (oldVersion == DB_VERSION_1 && newVersion == DB_VERSION_2) {
400         return UpgradeDbFromV1ToV2(rdbStore);
401     }
402     return NativeRdb::E_OK;
403 }
404 
FoldAppUsageDbHelper(const std::string & workPath)405 FoldAppUsageDbHelper::FoldAppUsageDbHelper(const std::string& workPath)
406 {
407     dbPath_ = workPath;
408     if (workPath.back() != '/') {
409         dbPath_ = workPath + "/";
410     }
411     dbPath_ += LOG_DB_PATH;
412     CreateDbStore(dbPath_, LOG_DB_NAME);
413     if (int ret = CreateAppEventsTable(LOG_DB_TABLE_NAME); ret != DB_SUCC) {
414         HIVIEW_LOGI("failed to create table");
415     }
416 }
417 
~FoldAppUsageDbHelper()418 FoldAppUsageDbHelper::~FoldAppUsageDbHelper()
419 {}
420 
CreateDbStore(const std::string & dbPath,const std::string & dbName)421 void FoldAppUsageDbHelper::CreateDbStore(const std::string& dbPath, const std::string& dbName)
422 {
423     std::string dbFile = dbPath + dbName;
424     if (!FileUtil::FileExists(dbPath) && FileUtil::ForceCreateDirectory(dbPath, FileUtil::FILE_PERM_770)) {
425         HIVIEW_LOGI("failed to create db path, use default path");
426         return;
427     }
428     NativeRdb::RdbStoreConfig config(dbFile);
429     config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
430     FoldDbStoreCallback callback;
431     int ret = NativeRdb::E_OK;
432     rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, DB_VERSION_2, callback, ret);
433     if (ret != NativeRdb::E_OK || rdbStore_ == nullptr) {
434         HIVIEW_LOGI("failed to create db store, dbFile = %{public}s, ret = %{public}d", dbFile.c_str(), ret);
435     }
436 }
437 
CreateAppEventsTable(const std::string & table)438 int FoldAppUsageDbHelper::CreateAppEventsTable(const std::string& table)
439 {
440     std::lock_guard<std::mutex> lockGuard(dbMutex_);
441     if (rdbStore_ == nullptr) {
442         HIVIEW_LOGI("dbstore is nullptr");
443         return DB_FAILED;
444     }
445     if (rdbStore_->ExecuteSql(GenerateCreateAppEventsSql()) != NativeRdb::E_OK) {
446         return DB_FAILED;
447     }
448     return DB_SUCC;
449 }
450 
AddAppEvent(const AppEventRecord & appEventRecord,const std::map<int,uint64_t> & durations)451 int FoldAppUsageDbHelper::AddAppEvent(const AppEventRecord& appEventRecord, const std::map<int, uint64_t>& durations)
452 {
453     std::lock_guard<std::mutex> lockGuard(dbMutex_);
454     if (rdbStore_ == nullptr) {
455         HIVIEW_LOGE("dbStore is nullptr");
456         return DB_FAILED;
457     }
458     NativeRdb::ValuesBucket valuesBucket;
459     valuesBucket.PutInt(FIELD_UID, -1);
460     valuesBucket.PutInt(FIELD_EVENT_ID, appEventRecord.rawid);
461     valuesBucket.PutLong(FIELD_TS, appEventRecord.ts);
462     valuesBucket.PutInt(FIELD_FOLD_STATUS, appEventRecord.foldStatus);
463     valuesBucket.PutInt(FIELD_PRE_FOLD_STATUS, appEventRecord.preFoldStatus);
464     valuesBucket.PutString(FIELD_VERSION_NAME, appEventRecord.versionName);
465     valuesBucket.PutLong(FIELD_HAPPEN_TIME, appEventRecord.happenTime);
466     valuesBucket.PutString(FIELD_BUNDLE_NAME, appEventRecord.bundleName);
467     SetValuesBucket(valuesBucket, durations);
468     int64_t seq = 0;
469     if (int ret = rdbStore_->Insert(seq, LOG_DB_TABLE_NAME, valuesBucket); ret != NativeRdb::E_OK) {
470         HIVIEW_LOGI("failed to add app event");
471         return DB_FAILED;
472     }
473     return DB_SUCC;
474 }
475 
QueryRawEventIndex(const std::string & bundleName,int rawId)476 int FoldAppUsageDbHelper::QueryRawEventIndex(const std::string& bundleName, int rawId)
477 {
478     std::lock_guard<std::mutex> lockGuard(dbMutex_);
479     if (rdbStore_ == nullptr) {
480         HIVIEW_LOGE("dbStore is nullptr");
481         return 0;
482     }
483     NativeRdb::RdbPredicates predicates(LOG_DB_TABLE_NAME);
484     predicates.EqualTo(FIELD_BUNDLE_NAME, bundleName);
485     predicates.EqualTo(FIELD_EVENT_ID, rawId);
486     predicates.OrderByDesc(FIELD_ID);
487     predicates.Limit(1); // query the nearest one event
488     auto resultSet = rdbStore_->Query(predicates, {FIELD_ID});
489     int index = 0;
490     if (resultSet == nullptr) {
491         HIVIEW_LOGI("failed to query raw event index");
492         return index;
493     }
494     if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
495         GetIntFromResultSet(resultSet, FIELD_ID, index);
496     }
497     resultSet->Close();
498     return index;
499 }
500 
QueryAppEventRecords(int startIndex,int64_t dayStartTime,const std::string & bundleName,std::vector<AppEventRecord> & records)501 void FoldAppUsageDbHelper::QueryAppEventRecords(int startIndex, int64_t dayStartTime, const std::string& bundleName,
502     std::vector<AppEventRecord>& records)
503 {
504     std::lock_guard<std::mutex> lockGuard(dbMutex_);
505     if (rdbStore_ == nullptr) {
506         HIVIEW_LOGE("dbStore is nullptr");
507         return;
508     }
509     NativeRdb::RdbPredicates predicates(LOG_DB_TABLE_NAME);
510     predicates.EqualTo(FIELD_BUNDLE_NAME, bundleName);
511     predicates.GreaterThanOrEqualTo(FIELD_ID, startIndex);
512     predicates.GreaterThanOrEqualTo(FIELD_HAPPEN_TIME, dayStartTime);
513     predicates.OrderByAsc(FIELD_ID);
514 
515     std::vector<std::string> columns = {
516         FIELD_EVENT_ID, FIELD_TS, FIELD_FOLD_STATUS, FIELD_PRE_FOLD_STATUS,
517         FIELD_VERSION_NAME, FIELD_HAPPEN_TIME, FIELD_BUNDLE_NAME
518     };
519     auto resultSet = rdbStore_->Query(predicates, columns);
520     if (resultSet == nullptr) {
521         HIVIEW_LOGI("failed to query event event");
522         return;
523     }
524     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
525         NativeRdb::RowEntity entity;
526         if (resultSet->GetRow(entity) != NativeRdb::E_OK) {
527             HIVIEW_LOGI("failed to read row entity from result set");
528             resultSet->Close();
529             return;
530         }
531         AppEventRecord record;
532         ParseEntity(entity, record);
533         if (record.rawid == FoldEventId::EVENT_COUNT_DURATION) {
534             records.clear();
535             continue;
536         }
537         records.emplace_back(record);
538     }
539     resultSet->Close();
540 }
541 
QueryFinalAppInfo(uint64_t endTime,FoldAppUsageRawEvent & event)542 void FoldAppUsageDbHelper::QueryFinalAppInfo(uint64_t endTime, FoldAppUsageRawEvent& event)
543 {
544     std::lock_guard<std::mutex> lockGuard(dbMutex_);
545     if (rdbStore_ == nullptr) {
546         HIVIEW_LOGE("db is nullptr");
547         return;
548     }
549     NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
550     predicates.Between(FIELD_HAPPEN_TIME, 0, static_cast<int64_t>(endTime));
551     predicates.OrderByDesc(FIELD_ID);
552     predicates.Limit(1);
553     auto resultSet = rdbStore_->Query(predicates, {FIELD_ID, FIELD_EVENT_ID, FIELD_FOLD_STATUS, FIELD_BUNDLE_NAME});
554     if (resultSet == nullptr) {
555         HIVIEW_LOGE("resultSet is nullptr");
556         return;
557     }
558     if (resultSet->GoToNextRow() == NativeRdb::E_OK &&
559         GetLongFromResultSet(resultSet, FIELD_ID, event.id) &&
560         GetIntFromResultSet(resultSet, FIELD_EVENT_ID, event.rawId) &&
561         GetIntFromResultSet(resultSet, FIELD_FOLD_STATUS, event.screenStatusAfter) &&
562         GetStringFromResultSet(resultSet, FIELD_BUNDLE_NAME, event.package)) {
563         HIVIEW_LOGI("get handle seq=%{public}" PRId64 ", rawId=%{public}d, screen stat=%{public}d",
564             event.id, event.rawId, event.screenStatusAfter);
565     } else {
566         HIVIEW_LOGE("get handle seq and screen stat failed");
567     }
568     resultSet->Close();
569     return;
570 }
571 
QueryStatisticEventsInPeriod(uint64_t startTime,uint64_t endTime,std::unordered_map<std::string,FoldAppUsageInfo> & infos)572 void FoldAppUsageDbHelper::QueryStatisticEventsInPeriod(uint64_t startTime, uint64_t endTime,
573     std::unordered_map<std::string, FoldAppUsageInfo> &infos)
574 {
575     std::lock_guard<std::mutex> lockGuard(dbMutex_);
576     if (rdbStore_ == nullptr) {
577         HIVIEW_LOGE("db is nullptr");
578         return;
579     }
580     std::vector<std::string> columns = {
581         FIELD_FOLD_PORTRAIT_DURATION, FIELD_FOLD_LANDSCAPE_DURATION,
582         FIELD_EXPAND_PORTRAIT_DURATION, FIELD_EXPAND_LANDSCAPE_DURATION,
583         FIELD_FOLD_PORTRAIT_SPLIT_DURATION, FIELD_FOLD_PORTRAIT_FLOATING_DURATION,
584         FIELD_FOLD_PORTRAIT_MIDSCENE_DURATION, FIELD_FOLD_LANDSCAPE_SPLIT_DURATION,
585         FIELD_FOLD_LANDSCAPE_FLOATING_DURATION, FIELD_FOLD_LANDSCAPE_MIDSCENE_DURATION,
586         FIELD_EXPAND_PORTRAIT_SPLIT_DURATION, FIELD_EXPAND_PORTRAIT_FLOATING_DURATION,
587         FIELD_EXPAND_PORTRAIT_MIDSCENE_DURATION, FIELD_EXPAND_LANDSCAPE_SPLIT_DURATION,
588         FIELD_EXPAND_LANDSCAPE_FLOATING_DURATION, FIELD_EXPAND_LANDSCAPE_MIDSCENE_DURATION,
589         FIELD_G_PORTRAIT_FULL_DURATION, FIELD_G_PORTRAIT_SPLIT_DURATION,
590         FIELD_G_PORTRAIT_FLOATING_DURATION, FIELD_G_PORTRAIT_MIDSCENE_DURATION,
591         FIELD_G_LANDSCAPE_FULL_DURATION, FIELD_G_LANDSCAPE_SPLIT_DURATION,
592         FIELD_G_LANDSCAPE_FLOATING_DURATION, FIELD_G_LANDSCAPE_MIDSCENE_DURATION
593     };
594     std::string sqlCmd = "SELECT ";
595     sqlCmd.append(FIELD_BUNDLE_NAME).append(", ").append(FIELD_VERSION_NAME);
596     for (const auto& column : columns) {
597         sqlCmd.append(", SUM(").append(column).append(") AS ").append(column);
598     }
599     sqlCmd.append(", COUNT(*) AS start_num FROM ").append(LOG_DB_TABLE_NAME);
600     sqlCmd.append(" WHERE ").append(FIELD_EVENT_ID).append("=");
601     sqlCmd.append(std::to_string(FoldEventId::EVENT_COUNT_DURATION));
602     sqlCmd.append(" AND ").append(FIELD_HAPPEN_TIME).append(" BETWEEN ");
603     sqlCmd.append(std::to_string(startTime)).append(" AND ").append(std::to_string(endTime));
604     sqlCmd.append(" GROUP BY ").append(FIELD_BUNDLE_NAME).append(", ");
605     sqlCmd.append(FIELD_VERSION_NAME);
606     auto resultSet = rdbStore_->QuerySql(sqlCmd);
607     if (resultSet == nullptr) {
608         HIVIEW_LOGE("resultSet is nullptr");
609         return;
610     }
611     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
612         FoldAppUsageInfo usageInfo;
613         if (GetStringFromResultSet(resultSet, FIELD_BUNDLE_NAME, usageInfo.package) &&
614             GetStringFromResultSet(resultSet, FIELD_VERSION_NAME, usageInfo.version) &&
615             GetUsageDurationFromResultSet(resultSet, usageInfo) &&
616             GetUIntFromResultSet(resultSet, "start_num", usageInfo.startNum)) {
617             infos[usageInfo.package + usageInfo.version] = usageInfo;
618         } else {
619             HIVIEW_LOGE("fail to get appusage info!");
620         }
621     }
622     resultSet->Close();
623 }
624 
QueryForegroundAppsInfo(uint64_t startTime,uint64_t endTime,int screenStatus,FoldAppUsageInfo & info)625 void FoldAppUsageDbHelper::QueryForegroundAppsInfo(uint64_t startTime, uint64_t endTime, int screenStatus,
626     FoldAppUsageInfo &info)
627 {
628     std::lock_guard<std::mutex> lockGuard(dbMutex_);
629     if (rdbStore_ == nullptr) {
630         HIVIEW_LOGE("db is nullptr");
631         return;
632     }
633     NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
634     predicates.EqualTo(FIELD_BUNDLE_NAME, info.package);
635     predicates.Between(FIELD_HAPPEN_TIME, static_cast<int64_t>(startTime),
636         static_cast<int64_t>(endTime));
637     predicates.OrderByDesc(FIELD_ID);
638     auto resultSet = rdbStore_->Query(predicates, {FIELD_ID, FIELD_EVENT_ID,
639         FIELD_BUNDLE_NAME, FIELD_VERSION_NAME, FIELD_HAPPEN_TIME,
640         FIELD_FOLD_STATUS, FIELD_PRE_FOLD_STATUS, FIELD_TS});
641     if (resultSet == nullptr) {
642         HIVIEW_LOGE("resultSet is nullptr");
643         return;
644     }
645     std::vector<FoldAppUsageRawEvent> events;
646     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
647         FoldAppUsageRawEvent event;
648         if (!GetLongFromResultSet(resultSet, FIELD_ID, event.id) ||
649             !GetIntFromResultSet(resultSet, FIELD_EVENT_ID, event.rawId) ||
650             !GetStringFromResultSet(resultSet, FIELD_BUNDLE_NAME, event.package) ||
651             !GetStringFromResultSet(resultSet, FIELD_VERSION_NAME, event.version) ||
652             !GetLongFromResultSet(resultSet, FIELD_HAPPEN_TIME, event.happenTime) ||
653             !GetIntFromResultSet(resultSet, FIELD_FOLD_STATUS, event.screenStatusAfter) ||
654             !GetIntFromResultSet(resultSet, FIELD_PRE_FOLD_STATUS, event.screenStatusBefore) ||
655             !GetLongFromResultSet(resultSet, FIELD_TS, event.ts)) {
656             HIVIEW_LOGE("fail to get db event!");
657             resultSet->Close();
658             return;
659         }
660         if (event.rawId != FoldEventId::EVENT_APP_START && event.rawId != FoldEventId::EVENT_SCREEN_STATUS_CHANGED) {
661             HIVIEW_LOGE("can not find foreground event, latest raw id: %{public}d", event.rawId);
662             resultSet->Close();
663             return;
664         }
665         events.emplace_back(event);
666         if (event.rawId == FoldEventId::EVENT_APP_START) {
667             break;
668         }
669     }
670     info = CaculateForegroundAppUsage(events, startTime, endTime, info.package, screenStatus);
671     resultSet->Close();
672 }
673 
DeleteEventsByTime(uint64_t clearDataTime)674 int FoldAppUsageDbHelper::DeleteEventsByTime(uint64_t clearDataTime)
675 {
676     std::lock_guard<std::mutex> lockGuard(dbMutex_);
677     if (rdbStore_ == nullptr) {
678         HIVIEW_LOGE("db is nullptr");
679         return 0;
680     }
681     NativeRdb::AbsRdbPredicates predicates(LOG_DB_TABLE_NAME);
682     predicates.Between(FIELD_HAPPEN_TIME, 0, static_cast<int64_t>(clearDataTime));
683     int seq = 0;
684     int ret = rdbStore_->Delete(seq, predicates);
685     HIVIEW_LOGI("rows are deleted: %{public}d, ret: %{public}d", seq, ret);
686     return seq;
687 }
688 } // namespace HiviewDFX
689 } // namespace OHOS