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