• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 <iostream>
17 #include <fstream>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <sstream>
22 #include <cstdlib>
23 #include <algorithm>
24 #include <map>
25 #include <limits>
26 #include <cmath>
27 
28 #include "time_service_client.h"
29 
30 #include "bundle_active_constant.h"
31 #include "bundle_active_open_callback.h"
32 #include "bundle_active_log.h"
33 #include "bundle_active_package_stats.h"
34 #include "bundle_active_binary_search.h"
35 #include "bundle_active_period_stats.h"
36 #include "bundle_active_usage_database.h"
37 #include "bundle_active_bundle_mgr_helper.h"
38 #include "bundle_active_account_helper.h"
39 
40 namespace OHOS {
41 namespace DeviceUsageStats {
42 using namespace OHOS::NativeRdb;
43 using namespace std;
44 namespace {
45     const int32_t MAX_FILES_EVERY_INTERVAL_TYPE[SORTED_TABLE_ARRAY_NUMBER] = {30, 30, 12, 10};
46     const int32_t MAIN_APP_INDEX = 0;
47     const int32_t FILE_VERSION_LINE_NUM = 50;
48 }
BundleActiveUsageDatabase()49 BundleActiveUsageDatabase::BundleActiveUsageDatabase()
50 {
51     currentVersion_ = BUNDLE_ACTIVE_CURRENT_VERSION;
52     for (uint32_t i = 0; i < sizeof(DATABASE_TYPE)/sizeof(DATABASE_TYPE[0]); i++) {
53         databaseFiles_.push_back(DATABASE_TYPE[i] + SUFFIX_TYPE[0]);
54     }
55     eventTableName_ = UNKNOWN_TABLE_NAME;
56     durationTableName_ = UNKNOWN_TABLE_NAME;
57     bundleHistoryTableName_ = UNKNOWN_TABLE_NAME;
58     moduleRecordsTableName_ = UNKNOWN_TABLE_NAME;
59     formRecordsTableName_ = UNKNOWN_TABLE_NAME;
60     sortedTableArray_ = vector<vector<int64_t>>(SORTED_TABLE_ARRAY_NUMBER);
61     calendar_ = make_shared<BundleActiveCalendar>();
62     eventBeginTime_ = EVENT_BEGIN_TIME_INITIAL_VALUE;
63     debugDatabase_ = false;
64 }
65 
~BundleActiveUsageDatabase()66 BundleActiveUsageDatabase::~BundleActiveUsageDatabase()
67 {
68     RdbHelper::ClearCache();
69 }
70 
ChangeToDebug()71 void BundleActiveUsageDatabase::ChangeToDebug()
72 {
73     calendar_->ChangeToDebug();
74     debugDatabase_ = true;
75 }
76 
InitUsageGroupDatabase(const int32_t databaseType,const bool forModuleRecords)77 void BundleActiveUsageDatabase::InitUsageGroupDatabase(const int32_t databaseType, const bool forModuleRecords)
78 {
79     lock_guard<ffrt::mutex> lock(databaseMutex_);
80     if (CreateDatabasePath() == BUNDLE_ACTIVE_FAIL) {
81         BUNDLE_ACTIVE_LOGE("database path is not exist");
82         return;
83     }
84     if (databaseType != APP_GROUP_DATABASE_INDEX) {
85         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}d", databaseType);
86         return;
87     }
88     string queryDatabaseTableNames = "select * from sqlite_master where type = ?";
89     vector<string> queryCondition;
90     queryCondition.push_back(DATABASE_FILE_TABLE_NAME);
91     auto bundleActiveResult = QueryStatsInfoByStep(databaseType,
92         queryDatabaseTableNames, queryCondition);
93     if (bundleActiveResult == nullptr) {
94         BUNDLE_ACTIVE_LOGE("bundleActiveResult is invalid");
95         return;
96     }
97     int32_t tableNumber;
98     bundleActiveResult->GetRowCount(tableNumber);
99     if (tableNumber == TABLE_NOT_EXIST) {
100         BUNDLE_ACTIVE_LOGE("table not exist");
101         return;
102     }
103     int32_t tableNameIndex;
104     bundleActiveResult->GetColumnIndex(SQLITE_MASTER_NAME, tableNameIndex);
105     string tableName;
106     for (int32_t i = 0; i < tableNumber; i++) {
107         bundleActiveResult->GoToRow(i);
108         bundleActiveResult->GetString(tableNameIndex, tableName);
109         if (!forModuleRecords) {
110             if (DURATION_LOG_TABLE == tableName) {
111                 durationTableName_ = DURATION_LOG_TABLE;
112             } else if (BUNDLE_HISTORY_LOG_TABLE == tableName) {
113                 bundleHistoryTableName_ = BUNDLE_HISTORY_LOG_TABLE;
114             }
115         } else {
116             if (tableName.find(MODULE_RECORD_LOG_TABLE.c_str()) != tableName.npos) {
117                 moduleRecordsTableName_ = tableName;
118             } else if (tableName.find(FORM_RECORD_LOG_TABLE.c_str()) != tableName.npos) {
119                 formRecordsTableName_ = tableName;
120             }
121         }
122     }
123 }
124 
CreateDatabasePath()125 int32_t BundleActiveUsageDatabase::CreateDatabasePath()
126 {
127     if (access(BUNDLE_ACTIVE_DATABASE_DIR.c_str(), F_OK) != 0) {
128         int32_t createDir = mkdir(BUNDLE_ACTIVE_DATABASE_DIR.c_str(), S_IRWXU);
129         if (createDir != 0) {
130             BUNDLE_ACTIVE_LOGE("failed to create directory %{public}s", BUNDLE_ACTIVE_DATABASE_DIR.c_str());
131             return BUNDLE_ACTIVE_FAIL;
132         }
133     }
134     return BUNDLE_ACTIVE_SUCCESS;
135 }
136 
InitDatabaseTableInfo(int64_t currentTime)137 void BundleActiveUsageDatabase::InitDatabaseTableInfo(int64_t currentTime)
138 {
139     lock_guard<ffrt::mutex> lock(databaseMutex_);
140     if (CreateDatabasePath() == BUNDLE_ACTIVE_FAIL) {
141         BUNDLE_ACTIVE_LOGE("database path is not exist");
142         return;
143     }
144     CheckDatabaseVersion();
145     for (uint32_t i = 0; i < databaseFiles_.size(); i++) {
146         HandleTableInfo(i);
147         DeleteExcessiveTableData(i);
148     }
149     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
150         int32_t startIndex = NearIndexOnOrAfterCurrentTime(currentTime, sortedTableArray_.at(i));
151         if (startIndex < BUNDLE_ACTIVE_SUCCESS) {
152             continue;
153         }
154         int32_t tableNumber = static_cast<int32_t>(sortedTableArray_.at(i).size());
155         for (int32_t j = startIndex; j < tableNumber; j++) {
156             DeleteInvalidTable(i, sortedTableArray_.at(i).at(startIndex));
157             sortedTableArray_.at(i).erase(sortedTableArray_.at(i).begin() + startIndex);
158         }
159     }
160     if (eventTableName_ != UNKNOWN_TABLE_NAME) {
161         int64_t eventTableTime = ParseStartTime(eventTableName_);
162         if (currentTime < eventTableTime) {
163             DeleteInvalidTable(EVENT_DATABASE_INDEX, eventTableTime);
164         }
165     }
166 }
167 
NearIndexOnOrAfterCurrentTime(int64_t currentTime,vector<int64_t> & sortedTableArray)168 int32_t BundleActiveUsageDatabase::NearIndexOnOrAfterCurrentTime(int64_t currentTime,
169     vector<int64_t> &sortedTableArray)
170 {
171     int32_t low = 0;
172     int32_t high = static_cast<int32_t>(sortedTableArray.size() - 1);
173     int32_t mid = -1;
174     int64_t tableTime = -1;
175     int32_t divisor = 2;
176     while (low <= high) {
177         mid = (high + low) / divisor;
178         tableTime = sortedTableArray.at(mid);
179         if (currentTime > tableTime) {
180             low = mid + 1;
181         } else if (currentTime < tableTime) {
182             high = mid - 1;
183         } else {
184             return mid;
185         }
186     }
187     if (currentTime < tableTime) {
188         return mid;
189     } else if (currentTime > tableTime && low < static_cast<int32_t>(sortedTableArray.size())) {
190         return low;
191     } else {
192         return BUNDLE_ACTIVE_FAIL;
193     }
194 }
195 
NearIndexOnOrBeforeCurrentTime(int64_t currentTime,vector<int64_t> & sortedTableArray)196 int32_t BundleActiveUsageDatabase::NearIndexOnOrBeforeCurrentTime(int64_t currentTime,
197     vector<int64_t> &sortedTableArray)
198 {
199     int32_t index = NearIndexOnOrAfterCurrentTime(currentTime, sortedTableArray);
200     if (index < 0) {
201         return sortedTableArray.size() - 1;
202     }
203     if (sortedTableArray.at(index) == currentTime) {
204         return index;
205     }
206     return index - 1;
207 }
208 
QueryStatsInfoByStep(uint32_t databaseType,const string & sql,const vector<string> & selectionArgs)209 shared_ptr<NativeRdb::ResultSet> WEAK_FUNC BundleActiveUsageDatabase::QueryStatsInfoByStep(uint32_t databaseType,
210     const string &sql, const vector<string> &selectionArgs)
211 {
212     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
213     if (rdbStore == nullptr) {
214         BUNDLE_ACTIVE_LOGE("query stats info by step fail, rdbStore is nullptr");
215         return nullptr;
216     }
217     shared_ptr<NativeRdb::ResultSet> result;
218     if (selectionArgs.empty()) {
219         result = rdbStore->QueryByStep(sql);
220     } else {
221         result = rdbStore->QueryByStep(sql, selectionArgs);
222     }
223     return result;
224 }
225 
HandleTableInfo(uint32_t databaseType)226 void BundleActiveUsageDatabase::HandleTableInfo(uint32_t databaseType)
227 {
228     string queryDatabaseTableNames = "select * from sqlite_master where type = ?";
229     vector<string> queryCondition;
230     queryCondition.push_back(DATABASE_FILE_TABLE_NAME);
231     auto bundleActiveResult = QueryStatsInfoByStep(databaseType,
232         queryDatabaseTableNames, queryCondition);
233     if (bundleActiveResult == nullptr) {
234         BUNDLE_ACTIVE_LOGE("bundleActiveResult is invalid");
235         return;
236     }
237     int32_t tableNumber;
238     bundleActiveResult->GetRowCount(tableNumber);
239     if (tableNumber == TABLE_NOT_EXIST) {
240         BUNDLE_ACTIVE_LOGE("table not exist");
241         return;
242     }
243     int32_t tableNameIndex;
244     bundleActiveResult->GetColumnIndex(SQLITE_MASTER_NAME, tableNameIndex);
245     if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
246         if (!sortedTableArray_.at(databaseType).empty()) {
247             sortedTableArray_.at(databaseType).clear();
248         }
249         for (int32_t i = 0; i < tableNumber; i++) {
250             string tableName;
251             bundleActiveResult->GoToRow(i);
252             bundleActiveResult->GetString(tableNameIndex, tableName);
253             sortedTableArray_.at(databaseType).push_back(ParseStartTime(tableName));
254         }
255         if (!sortedTableArray_.at(databaseType).empty()) {
256             sort(sortedTableArray_.at(databaseType).begin(), sortedTableArray_.at(databaseType).end());
257         }
258         if ((databaseType == DAILY_DATABASE_INDEX) && !sortedTableArray_.at(databaseType).empty()) {
259             size_t lastTableIndex = sortedTableArray_.at(databaseType).size();
260             if (lastTableIndex == 0) {
261                 return;
262             }
263             eventBeginTime_ = sortedTableArray_.at(databaseType).at(lastTableIndex -1);
264         }
265     } else if (databaseType == EVENT_DATABASE_INDEX) {
266         if (tableNumber == EVENT_TABLE_NUMBER) {
267             bundleActiveResult->GoToRow(tableNumber - EVENT_TABLE_NUMBER);
268             bundleActiveResult->GetString(tableNameIndex, eventTableName_);
269         }
270     }
271 }
272 
HandleAllTableName(const uint32_t databaseType,std::vector<std::vector<std::string>> & allTableName)273 void BundleActiveUsageDatabase::HandleAllTableName(const uint32_t databaseType,
274     std::vector<std::vector<std::string>>& allTableName)
275 {
276     string queryDatabaseTableNames = "select * from sqlite_master where type = ?";
277     vector<string> queryCondition;
278     queryCondition.push_back(DATABASE_FILE_TABLE_NAME);
279     auto bundleActiveResult = QueryStatsInfoByStep(databaseType,
280         queryDatabaseTableNames, queryCondition);
281     if (bundleActiveResult == nullptr) {
282         BUNDLE_ACTIVE_LOGE("bundleActiveResult is invalid");
283         return;
284     }
285     int32_t tableNumber;
286     bundleActiveResult->GetRowCount(tableNumber);
287     if (tableNumber == TABLE_NOT_EXIST) {
288         BUNDLE_ACTIVE_LOGE("table not exist");
289         return;
290     }
291     int32_t tableNameIndex;
292     bundleActiveResult->GetColumnIndex(SQLITE_MASTER_NAME, tableNameIndex);
293     for (int32_t i = 0; i < tableNumber; i++) {
294         string tableName;
295         bundleActiveResult->GoToRow(i);
296         bundleActiveResult->GetString(tableNameIndex, tableName);
297         allTableName.at(databaseType).push_back(tableName);
298     }
299 }
300 
DeleteExcessiveTableData(uint32_t databaseType)301 void BundleActiveUsageDatabase::DeleteExcessiveTableData(uint32_t databaseType)
302 {
303     if (databaseType >= 0 && databaseType < SORTED_TABLE_ARRAY_NUMBER) {
304         if (sortedTableArray_.at(databaseType).empty()) {
305             BUNDLE_ACTIVE_LOGE("database table not exist");
306             return;
307         }
308         int32_t existingNumber = static_cast<int32_t>(sortedTableArray_.at(databaseType).size());
309         int32_t deleteNumber = existingNumber - MAX_FILES_EVERY_INTERVAL_TYPE[databaseType];
310         if (deleteNumber > 0) {
311             for (int32_t i = 0; i < deleteNumber; i++) {
312                 // 删除多余文件
313                 DeleteInvalidTable(databaseType, sortedTableArray_.at(databaseType).at(0));
314                 sortedTableArray_.at(databaseType).erase(sortedTableArray_.at(databaseType).begin());
315             }
316             BUNDLE_ACTIVE_LOGD("BundleActiveUsageDatabase DeleteExcessiveTableData Deleted %{public}d tables from "
317                 "database type %{public}d", deleteNumber, databaseType);
318         }
319     } else if (databaseType == EVENT_DATABASE_INDEX) {
320         // 删除多余数据
321         if ((eventTableName_ == UNKNOWN_TABLE_NAME) || (eventBeginTime_ == EVENT_BEGIN_TIME_INITIAL_VALUE)) {
322             return;
323         }
324         int64_t eventTableTime = ParseStartTime(eventTableName_);
325         int64_t deleteTimePoint = 0;
326         if (debugDatabase_) {
327             deleteTimePoint = eventBeginTime_ - SIX_DAY_IN_MILLIS_MAX_DEBUG - eventTableTime;
328         } else {
329             deleteTimePoint = eventBeginTime_ - SIX_DAY_IN_MILLIS_MAX - eventTableTime;
330         }
331         if (deleteTimePoint <= 0) {
332             return;
333         }
334         shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
335         if (rdbStore == nullptr) {
336             BUNDLE_ACTIVE_LOGE("delete excessive tableData fail, rdbStore is nullptr");
337             return;
338         }
339         string deleteEventDataSql = "delete from " + eventTableName_ + " where timeStamp <= " +
340             to_string(deleteTimePoint);
341         int32_t deleteResult = rdbStore->ExecuteSql(deleteEventDataSql);
342         if (deleteResult != NativeRdb::E_OK) {
343             BUNDLE_ACTIVE_LOGE("delete event data failed, rdb error number: %{public}d", deleteResult);
344         }
345     } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
346         // 无数据删除
347     } else {
348         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}u", databaseType);
349     }
350 }
351 
GetOverdueTableCreateTime(uint32_t databaseType,int64_t currentTimeMillis)352 std::unique_ptr<std::vector<int64_t>> BundleActiveUsageDatabase::GetOverdueTableCreateTime(uint32_t databaseType,
353     int64_t currentTimeMillis)
354 {
355     std::unique_ptr<std::vector<int64_t>> overdueTableCreateTime = std::make_unique<std::vector<int64_t>>();
356     if (databaseType >= sortedTableArray_.size()) {
357         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}u", databaseType);
358         return nullptr;
359     }
360     string queryDatabaseTableNames = "select * from sqlite_master where type = ?";
361     vector<string> queryCondition;
362     queryCondition.push_back(DATABASE_FILE_TABLE_NAME);
363     auto bundleActiveResult = QueryStatsInfoByStep(databaseType,
364         queryDatabaseTableNames, queryCondition);
365     if (bundleActiveResult == nullptr) {
366         BUNDLE_ACTIVE_LOGE("bundleActiveResult is invalid");
367         return nullptr;
368     }
369     int32_t tableNumber;
370     bundleActiveResult->GetRowCount(tableNumber);
371     if (tableNumber == 0) {
372         BUNDLE_ACTIVE_LOGE("table does not exist");
373         return nullptr;
374     }
375     int32_t tableNameIndex;
376     bundleActiveResult->GetColumnIndex(SQLITE_MASTER_NAME, tableNameIndex);
377     string tableName;
378     for (int32_t i = 0; i < tableNumber; i++) {
379         bundleActiveResult->GoToRow(i);
380         bundleActiveResult->GetString(tableNameIndex, tableName);
381         if (ParseStartTime(tableName) < currentTimeMillis) {
382             overdueTableCreateTime->push_back(ParseStartTime(tableName));
383         }
384     }
385     return overdueTableCreateTime;
386 }
387 
DeleteInvalidTable(uint32_t databaseType,int64_t tableTimeMillis)388 int32_t BundleActiveUsageDatabase::DeleteInvalidTable(uint32_t databaseType, int64_t tableTimeMillis)
389 {
390     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
391     if (rdbStore == nullptr) {
392         BUNDLE_ACTIVE_LOGE("delete invalid table fail, rdbStore is nullptr");
393         return BUNDLE_ACTIVE_FAIL;
394     }
395     if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
396         string packageTable = PACKAGE_LOG_TABLE + to_string(tableTimeMillis);
397         string deletePackageTableSql = "drop table " + packageTable;
398         int32_t deletePackageTable = rdbStore->ExecuteSql(deletePackageTableSql);
399         if (deletePackageTable != NativeRdb::E_OK) {
400             BUNDLE_ACTIVE_LOGE("delete package table failed, rdb error number: %{public}d", deletePackageTable);
401             return BUNDLE_ACTIVE_FAIL;
402         }
403     } else if (databaseType == EVENT_DATABASE_INDEX) {
404         string eventTable = EVENT_LOG_TABLE + to_string(tableTimeMillis);
405         string deleteEventTableSql = "drop table " + eventTable;
406         int32_t deleteEventTable = rdbStore->ExecuteSql(deleteEventTableSql);
407         if (deleteEventTable != NativeRdb::E_OK) {
408             BUNDLE_ACTIVE_LOGE("delete event table failed, rdb error number: %{public}d", deleteEventTable);
409             return BUNDLE_ACTIVE_FAIL;
410         }
411     } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
412     }
413     return BUNDLE_ACTIVE_SUCCESS;
414 }
415 
ParseStartTime(const string & tableName)416 int64_t BundleActiveUsageDatabase::ParseStartTime(const string &tableName)
417 {
418     if (tableName.empty()) {
419         int64_t invalidStartTime(BUNDLE_ACTIVE_FAIL);
420         return invalidStartTime;
421     }
422     string tableTime = tableName;
423     if (tableTime.length() > BUNDLE_ACTIVE_DB_NAME_MAX_LENGTH) {
424         int64_t invalidStartTime(BUNDLE_ACTIVE_FAIL);
425         return invalidStartTime;
426     }
427     for (uint32_t i = 0; i < tableTime.length(); i++) {
428         if (tableTime[i] >= '0' && tableTime[i] <= '9') {
429             tableTime = tableTime.substr(i);
430             break;
431         }
432     }
433     return atoll(tableTime.c_str());
434 }
435 
CheckDatabaseVersion()436 void BundleActiveUsageDatabase::CheckDatabaseVersion()
437 {
438     if (access(BUNDLE_ACTIVE_DATABASE_DIR.c_str(), F_OK) == 0) {
439         int32_t oldVersion = GetOldDbVersion();
440         if (oldVersion != BUNDLE_ACTIVE_FAIL && oldVersion < BUNDLE_ACTIVE_CURRENT_VERSION) {
441             UpgradleDatabase(oldVersion, BUNDLE_ACTIVE_CURRENT_VERSION);
442         }
443         ofstream openVersionFile;
444         openVersionFile.open(BUNDLE_ACTIVE_VERSION_DIRECTORY_PATH, ios::out);
445         if (openVersionFile) {
446             openVersionFile << "version : " << BUNDLE_ACTIVE_CURRENT_VERSION;
447         }
448         openVersionFile.close();
449     }
450 }
451 
GetOldDbVersion()452 int32_t BundleActiveUsageDatabase::GetOldDbVersion()
453 {
454     int32_t oldVersion = -1;
455     if (access(BUNDLE_ACTIVE_DATABASE_DIR.c_str(), F_OK) == 0) {
456         ifstream openVersionFile;
457         openVersionFile.open(BUNDLE_ACTIVE_VERSION_DIRECTORY_PATH, ios::in);
458         if (openVersionFile) {
459             char str[FILE_VERSION_LINE_NUM] = {0};
460             openVersionFile.getline(str, FILE_VERSION_LINE_NUM);
461             oldVersion = GetVersionByFileInput(str);
462         }
463         openVersionFile.close();
464     }
465     return oldVersion;
466 }
467 
GetVersionByFileInput(const std::string & FileVersionInput)468 int32_t BundleActiveUsageDatabase::GetVersionByFileInput(const std::string& FileVersionInput)
469 {
470     if (FileVersionInput.empty()) {
471         return BUNDLE_ACTIVE_FAIL;
472     }
473     string databaseVersion = FileVersionInput;
474     for (uint32_t i = 0; i < databaseVersion.length(); i++) {
475         if (databaseVersion[i] >= '0' && databaseVersion[i] <= '9') {
476             databaseVersion = databaseVersion.substr(i);
477             break;
478         }
479     }
480     return atoi(databaseVersion.c_str());
481 }
482 
UpgradleDatabase(const int32_t oldVersion,const int32_t curVersion)483 void BundleActiveUsageDatabase::UpgradleDatabase(const int32_t oldVersion, const int32_t curVersion)
484 {
485     BUNDLE_ACTIVE_LOGI("upgradle database oldVersion: %{public}d, curVersion: %{public}d", oldVersion, curVersion);
486     if (oldVersion < curVersion && curVersion == BUNDLE_ACTIVE_CURRENT_VERSION) {
487         if (oldVersion == BUNDLE_ACTIVE_VERSION_V1) {
488             SupportAppTwin();
489         }
490     }
491 }
492 
SupportAppTwin()493 void BundleActiveUsageDatabase::SupportAppTwin()
494 {
495     vector<vector<string>> allTableName = vector<vector<string>>(ALL_TABLE_ARRAY_NUMBER);
496     for (uint32_t i = 0; i <databaseFiles_.size(); i++) {
497         HandleAllTableName(i, allTableName);
498     }
499 
500     map<string, int32_t> bundleNameUidMap;
501     vector<int32_t> activatedOsAccountIds;
502     BundleActiveAccountHelper::GetActiveUserId(activatedOsAccountIds);
503     for (uint32_t i = 0; i < allTableName.size(); i++) {
504         auto tableNames = allTableName.at(i);
505         shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(i);
506         if (!rdbStore) {
507             BUNDLE_ACTIVE_LOGI("get RdbStore fail, databaseType: %{public}u", i);
508             continue;
509         }
510         for (string tableName: tableNames) {
511             if (DURATION_LOG_TABLE == tableName) {
512                 continue;
513             }
514             AddRdbColumn(rdbStore, tableName, BUNDLE_ACTIVE_DB_UID, RDB_STORE_COLUMN_TYPE_INT);
515             for (auto userId: activatedOsAccountIds) {
516                 UpdateOldDataUid(rdbStore, tableName, userId, bundleNameUidMap);
517             }
518         }
519     }
520 }
521 
AddRdbColumn(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const string & columnName,const string & columnType)522 void BundleActiveUsageDatabase::AddRdbColumn(const shared_ptr<NativeRdb::RdbStore> store,
523     const string& tableName, const string& columnName, const string& columnType)
524 {
525     string sqlStr = "";
526     if (columnType == RDB_STORE_COLUMN_TYPE_INT) {
527         sqlStr = "ALTER TABLE " + tableName + " ADD " + columnName + " " + columnType + " NOT NULL DEFAULT -1";
528     }
529     store->ExecuteSql(sqlStr);
530 }
531 
UpdateOldDataUid(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const int32_t userId,map<string,int32_t> & bundleNameUidMap)532 void BundleActiveUsageDatabase::UpdateOldDataUid(const shared_ptr<NativeRdb::RdbStore> store,
533     const string& tableName, const int32_t userId, map<string, int32_t>& bundleNameUidMap)
534 {
535     vector<string> queryCondition;
536     string querySql = "select * from " + tableName;
537     shared_ptr<NativeRdb::ResultSet> bundleActiveResult;
538     bundleActiveResult = store->QueryByStep(querySql);
539     int32_t tableRowNumber = 0;
540     bundleActiveResult->GetRowCount(tableRowNumber);
541     string bundleName;
542     int32_t uid;
543     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
544     NativeRdb::ValuesBucket valuesBucket;
545     for (int32_t i = 0; i < tableRowNumber; i++) {
546         bundleActiveResult->GoToRow(i);
547         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, bundleName);
548         AppExecFwk::ApplicationInfo appInfo;
549         string bundleNameUserIdKey = bundleName + to_string(userId);
550         auto it = bundleNameUidMap.find(bundleNameUserIdKey);
551         if (it == bundleNameUidMap.end()) {
552             BundleActiveBundleMgrHelper::GetInstance()->GetApplicationInfo(bundleName,
553                 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, appInfo);
554             uid = appInfo.uid;
555             bundleNameUidMap[bundleNameUserIdKey] = uid;
556         } else {
557             uid = it->second;
558         }
559         queryCondition.push_back(to_string(userId));
560         queryCondition.push_back(bundleName);
561         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, uid);
562         store->Update(changeRow, tableName, valuesBucket, "userId = ? and bundleName = ?", queryCondition);
563         queryCondition.clear();
564         valuesBucket.Clear();
565         changeRow = BUNDLE_ACTIVE_FAIL;
566     }
567 }
568 
GetBundleActiveRdbStore(uint32_t databaseType)569 shared_ptr<NativeRdb::RdbStore> WEAK_FUNC BundleActiveUsageDatabase::GetBundleActiveRdbStore(uint32_t databaseType)
570 {
571     shared_ptr<NativeRdb::RdbStore> rdbStore;
572     string file = databaseFiles_.at(databaseType);
573     if (bundleActiveRdbStoreCache_.find(file) == bundleActiveRdbStoreCache_.end()) {
574         int32_t errCode(BUNDLE_ACTIVE_FAIL);
575         string currDatabaseFileConfig = BUNDLE_ACTIVE_DATABASE_DIR + databaseFiles_.at(databaseType);
576         RdbStoreConfig config(currDatabaseFileConfig);
577         BundleActiveOpenCallback rdbDataCallBack;
578         config.SetJournalMode(NativeRdb::JournalMode::MODE_OFF);
579         config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
580         rdbStore = RdbHelper::GetRdbStore(config, BUNDLE_ACTIVE_RDB_VERSION, rdbDataCallBack, errCode);
581         if ((rdbStore == nullptr)) {
582             config.SetJournalMode(NativeRdb::JournalMode::MODE_WAL);
583             rdbStore = RdbHelper::GetRdbStore(config, BUNDLE_ACTIVE_RDB_VERSION_V2, rdbDataCallBack, errCode);
584             if (rdbStore == nullptr) {
585                 BUNDLE_ACTIVE_LOGE("get bundle active rdbStore fail, rdbStore is nullptr");
586                 return nullptr;
587             }
588         }
589         bundleActiveRdbStoreCache_.insert(pair {file, rdbStore});
590     } else {
591         rdbStore = bundleActiveRdbStoreCache_[file];
592     }
593     if (rdbStore == nullptr) {
594         BUNDLE_ACTIVE_LOGE("get bundle active rdbStore fail, rdbStore is nullptr");
595         return nullptr;
596     }
597     int version = 0;
598     rdbStore->GetVersion(version);
599     if (version == BUNDLE_ACTIVE_RDB_VERSION_V2) {
600         return rdbStore;
601     }
602     auto[createResult, test] = rdbStore->Execute("PRAGMA journal_mode = WAL;");
603     if (createResult != NativeRdb::E_OK) {
604         BUNDLE_ACTIVE_LOGE("PRAGMA journal_mode createResult is fail, rdb error: %{public}d", createResult);
605     }
606     return rdbStore;
607 }
608 
CheckDatabaseFile(uint32_t databaseType)609 void BundleActiveUsageDatabase::CheckDatabaseFile(uint32_t databaseType)
610 {
611     std::string databaseFileName = databaseFiles_.at(databaseType);
612     for (uint32_t i = 0; i < sizeof(SUFFIX_TYPE) / sizeof(SUFFIX_TYPE[0]); i++) {
613         std::string dbFile = BUNDLE_ACTIVE_DATABASE_DIR + DATABASE_TYPE[databaseType] + SUFFIX_TYPE[i];
614         if ((access(dbFile.c_str(), F_OK) != 0)
615             && (bundleActiveRdbStoreCache_.find(databaseFileName) != bundleActiveRdbStoreCache_.end())) {
616             bundleActiveRdbStoreCache_.erase(databaseFileName);
617             std::string rdbStorePath = BUNDLE_ACTIVE_DATABASE_DIR + DATABASE_TYPE[databaseType] + SUFFIX_TYPE[0];
618             RdbHelper::DeleteRdbStore(rdbStorePath);
619             if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
620                 sortedTableArray_.at(databaseType).clear();
621             } else if (databaseType == EVENT_DATABASE_INDEX) {
622                 eventTableName_ = UNKNOWN_TABLE_NAME;
623             } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
624                 durationTableName_ = UNKNOWN_TABLE_NAME;
625                 bundleHistoryTableName_ = UNKNOWN_TABLE_NAME;
626                 moduleRecordsTableName_ = UNKNOWN_TABLE_NAME;
627                 formRecordsTableName_ = UNKNOWN_TABLE_NAME;
628             }
629             return;
630         }
631     }
632 }
633 
CreateEventLogTable(uint32_t databaseType,int64_t currentTimeMillis)634 int32_t BundleActiveUsageDatabase::CreateEventLogTable(uint32_t databaseType, int64_t currentTimeMillis)
635 {
636     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
637     if (rdbStore == nullptr) {
638         BUNDLE_ACTIVE_LOGE(" create event log table faile, rdbStore is nullptr");
639         return BUNDLE_ACTIVE_FAIL;
640     }
641     string eventTable = EVENT_LOG_TABLE + to_string(currentTimeMillis);
642     eventTableName_ = eventTable;
643     const string createEventTableSql = "CREATE TABLE IF NOT EXISTS "
644                                            + eventTable
645                                            + " ("
646                                            + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
647                                            + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
648                                            + BUNDLE_ACTIVE_DB_EVENT_ID + " INTEGER NOT NULL, "
649                                            + BUNDLE_ACTIVE_DB_TIME_STAMP + " INTEGER NOT NULL, "
650                                            + BUNDLE_ACTIVE_DB_ABILITY_ID + " TEXT NOT NULL, "
651                                            + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
652     int32_t createEventTable = rdbStore->ExecuteSql(createEventTableSql);
653     if (createEventTable != NativeRdb::E_OK) {
654         BUNDLE_ACTIVE_LOGE("create event table failed, rdb error number: %{public}d", createEventTable);
655         return createEventTable;
656     }
657     string createEventTableIndex = GetTableIndexSql(EVENT_DATABASE_INDEX, currentTimeMillis, true);
658     int32_t createResult = rdbStore->ExecuteSql(createEventTableIndex);
659     if (createResult != NativeRdb::E_OK) {
660         BUNDLE_ACTIVE_LOGE("create event table index failed, rdb error number: %{public}d", createResult);
661         return BUNDLE_ACTIVE_FAIL;
662     }
663     return BUNDLE_ACTIVE_SUCCESS;
664 }
665 
CreatePackageLogTable(uint32_t databaseType,int64_t currentTimeMillis)666 int32_t BundleActiveUsageDatabase::CreatePackageLogTable(uint32_t databaseType, int64_t currentTimeMillis)
667 {
668     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
669     if (rdbStore == nullptr) {
670         BUNDLE_ACTIVE_LOGE(" create package log table fail, rdbStore is nullptr");
671         return BUNDLE_ACTIVE_FAIL;
672     }
673     string packageTable = PACKAGE_LOG_TABLE + to_string(currentTimeMillis);
674     string createPackageTableSql = "CREATE TABLE IF NOT EXISTS "
675                                         + packageTable
676                                         + " ("
677                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
678                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
679                                         + BUNDLE_ACTIVE_DB_BUNDLE_STARTED_COUNT + " INTEGER NOT NULL, "
680                                         + BUNDLE_ACTIVE_DB_LAST_TIME + " INTEGER NOT NULL, "
681                                         + BUNDLE_ACTIVE_DB_LAST_TIME_CONTINUOUS_TASK + " INTEGER NOT NULL, "
682                                         + BUNDLE_ACTIVE_DB_TOTAL_TIME + " INTEGER NOT NULL, "
683                                         + BUNDLE_ACTIVE_DB_TOTAL_TIME_CONTINUOUS_TASK + " INTEGER NOT NULL, "
684                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
685     int32_t createPackageTable = rdbStore->ExecuteSql(createPackageTableSql);
686     if (createPackageTable != NativeRdb::E_OK) {
687         BUNDLE_ACTIVE_LOGE("create packageLog table failed, rdb error number: %{public}d", createPackageTable);
688         return BUNDLE_ACTIVE_FAIL;
689     }
690     string createPackageTableIndex = GetTableIndexSql(databaseType, currentTimeMillis, true);
691     int32_t createResult = rdbStore->ExecuteSql(createPackageTableIndex);
692     if (createResult != NativeRdb::E_OK) {
693         BUNDLE_ACTIVE_LOGE("create package table index failed, rdb error number: %{public}d", createResult);
694         return BUNDLE_ACTIVE_FAIL;
695     }
696     return BUNDLE_ACTIVE_SUCCESS;
697 }
698 
CreateModuleRecordTable(uint32_t databaseType,int64_t timeStamp)699 int32_t BundleActiveUsageDatabase::CreateModuleRecordTable(uint32_t databaseType, int64_t timeStamp)
700 {
701     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
702     if (rdbStore == nullptr) {
703         BUNDLE_ACTIVE_LOGE("create module record table fail, rdbStore is nullptr");
704         return BUNDLE_ACTIVE_FAIL;
705     }
706     string moduleRecord = MODULE_RECORD_LOG_TABLE + to_string(timeStamp);
707     moduleRecordsTableName_ = moduleRecord;
708     string createModuleRecordTableSql = "CREATE TABLE IF NOT EXISTS "
709                                         + moduleRecord
710                                         + " ("
711                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
712                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
713                                         + BUNDLE_ACTIVE_DB_MODULE_NAME + " TEXT NOT NULL, "
714                                         + BUNDLE_ACTIVE_DB_MODULE_LAUNCHED_COUNT + " INTEGER NOT NULL, "
715                                         + BUNDLE_ACTIVE_DB_LAST_TIME + " INTEGER NOT NULL, "
716                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
717     int32_t createModuleRecordTable = rdbStore->ExecuteSql(createModuleRecordTableSql);
718     if (createModuleRecordTable != NativeRdb::E_OK) {
719         BUNDLE_ACTIVE_LOGE("create ModuleRecord table failed, rdb error number: %{public}d", createModuleRecordTable);
720         return BUNDLE_ACTIVE_FAIL;
721     }
722     string createModuleTableIndex = GetTableIndexSql(databaseType, timeStamp, true, BUNDLE_ACTIVE_DB_INDEX_MODULE);
723     int32_t createResult = rdbStore->ExecuteSql(createModuleTableIndex);
724     if (createResult != NativeRdb::E_OK) {
725         BUNDLE_ACTIVE_LOGE("create module table index failed, rdb error number: %{public}d", createResult);
726         return BUNDLE_ACTIVE_FAIL;
727     }
728     return BUNDLE_ACTIVE_SUCCESS;
729 }
730 
CreateFormRecordTable(uint32_t databaseType,int64_t timeStamp)731 int32_t BundleActiveUsageDatabase::CreateFormRecordTable(uint32_t databaseType, int64_t timeStamp)
732 {
733     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
734     if (rdbStore == nullptr) {
735         BUNDLE_ACTIVE_LOGE("create form record table fail, rdbStore is nullptr");
736         return BUNDLE_ACTIVE_FAIL;
737     }
738     string formRecord = FORM_RECORD_LOG_TABLE + to_string(timeStamp);
739     formRecordsTableName_ = formRecord;
740     string createFormRecordTableSql = "CREATE TABLE IF NOT EXISTS "
741                                         + formRecord
742                                         + " ("
743                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
744                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
745                                         + BUNDLE_ACTIVE_DB_MODULE_NAME + " TEXT NOT NULL, "
746                                         + BUNDLE_ACTIVE_DB_FORM_NAME + " TEXT NOT NULL, "
747                                         + BUNDLE_ACTIVE_DB_FORM_DIMENSION + " INTEGER NOT NULL, "
748                                         + BUNDLE_ACTIVE_DB_FORM_ID + " INTEGER NOT NULL, "
749                                         + BUNDLE_ACTIVE_DB_FORM_TOUCH_COUNT + " INTEGER NOT NULL, "
750                                         + BUNDLE_ACTIVE_DB_LAST_TIME + " INTEGER NOT NULL, "
751                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
752     int32_t createFormRecordTable = rdbStore->ExecuteSql(createFormRecordTableSql);
753     if (createFormRecordTable != NativeRdb::E_OK) {
754         BUNDLE_ACTIVE_LOGE("create ModuleRecord table failed, rdb error number: %{public}d", createFormRecordTable);
755         return BUNDLE_ACTIVE_FAIL;
756     }
757     string createFormTableIndex = GetTableIndexSql(databaseType, timeStamp, true, BUNDLE_ACTIVE_DB_INDEX_FORM);
758     int32_t createResult = rdbStore->ExecuteSql(createFormTableIndex);
759     if (createResult != NativeRdb::E_OK) {
760         BUNDLE_ACTIVE_LOGE("create module table index failed, rdb error number: %{public}d", createResult);
761         return BUNDLE_ACTIVE_FAIL;
762     }
763     return BUNDLE_ACTIVE_SUCCESS;
764 }
765 
CreateDurationTable(uint32_t databaseType)766 int32_t BundleActiveUsageDatabase::CreateDurationTable(uint32_t databaseType)
767 {
768     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
769     if (rdbStore == nullptr) {
770         BUNDLE_ACTIVE_LOGE("create duration table fail, rdbStore is nullptr");
771         return BUNDLE_ACTIVE_FAIL;
772     }
773     string createDurationTableSql = "CREATE TABLE IF NOT EXISTS "
774                                         + DURATION_LOG_TABLE
775                                         + " ("
776                                         + BUNDLE_ACTIVE_DB_BOOT_BASED_DURATION + " INTEGER NOT NULL, "
777                                         + BUNDLE_ACTIVE_DB_SCREEN_ON_DURATION + " INTEGER NOT NULL);";
778     int32_t createDurationTable = rdbStore->ExecuteSql(createDurationTableSql);
779     if (createDurationTable != NativeRdb::E_OK) {
780         BUNDLE_ACTIVE_LOGE("create duration table failed, rdb error number: %{public}d", createDurationTable);
781         return BUNDLE_ACTIVE_FAIL;
782     }
783     return BUNDLE_ACTIVE_SUCCESS;
784 }
785 
CreateBundleHistoryTable(uint32_t databaseType)786 int32_t BundleActiveUsageDatabase::CreateBundleHistoryTable(uint32_t databaseType)
787 {
788     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
789     if (rdbStore == nullptr) {
790         BUNDLE_ACTIVE_LOGE("create bundle history table fail, rdbStore is nullptr");
791         return BUNDLE_ACTIVE_FAIL;
792     }
793     string createBundleHistoryTableSql = "CREATE TABLE IF NOT EXISTS "
794                                         + BUNDLE_HISTORY_LOG_TABLE
795                                         + " ("
796                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
797                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
798                                         + BUNDLE_ACTIVE_DB_LAST_BOOT_FROM_USED_TIME + " INTEGER NOT NULL, "
799                                         + BUNDLE_ACTIVE_DB_LAST_SCREEN_USED_TIME + " INTEGER NOT NULL, "
800                                         + BUNDLE_ACTIVE_DB_CURRENT_GROUP + " INTEGER NOT NULL, "
801                                         + BUNDLE_ACTIVE_DB_REASON_IN_GROUP + " INTEGER NOT NULL, "
802                                         + BUNDLE_ACTIVE_DB_BUNDLE_ALIVE_TIMEOUT_TIME + " INTEGER NOT NULL, "
803                                         + BUNDLE_ACTIVE_DB_BUNDLE_DAILY_TIMEOUT_TIME + " INTEGER NOT NULL, "
804                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
805     int32_t createBundleHistoryTable = rdbStore->ExecuteSql(createBundleHistoryTableSql);
806     if (createBundleHistoryTable != NativeRdb::E_OK) {
807         BUNDLE_ACTIVE_LOGE("create bundleHistory table failed, rdb error number: %{public}d", createBundleHistoryTable);
808         return createBundleHistoryTable;
809     }
810     int32_t time = 0;
811     string createBundleHistoryTableIndex = GetTableIndexSql(databaseType, time, true);
812     int32_t createResult = rdbStore->ExecuteSql(createBundleHistoryTableIndex);
813     if (createResult != NativeRdb::E_OK) {
814         BUNDLE_ACTIVE_LOGE("create bundleHistory table index failed, rdb error number: %{public}d", createResult);
815         return BUNDLE_ACTIVE_FAIL;
816     }
817     return BUNDLE_ACTIVE_SUCCESS;
818 }
819 
BatchInsert(std::shared_ptr<NativeRdb::RdbStore> rdbStore,std::vector<NativeRdb::ValuesBucket> & rawContactValues,const std::string & tableName)820 void BundleActiveUsageDatabase::BatchInsert(std::shared_ptr<NativeRdb::RdbStore> rdbStore,
821     std::vector<NativeRdb::ValuesBucket>& rawContactValues, const std::string& tableName)
822 {
823     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
824     if (rawContactValues.size() != 0) {
825         rdbStore->BatchInsert(outRowId, tableName, rawContactValues);
826     }
827 }
828 
PutBundleHistoryData(int32_t userId,shared_ptr<map<string,shared_ptr<BundleActivePackageHistory>>> userHistory)829 void BundleActiveUsageDatabase::PutBundleHistoryData(int32_t userId,
830     shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> userHistory)
831 {
832     lock_guard<ffrt::mutex> lock(databaseMutex_);
833     if (userHistory == nullptr) {
834         return;
835     }
836     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
837     if (userHistory == nullptr || rdbStore == nullptr) {
838         return;
839     }
840     CheckDatabaseFileAndTable();
841     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
842     std::vector<NativeRdb::ValuesBucket> valuesBuckets;
843     vector<string> queryCondition;
844     int32_t updatedcount = 0;
845     int32_t unupdatedcount = 0;
846     for (auto iter = userHistory->begin(); iter != userHistory->end(); iter++) {
847         if (iter->second == nullptr || !iter->second->isChanged_) {
848             unupdatedcount++;
849             continue;
850         }
851         NativeRdb::ValuesBucket valuesBucket;
852         queryCondition.push_back(to_string(userId));
853         queryCondition.push_back(iter->second->bundleName_);
854         queryCondition.push_back(to_string(iter->second->uid_));
855         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_BOOT_FROM_USED_TIME, iter->second->lastBootFromUsedTimeStamp_);
856         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_SCREEN_USED_TIME, iter->second->lastScreenUsedTimeStamp_);
857         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_CURRENT_GROUP, iter->second->currentGroup_);
858         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_REASON_IN_GROUP, static_cast<int32_t>(iter->second->reasonInGroup_));
859         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BUNDLE_ALIVE_TIMEOUT_TIME, iter->second->bundleAliveTimeoutTimeStamp_);
860         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BUNDLE_DAILY_TIMEOUT_TIME, iter->second->bundleDailyTimeoutTimeStamp_);
861         rdbStore->Update(changeRow, BUNDLE_HISTORY_LOG_TABLE, valuesBucket,
862             "userId = ? and bundleName = ? and uid = ?", queryCondition);
863         if (changeRow == NO_UPDATE_ROW) {
864             valuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, iter->second->bundleName_);
865             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, userId);
866             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, iter->second->uid_);
867             valuesBuckets.push_back(valuesBucket);
868         } else {
869             changeRow = BUNDLE_ACTIVE_FAIL;
870         }
871         queryCondition.clear();
872         iter->second->isChanged_ = false;
873         updatedcount++;
874     }
875     BatchInsert(rdbStore, valuesBuckets, BUNDLE_HISTORY_LOG_TABLE);
876     BUNDLE_ACTIVE_LOGI("update %{public}d bundles, keep %{public}d bundles group", updatedcount, unupdatedcount);
877 }
878 
CheckDatabaseFileAndTable()879 void BundleActiveUsageDatabase::CheckDatabaseFileAndTable()
880 {
881     CheckDatabaseFile(APP_GROUP_DATABASE_INDEX);
882     if (bundleHistoryTableName_ == UNKNOWN_TABLE_NAME) {
883         CreateBundleHistoryTable(APP_GROUP_DATABASE_INDEX);
884         bundleHistoryTableName_ = BUNDLE_HISTORY_LOG_TABLE;
885     }
886 }
887 
GetBundleHistoryData(int32_t userId)888 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> BundleActiveUsageDatabase::GetBundleHistoryData(
889     int32_t userId)
890 {
891     lock_guard<ffrt::mutex> lock(databaseMutex_);
892     if (bundleHistoryTableName_ == UNKNOWN_TABLE_NAME) {
893         return nullptr;
894     }
895     string queryHistoryDataSql = "select * from " + BUNDLE_HISTORY_LOG_TABLE + " where userId = ?";
896     vector<string> queryCondition;
897     queryCondition.push_back(to_string(userId));
898     auto bundleActiveResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX,
899         queryHistoryDataSql, queryCondition);
900     if (bundleActiveResult == nullptr) {
901         return nullptr;
902     }
903     int32_t tableRowNumber;
904     bundleActiveResult->GetRowCount(tableRowNumber);
905     if (tableRowNumber == TABLE_ROW_ZERO) {
906         return nullptr;
907     }
908     shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> userUsageHistory =
909         make_shared<map<string, shared_ptr<BundleActivePackageHistory>>>();
910     int32_t currentBundleGroupReason = 0;
911     for (int32_t i = 0; i < tableRowNumber; i++) {
912         bundleActiveResult->GoToRow(i);
913         shared_ptr<BundleActivePackageHistory> usageHistory = make_shared<BundleActivePackageHistory>();
914         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, usageHistory->bundleName_);
915         bundleActiveResult->GetLong(LAST_BOOT_FROM_USED_TIME_COLUMN_INDEX, usageHistory->lastBootFromUsedTimeStamp_);
916         bundleActiveResult->GetLong(LAST_SCREEN_USED_TIME_COLUMN_INDEX, usageHistory->lastScreenUsedTimeStamp_);
917         bundleActiveResult->GetInt(CURRENT_GROUP_COLUMN_INDEX, usageHistory->currentGroup_);
918         bundleActiveResult->GetInt(REASON_IN_GROUP_COLUMN_INDEX, currentBundleGroupReason);
919         usageHistory->reasonInGroup_ = static_cast<uint32_t>(currentBundleGroupReason);
920         bundleActiveResult->GetLong(BUNDLE_ALIVE_TIMEOUT_TIME_COLUMN_INDEX,
921             usageHistory->bundleAliveTimeoutTimeStamp_);
922         bundleActiveResult->GetLong(BUNDLE_DAILY_TIMEOUT_TIME_COLUMN_INDEX,
923             usageHistory->bundleDailyTimeoutTimeStamp_);
924         bundleActiveResult->GetInt(BUNDLE_HISTORY_LOG_UID_COLUMN_INDEX, usageHistory->uid_);
925         string usageHistoryKey = usageHistory->bundleName_ + to_string(usageHistory->uid_);
926         userUsageHistory->insert(pair<string, shared_ptr<BundleActivePackageHistory>>(usageHistoryKey,
927             usageHistory));
928     }
929     return userUsageHistory;
930 }
931 
PutDurationData(int64_t bootBasedDuration,int64_t screenOnDuration)932 void BundleActiveUsageDatabase::PutDurationData(int64_t bootBasedDuration, int64_t screenOnDuration)
933 {
934     lock_guard<ffrt::mutex> lock(databaseMutex_);
935     CheckDatabaseFile(APP_GROUP_DATABASE_INDEX);
936     if (durationTableName_ == UNKNOWN_TABLE_NAME) {
937         CreateDurationTable(APP_GROUP_DATABASE_INDEX);
938         durationTableName_ = DURATION_LOG_TABLE;
939     }
940     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
941     if (rdbStore == nullptr) {
942         return;
943     }
944     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
945     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
946     NativeRdb::ValuesBucket valuesBucket;
947     valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BOOT_BASED_DURATION, bootBasedDuration);
948     valuesBucket.PutLong(BUNDLE_ACTIVE_DB_SCREEN_ON_DURATION, screenOnDuration);
949     rdbStore->Update(changeRow, DURATION_LOG_TABLE, valuesBucket);
950     if (changeRow == NO_UPDATE_ROW) {
951         rdbStore->Insert(outRowId, DURATION_LOG_TABLE, valuesBucket);
952     }
953 }
954 
GetDurationData()955 pair<int64_t, int64_t> BundleActiveUsageDatabase::GetDurationData()
956 {
957     lock_guard<ffrt::mutex> lock(databaseMutex_);
958     pair<int64_t, int64_t> durationData;
959     if (durationTableName_ == UNKNOWN_TABLE_NAME) {
960         return durationData;
961     }
962     string queryDurationDataSql = "select * from " + DURATION_LOG_TABLE;
963     auto bundleActiveResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX,
964         queryDurationDataSql,
965         vector<string> {});
966     if (bundleActiveResult == nullptr) {
967         return durationData;
968     }
969     int32_t tableRowNumber;
970     bundleActiveResult->GetRowCount(tableRowNumber);
971     if (tableRowNumber == DURATION_TABLE_ROW_NUMBER) {
972         bundleActiveResult->GoToRow(tableRowNumber - DURATION_TABLE_ROW_NUMBER);
973         bundleActiveResult->GetLong(BOOT_BASED_DURATION_COLUMN_INDEX, durationData.first);
974         bundleActiveResult->GetLong(SCREEN_ON_DURATION_COLUMN_INDEX, durationData.second);
975     }
976     return durationData;
977 }
978 
FlushPackageInfo(uint32_t databaseType,const BundleActivePeriodStats & stats)979 void BundleActiveUsageDatabase::FlushPackageInfo(uint32_t databaseType, const BundleActivePeriodStats &stats)
980 {
981     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
982     if (rdbStore == nullptr) {
983         BUNDLE_ACTIVE_LOGE("flush package info fail, rdbStore is nullptr");
984         return;
985     }
986     string tableName = PACKAGE_LOG_TABLE + to_string(stats.beginTime_);
987     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
988     std::vector<NativeRdb::ValuesBucket> valuesBuckets;
989     vector<string> queryCondition;
990     for (auto iter = stats.bundleStats_.begin(); iter != stats.bundleStats_.end(); iter++) {
991         if (iter->second == nullptr || (iter->second->totalInFrontTime_ == 0 &&
992             iter->second->totalContiniousTaskUsedTime_ == 0)) {
993             continue;
994         }
995         NativeRdb::ValuesBucket valuesBucket;
996         queryCondition.push_back(to_string(stats.userId_));
997         queryCondition.push_back(iter->second->bundleName_);
998         queryCondition.push_back(to_string(iter->second->uid_));
999         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BUNDLE_STARTED_COUNT, iter->second->startCount_);
1000         int64_t lastTimeUsedAdjusted = iter->second->lastTimeUsed_ == -1 ?
1001             iter->second->lastTimeUsed_ : iter->second->lastTimeUsed_ - stats.beginTime_;
1002         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME, lastTimeUsedAdjusted);
1003         int64_t lastContinuousTaskUsedAdjusted = iter->second->lastContiniousTaskUsed_ == -1 ?
1004             iter->second->lastContiniousTaskUsed_ : iter->second->lastContiniousTaskUsed_ - stats.beginTime_;
1005         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME_CONTINUOUS_TASK, lastContinuousTaskUsedAdjusted);
1006         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_TOTAL_TIME, iter->second->totalInFrontTime_);
1007         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_TOTAL_TIME_CONTINUOUS_TASK, iter->second->totalContiniousTaskUsedTime_);
1008         rdbStore->Update(changeRow, tableName, valuesBucket, "userId = ? and bundleName = ? and uid = ?",
1009             queryCondition);
1010         if (changeRow == NO_UPDATE_ROW) {
1011             valuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, iter->second->bundleName_);
1012             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, stats.userId_);
1013             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, iter->second->uid_);
1014             valuesBuckets.push_back(valuesBucket);
1015         } else {
1016             changeRow = BUNDLE_ACTIVE_FAIL;
1017         }
1018         queryCondition.clear();
1019     }
1020     BatchInsert(rdbStore, valuesBuckets, tableName);
1021 }
1022 
GetCurrentUsageData(int32_t databaseType,int32_t userId)1023 shared_ptr<BundleActivePeriodStats> BundleActiveUsageDatabase::GetCurrentUsageData(int32_t databaseType,
1024     int32_t userId)
1025 {
1026     lock_guard<ffrt::mutex> lock(databaseMutex_);
1027     if (databaseType < 0 || databaseType >= static_cast<int32_t>(sortedTableArray_.size())) {
1028         return nullptr;
1029     }
1030     int32_t tableNumber = static_cast<int32_t>(sortedTableArray_.at(databaseType).size());
1031     if (tableNumber == TABLE_NOT_EXIST) {
1032         return nullptr;
1033     }
1034     int64_t currentPackageTime = sortedTableArray_.at(databaseType).at(tableNumber - 1);
1035     auto intervalStats = make_shared<BundleActivePeriodStats>(userId, currentPackageTime);
1036     string packageTableName = PACKAGE_LOG_TABLE + to_string(currentPackageTime);
1037     string queryPackageSql = "select * from " + packageTableName + " where userId = ?";
1038     vector<string> queryCondition;
1039     queryCondition.push_back(to_string(userId));
1040     auto bundleActiveResult = QueryStatsInfoByStep(databaseType, queryPackageSql, queryCondition);
1041     if (bundleActiveResult == nullptr) {
1042         return nullptr;
1043     }
1044     int32_t tableRowNumber;
1045     bundleActiveResult->GetRowCount(tableRowNumber);
1046     map<string, shared_ptr<BundleActivePackageStats>> bundleStats;
1047     int64_t relativeLastTimeUsed;
1048     int64_t relativeLastTimeFrontServiceUsed;
1049     for (int32_t i = 0; i < tableRowNumber; i++) {
1050         shared_ptr<BundleActivePackageStats> usageStats = make_shared<BundleActivePackageStats>();
1051         bundleActiveResult->GoToRow(i);
1052         bundleActiveResult->GetInt(USER_ID_COLUMN_INDEX, intervalStats->userId_);
1053         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, usageStats->bundleName_);
1054         bundleActiveResult->GetInt(BUNDLE_STARTED_COUNT_COLUMN_INDEX, usageStats->startCount_);
1055         bundleActiveResult->GetLong(LAST_TIME_COLUMN_INDEX, relativeLastTimeUsed);
1056         usageStats->lastTimeUsed_ = relativeLastTimeUsed == -1 ? -1 : relativeLastTimeUsed + currentPackageTime;
1057         bundleActiveResult->GetLong(LAST_TIME_CONTINUOUS_TASK_COLUMN_INDEX, relativeLastTimeFrontServiceUsed);
1058         usageStats->lastContiniousTaskUsed_ = relativeLastTimeFrontServiceUsed == -1 ? -1 :
1059             relativeLastTimeFrontServiceUsed + currentPackageTime;
1060         bundleActiveResult->GetLong(TOTAL_TIME_COLUMN_INDEX, usageStats->totalInFrontTime_);
1061         bundleActiveResult->GetLong(TOTAL_TIME_CONTINUOUS_TASK_COLUMN_INDEX, usageStats->totalContiniousTaskUsedTime_);
1062         bundleActiveResult->GetInt(PACKAGE_LOG_UID_COLUMN_INDEX, usageStats->uid_);
1063         string bundleStatsKey = usageStats->bundleName_ + std::to_string(usageStats->uid_);
1064         BundleActiveBundleMgrHelper::GetInstance()->InsertPackageUid(usageStats->bundleName_, usageStats->uid_);
1065         bundleStats.insert(pair<string, shared_ptr<BundleActivePackageStats>>(bundleStatsKey, usageStats));
1066     }
1067     intervalStats->bundleStats_ = bundleStats;
1068     if (databaseType == DAILY_DATABASE_INDEX) {
1069         eventBeginTime_ = currentPackageTime;
1070     }
1071     int64_t systemTime = GetSystemTimeMs();
1072     intervalStats->lastTimeSaved_ = systemTime;
1073     return intervalStats;
1074 }
1075 
FlushEventInfo(uint32_t databaseType,BundleActivePeriodStats & stats)1076 void BundleActiveUsageDatabase::FlushEventInfo(uint32_t databaseType, BundleActivePeriodStats &stats)
1077 {
1078     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
1079     if (rdbStore == nullptr) {
1080         BUNDLE_ACTIVE_LOGE("flush event info fail, rdbStore is nullptr");
1081         return;
1082     }
1083     if (eventTableName_ == UNKNOWN_TABLE_NAME) {
1084         CreateEventLogTable(databaseType, stats.beginTime_);
1085     }
1086     int64_t eventTableTime = ParseStartTime(eventTableName_);
1087     std::vector<NativeRdb::ValuesBucket> valuesBuckets;
1088     for (uint32_t i = 0; i < stats.events_.Size(); i++) {
1089         NativeRdb::ValuesBucket valuesBucket;
1090         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, stats.userId_);
1091         valuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, stats.events_.events_.at(i).bundleName_);
1092         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_EVENT_ID, stats.events_.events_.at(i).eventId_);
1093         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_TIME_STAMP, stats.events_.events_.at(i).timeStamp_ - eventTableTime);
1094         valuesBucket.PutString(BUNDLE_ACTIVE_DB_ABILITY_ID, stats.events_.events_.at(i).abilityId_);
1095         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, stats.events_.events_.at(i).uid_);
1096         valuesBuckets.push_back(valuesBucket);
1097     }
1098     BatchInsert(rdbStore, valuesBuckets, eventTableName_);
1099 }
1100 
GetTableIndexSql(uint32_t databaseType,int64_t tableTime,bool createFlag,int32_t indexFlag)1101 string BundleActiveUsageDatabase::GetTableIndexSql(uint32_t databaseType, int64_t tableTime, bool createFlag,
1102     int32_t indexFlag)
1103 {
1104     string tableIndexSql;
1105     if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
1106         string packageTableIndex = PACKAGE_LOG_TABLE_INDEX_PREFIX + to_string(tableTime);
1107         string PackageTableName = PACKAGE_LOG_TABLE + to_string(tableTime);
1108         if (createFlag) {
1109             tableIndexSql = "CREATE INDEX " + packageTableIndex + " ON "
1110                 + PackageTableName + " (userId, lastTime, bundleName);";
1111         } else {
1112             tableIndexSql = "DROP INDEX " + packageTableIndex;
1113         }
1114     } else if (databaseType == EVENT_DATABASE_INDEX) {
1115         string eventTableIndex = EVENT_LOG_TABLE_INDEX_PREFIX + to_string(tableTime);
1116         string eventTableName = EVENT_LOG_TABLE + to_string(tableTime);
1117         if (createFlag) {
1118             tableIndexSql = "CREATE INDEX " + eventTableIndex + " ON " + eventTableName +
1119                 " (timeStamp, userId, bundleName);";
1120         } else {
1121             tableIndexSql = "DROP INDEX " + eventTableIndex;
1122         }
1123     } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
1124         if (createFlag) {
1125             if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_NORMAL) {
1126                 tableIndexSql = "CREATE INDEX " + BUNDLE_HISTORY_LOG_TABLE_INDEX_PREFIX
1127                     + " ON " + BUNDLE_HISTORY_LOG_TABLE + " (userId, bundleName);";
1128             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_MODULE) {
1129                 tableIndexSql = "CREATE INDEX " + MODULE_RECORD_LOG_TABLE_INDEX_PREFIX
1130                     + " ON " + MODULE_RECORD_LOG_TABLE + to_string(tableTime) + " (userId, bundleName, moduleName);";
1131             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_FORM) {
1132                 tableIndexSql = "CREATE INDEX " + FORM_RECORD_LOG_TABLE_INDEX_PREFIX
1133                     + " ON " + FORM_RECORD_LOG_TABLE + to_string(tableTime) +
1134                     " (userId, moduleName, formName, formDimension, formId);";
1135             }
1136         } else {
1137             if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_NORMAL) {
1138                 tableIndexSql = "DROP INDEX " + BUNDLE_HISTORY_LOG_TABLE_INDEX_PREFIX;
1139             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_MODULE) {
1140                 tableIndexSql = "DROP INDEX " + MODULE_RECORD_LOG_TABLE_INDEX_PREFIX;
1141             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_FORM) {
1142                 tableIndexSql = "DROP INDEX " + FORM_RECORD_LOG_TABLE_INDEX_PREFIX;
1143             }
1144         }
1145     } else {
1146         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}d", databaseType);
1147     }
1148     return tableIndexSql;
1149 }
1150 
SetNewIndexWhenTimeChanged(uint32_t databaseType,int64_t tableOldTime,int64_t tableNewTime,std::shared_ptr<NativeRdb::RdbStore> rdbStore)1151 int32_t BundleActiveUsageDatabase::SetNewIndexWhenTimeChanged(uint32_t databaseType, int64_t tableOldTime,
1152     int64_t tableNewTime, std::shared_ptr<NativeRdb::RdbStore> rdbStore)
1153 {
1154     if (rdbStore == nullptr) {
1155         return BUNDLE_ACTIVE_FAIL;
1156     }
1157     if (databaseType == APP_GROUP_DATABASE_INDEX) {
1158         string oldModuleTableIndex = GetTableIndexSql(databaseType, tableOldTime, false,
1159             BUNDLE_ACTIVE_DB_INDEX_MODULE);
1160         int32_t deleteResult = rdbStore->ExecuteSql(oldModuleTableIndex);
1161         if (deleteResult != NativeRdb::E_OK) {
1162             return BUNDLE_ACTIVE_FAIL;
1163         }
1164         string newModuleTableIndex = GetTableIndexSql(databaseType, tableNewTime, true,
1165             BUNDLE_ACTIVE_DB_INDEX_MODULE);
1166         int32_t createResult = rdbStore->ExecuteSql(newModuleTableIndex);
1167         if (createResult != NativeRdb::E_OK) {
1168             return BUNDLE_ACTIVE_FAIL;
1169         }
1170         string oldFormTableIndex = GetTableIndexSql(databaseType, tableOldTime, false,
1171             BUNDLE_ACTIVE_DB_INDEX_FORM);
1172         deleteResult = rdbStore->ExecuteSql(oldFormTableIndex);
1173         if (deleteResult != NativeRdb::E_OK) {
1174             return BUNDLE_ACTIVE_FAIL;
1175         }
1176         string newFormTableIndex = GetTableIndexSql(databaseType, tableNewTime, true,
1177             BUNDLE_ACTIVE_DB_INDEX_FORM);
1178         createResult = rdbStore->ExecuteSql(newFormTableIndex);
1179         if (createResult != NativeRdb::E_OK) {
1180             return BUNDLE_ACTIVE_FAIL;
1181         }
1182     } else {
1183         string oldTableIndex = GetTableIndexSql(databaseType, tableOldTime, false);
1184         int32_t deleteResult = rdbStore->ExecuteSql(oldTableIndex);
1185         if (deleteResult != NativeRdb::E_OK) {
1186             return BUNDLE_ACTIVE_FAIL;
1187         }
1188         string newTableIndex = GetTableIndexSql(databaseType, tableNewTime, true);
1189         int32_t createResult = rdbStore->ExecuteSql(newTableIndex);
1190         if (createResult != NativeRdb::E_OK) {
1191             return BUNDLE_ACTIVE_FAIL;
1192         }
1193     }
1194     return BUNDLE_ACTIVE_SUCCESS;
1195 }
1196 
RenameTableName(uint32_t databaseType,int64_t tableOldTime,int64_t tableNewTime)1197 int32_t BundleActiveUsageDatabase::RenameTableName(uint32_t databaseType, int64_t tableOldTime,
1198     int64_t tableNewTime)
1199 {
1200     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
1201     if (rdbStore == nullptr) {
1202         return BUNDLE_ACTIVE_FAIL;
1203     }
1204     if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
1205         if (ExecuteRenameTableName(PACKAGE_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1206             return BUNDLE_ACTIVE_FAIL;
1207         }
1208     } else if (databaseType == EVENT_DATABASE_INDEX) {
1209         if (ExecuteRenameTableName(EVENT_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1210             return BUNDLE_ACTIVE_FAIL;
1211         }
1212     } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
1213         if (ExecuteRenameTableName(MODULE_RECORD_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1214             return BUNDLE_ACTIVE_FAIL;
1215         }
1216         if (ExecuteRenameTableName(FORM_RECORD_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1217             return BUNDLE_ACTIVE_FAIL;
1218         }
1219     }
1220     int32_t setResult = SetNewIndexWhenTimeChanged(databaseType, tableOldTime, tableNewTime, rdbStore);
1221     if (setResult != BUNDLE_ACTIVE_SUCCESS) {
1222         return BUNDLE_ACTIVE_FAIL;
1223     }
1224     return BUNDLE_ACTIVE_SUCCESS;
1225 }
1226 
ExecuteRenameTableName(std::string tablePrefix,int64_t tableOldTime,int64_t tableNewTime,std::shared_ptr<NativeRdb::RdbStore> rdbStore)1227 int32_t BundleActiveUsageDatabase::ExecuteRenameTableName(std::string tablePrefix, int64_t tableOldTime,
1228     int64_t tableNewTime, std::shared_ptr<NativeRdb::RdbStore> rdbStore)
1229 {
1230     if (!rdbStore) {
1231         BUNDLE_ACTIVE_LOGE("execute rename table name fail, rdbstore is nullptr");
1232         return BUNDLE_ACTIVE_FAIL;
1233     }
1234     string oldTableName = tablePrefix + to_string(tableOldTime);
1235     string newTableName = tablePrefix + to_string(tableNewTime);
1236     string renameTableNameSql = "alter table " + oldTableName + " rename to " + newTableName;
1237     int32_t renameTableName = rdbStore->ExecuteSql(renameTableNameSql);
1238     if (renameTableName != NativeRdb::E_OK) {
1239         BUNDLE_ACTIVE_LOGE("Rename table failed");
1240         return BUNDLE_ACTIVE_FAIL;
1241     }
1242     return ERR_OK;
1243 }
1244 
GetOptimalIntervalType(int64_t beginTime,int64_t endTime)1245 int32_t BundleActiveUsageDatabase::GetOptimalIntervalType(int64_t beginTime, int64_t endTime)
1246 {
1247     lock_guard<ffrt::mutex> lock(databaseMutex_);
1248     int32_t optimalIntervalType = -1;
1249     int64_t leastTimeDiff = numeric_limits<int64_t>::max();
1250     for (int32_t i = static_cast<int32_t>(sortedTableArray_.size() - 1); i >= 0; i--) {
1251         int32_t index = NearIndexOnOrBeforeCurrentTime(beginTime, sortedTableArray_.at(i));
1252         int32_t size = static_cast<int32_t>(sortedTableArray_.at(i).size());
1253         if (index >= 0 && index < size) {
1254             int64_t diff = abs(sortedTableArray_.at(i).at(index) - beginTime);
1255             if (diff < leastTimeDiff) {
1256                 leastTimeDiff = diff;
1257                 optimalIntervalType = i;
1258             }
1259         }
1260     }
1261     BUNDLE_ACTIVE_LOGI("optimalIntervalType is %{public}d", optimalIntervalType);
1262     return optimalIntervalType;
1263 }
1264 
RemoveOldData(int64_t currentTime)1265 void BundleActiveUsageDatabase::RemoveOldData(int64_t currentTime)
1266 {
1267     lock_guard<ffrt::mutex> lock(databaseMutex_);
1268     calendar_->SetMilliseconds(currentTime);
1269     calendar_->IncreaseYears(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[YEARLY_DATABASE_INDEX]);
1270     std::unique_ptr<std::vector<int64_t>> overdueYearsTableCreateTime = GetOverdueTableCreateTime(YEARLY_DATABASE_INDEX,
1271         calendar_->GetMilliseconds());
1272     if (overdueYearsTableCreateTime != nullptr) {
1273         for (uint32_t i = 0; i < overdueYearsTableCreateTime->size(); i++) {
1274             DeleteInvalidTable(YEARLY_DATABASE_INDEX, overdueYearsTableCreateTime->at(i));
1275         }
1276     }
1277     calendar_->SetMilliseconds(currentTime);
1278     calendar_->IncreaseMonths(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[MONTHLY_DATABASE_INDEX]);
1279     std::unique_ptr<std::vector<int64_t>> overdueMonthsTableCreateTime
1280         = GetOverdueTableCreateTime(MONTHLY_DATABASE_INDEX, calendar_->GetMilliseconds());
1281     if (overdueMonthsTableCreateTime != nullptr) {
1282         for (uint32_t i = 0; i < overdueMonthsTableCreateTime->size(); i++) {
1283             DeleteInvalidTable(MONTHLY_DATABASE_INDEX, overdueMonthsTableCreateTime->at(i));
1284         }
1285     }
1286     calendar_->SetMilliseconds(currentTime);
1287     calendar_->IncreaseWeeks(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[WEEKLY_DATABASE_INDEX]);
1288     std::unique_ptr<std::vector<int64_t>> overdueWeeksTableCreateTime = GetOverdueTableCreateTime(WEEKLY_DATABASE_INDEX,
1289         calendar_->GetMilliseconds());
1290     if (overdueWeeksTableCreateTime != nullptr) {
1291         for (uint32_t i = 0; i < overdueWeeksTableCreateTime->size(); i++) {
1292             DeleteInvalidTable(WEEKLY_DATABASE_INDEX, overdueWeeksTableCreateTime->at(i));
1293         }
1294     }
1295     calendar_->SetMilliseconds(currentTime);
1296     calendar_->IncreaseDays(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[DAILY_DATABASE_INDEX]);
1297     std::unique_ptr<std::vector<int64_t>> overdueDaysTableCreateTime = GetOverdueTableCreateTime(DAILY_DATABASE_INDEX,
1298         calendar_->GetMilliseconds());
1299     if (overdueDaysTableCreateTime != nullptr) {
1300         for (uint32_t i = 0; i < overdueDaysTableCreateTime->size(); i++) {
1301             DeleteInvalidTable(DAILY_DATABASE_INDEX, overdueDaysTableCreateTime->at(i));
1302         }
1303     }
1304     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
1305         HandleTableInfo(i);
1306         DeleteExcessiveTableData(i);
1307     }
1308 }
1309 
RenewTableTime(int64_t timeDiffMillis)1310 void BundleActiveUsageDatabase::RenewTableTime(int64_t timeDiffMillis)
1311 {
1312     lock_guard<ffrt::mutex> lock(databaseMutex_);
1313     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
1314         if (sortedTableArray_.at(i).empty()) {
1315             continue;
1316         }
1317         vector<int64_t> tableArray = sortedTableArray_.at(i);
1318         for (uint32_t j = 0; j < tableArray.size(); j++) {
1319             int64_t newTime = tableArray.at(j) + timeDiffMillis;
1320             BUNDLE_ACTIVE_LOGI("new table time is %{public}lld", (long long)newTime);
1321             if (newTime < 0) {
1322                 DeleteInvalidTable(i, tableArray.at(j));
1323             } else {
1324                 RenameTableName(i, tableArray.at(j), newTime);
1325             }
1326         }
1327         sortedTableArray_.at(i).clear();
1328         HandleTableInfo(i);
1329         DeleteExcessiveTableData(i);
1330     }
1331     if (eventTableName_ != UNKNOWN_TABLE_NAME) {
1332         int64_t oldTime = ParseStartTime(eventTableName_);
1333         int64_t newTime = oldTime + timeDiffMillis;
1334         if (newTime < 0) {
1335             int32_t deletedResult = DeleteInvalidTable(EVENT_DATABASE_INDEX, oldTime);
1336             if (deletedResult == BUNDLE_ACTIVE_SUCCESS) {
1337                 eventTableName_ = UNKNOWN_TABLE_NAME;
1338             }
1339         } else {
1340             int32_t renamedResult = RenameTableName(EVENT_DATABASE_INDEX, oldTime, newTime);
1341             if (renamedResult == BUNDLE_ACTIVE_SUCCESS) {
1342                 eventTableName_ = EVENT_LOG_TABLE + to_string(newTime);
1343             }
1344         }
1345     }
1346     if (formRecordsTableName_ != UNKNOWN_TABLE_NAME && moduleRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1347         int64_t oldTime = ParseStartTime(moduleRecordsTableName_);
1348         int64_t newTime = oldTime + timeDiffMillis;
1349         int32_t renamedResult = RenameTableName(APP_GROUP_DATABASE_INDEX, oldTime, newTime);
1350         if (renamedResult == BUNDLE_ACTIVE_SUCCESS) {
1351             moduleRecordsTableName_ = MODULE_RECORD_LOG_TABLE + to_string(newTime);
1352             formRecordsTableName_ = FORM_RECORD_LOG_TABLE + to_string(newTime);
1353         }
1354     }
1355 }
1356 
UpdateEventData(int32_t databaseType,BundleActivePeriodStats & stats)1357 void BundleActiveUsageDatabase::UpdateEventData(int32_t databaseType, BundleActivePeriodStats &stats)
1358 {
1359     lock_guard<ffrt::mutex> lock(databaseMutex_);
1360     CheckDatabaseFile(databaseType);
1361     if (databaseType != DAILY_DATABASE_INDEX) {
1362         return;
1363     }
1364     if (stats.events_.Size() != 0) {
1365         CheckDatabaseFile(EVENT_DATABASE_INDEX);
1366         FlushEventInfo(EVENT_DATABASE_INDEX, stats);
1367     }
1368 }
1369 
UpdateBundleUsageData(int32_t databaseType,BundleActivePeriodStats & stats)1370 void BundleActiveUsageDatabase::UpdateBundleUsageData(int32_t databaseType, BundleActivePeriodStats &stats)
1371 {
1372     lock_guard<ffrt::mutex> lock(databaseMutex_);
1373     if (databaseType < 0 || databaseType >= EVENT_DATABASE_INDEX) {
1374         BUNDLE_ACTIVE_LOGE("databaseType is invalid : %{public}d", databaseType);
1375         return;
1376     }
1377     CheckDatabaseFile(databaseType);
1378     int32_t packageTableIndex = BundleActiveBinarySearch::GetInstance()->BinarySearch(
1379         sortedTableArray_.at(databaseType), stats.beginTime_);
1380     if (packageTableIndex < 0) {
1381         CreatePackageLogTable(databaseType, stats.beginTime_);
1382         if (databaseType == DAILY_DATABASE_INDEX) {
1383             eventBeginTime_ = stats.beginTime_;
1384             DeleteExcessiveTableData(EVENT_DATABASE_INDEX);
1385         }
1386         sortedTableArray_.at(databaseType).push_back(stats.beginTime_);
1387         sort(sortedTableArray_.at(databaseType).begin(), sortedTableArray_.at(databaseType).end());
1388         DeleteExcessiveTableData(databaseType);
1389     }
1390     FlushPackageInfo(databaseType, stats);
1391     int64_t systemTime = GetSystemTimeMs();
1392     stats.lastTimeSaved_ = systemTime;
1393 }
1394 
GetDbIndex(const int64_t beginTime,const int64_t endTime,const int32_t databaseType,int32_t & startIndex,int32_t & endIndex)1395 bool BundleActiveUsageDatabase::GetDbIndex(const int64_t beginTime, const int64_t endTime,
1396     const int32_t databaseType, int32_t &startIndex, int32_t &endIndex)
1397 {
1398     if (databaseType < 0 || databaseType >= static_cast<int32_t>(sortedTableArray_.size())) {
1399         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}d", databaseType);
1400         return false;
1401     }
1402     if (endTime <= beginTime) {
1403         BUNDLE_ACTIVE_LOGE("endTime(%{public}lld) <= beginTime(%{public}lld)",
1404             (long long)endTime, (long long)beginTime);
1405         return false;
1406     }
1407     startIndex = NearIndexOnOrBeforeCurrentTime(beginTime, sortedTableArray_.at(databaseType));
1408     if (startIndex < 0) {
1409         startIndex = 0;
1410     }
1411     endIndex = NearIndexOnOrBeforeCurrentTime(endTime, sortedTableArray_.at(databaseType));
1412     if (endIndex < 0) {
1413         return false;
1414     }
1415     if (sortedTableArray_.at(databaseType).at(endIndex) == endTime) {
1416         endIndex--;
1417         if (endIndex < 0) {
1418         return false;
1419         }
1420     }
1421     return true;
1422 }
1423 
GetQuerySqlCommand(const int64_t beginTime,const int64_t endTime,const int32_t databaseType,const int32_t index,const int32_t startIndex,const int32_t endIndex,const int32_t userId,std::vector<std::string> & queryCondition,std::string & queryPackageSql)1424 void BundleActiveUsageDatabase::GetQuerySqlCommand(const int64_t beginTime,
1425     const int64_t endTime, const int32_t databaseType,
1426     const int32_t index, const int32_t startIndex, const int32_t endIndex, const int32_t userId,
1427     std::vector<std::string> &queryCondition, std::string &queryPackageSql)
1428 {
1429     string packageTableName;
1430     int64_t packageTableTime = sortedTableArray_.at(databaseType).at(index);
1431     packageTableName = PACKAGE_LOG_TABLE + to_string(packageTableTime);
1432     queryCondition.push_back(to_string(userId));
1433     if (startIndex == endIndex) {
1434         int64_t diff = beginTime - packageTableTime;
1435         if (diff >= 0) {
1436             queryCondition.push_back(to_string(diff));
1437         } else {
1438             queryCondition.push_back(to_string(LAST_TIME_IN_MILLIS_MIN));
1439         }
1440         queryCondition.push_back(to_string(endTime - packageTableTime));
1441         queryPackageSql = "select * from " + packageTableName +
1442             " where userId = ? and lastTime >= ? and lastTime <= ?";
1443     } else {
1444         if (index == startIndex) {
1445             int64_t diff = beginTime - packageTableTime;
1446             if (diff >= 0) {
1447                 queryCondition.push_back(to_string(diff));
1448             } else {
1449                 queryCondition.push_back(to_string(LAST_TIME_IN_MILLIS_MIN));
1450             }
1451             queryPackageSql = "select * from " + packageTableName + " where userId = ? and lastTime >= ?";
1452         } else if (index == endIndex) {
1453             queryCondition.push_back(to_string(endTime - packageTableTime));
1454             queryPackageSql = "select * from " + packageTableName + " where userId = ? and lastTime <= ?";
1455         } else {
1456             queryPackageSql = "select * from " + packageTableName + " where userId = ?";
1457         }
1458     }
1459 }
1460 
QueryDatabaseUsageStats(int32_t databaseType,int64_t beginTime,int64_t endTime,int32_t userId,const std::string & bundleName)1461 vector<BundleActivePackageStats> BundleActiveUsageDatabase::QueryDatabaseUsageStats(int32_t databaseType,
1462     int64_t beginTime, int64_t endTime, int32_t userId, const std::string& bundleName)
1463 {
1464     lock_guard<ffrt::mutex> lock(databaseMutex_);
1465     vector<BundleActivePackageStats> databaseUsageStats;
1466     int32_t startIndex = 0;
1467     int32_t endIndex = 0;
1468     if (!GetDbIndex(beginTime, endTime, databaseType, startIndex, endIndex)) {
1469         return databaseUsageStats;
1470     }
1471     for (int32_t i = startIndex; i <= endIndex; i++) {
1472         string queryPackageSql;
1473         vector<string> queryCondition;
1474 
1475         GetQuerySqlCommand(beginTime, endTime, databaseType, i, startIndex,
1476             endIndex, userId, queryCondition, queryPackageSql);
1477         if (bundleName != "") {
1478             queryCondition.push_back(bundleName);
1479             queryPackageSql += " and bundleName = ?";
1480         }
1481         auto bundleActiveResult = QueryStatsInfoByStep(databaseType, queryPackageSql,
1482             queryCondition);
1483         if (bundleActiveResult == nullptr) {
1484             return databaseUsageStats;
1485         }
1486         int32_t tableRowNumber;
1487         bundleActiveResult->GetRowCount(tableRowNumber);
1488         BundleActivePackageStats usageStats;
1489         int64_t relativeLastTimeUsed;
1490         int64_t relativeLastTimeFrontServiceUsed;
1491         int64_t packageTableTime = sortedTableArray_.at(databaseType).at(i);
1492         for (int32_t j = 0; j < tableRowNumber; j++) {
1493             bundleActiveResult->GoToRow(j);
1494             bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, usageStats.bundleName_);
1495             bundleActiveResult->GetInt(BUNDLE_STARTED_COUNT_COLUMN_INDEX, usageStats.startCount_);
1496             bundleActiveResult->GetLong(LAST_TIME_COLUMN_INDEX, usageStats.lastTimeUsed_);
1497             bundleActiveResult->GetLong(LAST_TIME_COLUMN_INDEX, relativeLastTimeUsed);
1498             usageStats.lastTimeUsed_ = relativeLastTimeUsed == -1 ? -1 :
1499                 relativeLastTimeUsed + packageTableTime;
1500             bundleActiveResult->GetLong(LAST_TIME_CONTINUOUS_TASK_COLUMN_INDEX, relativeLastTimeFrontServiceUsed);
1501             usageStats.lastContiniousTaskUsed_ = relativeLastTimeFrontServiceUsed == -1 ? -1 :
1502                 relativeLastTimeFrontServiceUsed + packageTableTime;
1503             bundleActiveResult->GetLong(TOTAL_TIME_COLUMN_INDEX, usageStats.totalInFrontTime_);
1504             bundleActiveResult->GetLong(TOTAL_TIME_CONTINUOUS_TASK_COLUMN_INDEX,
1505                 usageStats.totalContiniousTaskUsedTime_);
1506             bundleActiveResult->GetInt(PACKAGE_LOG_UID_COLUMN_INDEX, usageStats.uid_);
1507             usageStats.userId_ = userId;
1508             databaseUsageStats.push_back(usageStats);
1509         }
1510         queryCondition.clear();
1511     }
1512     return databaseUsageStats;
1513 }
1514 
QueryDatabaseEvents(int64_t beginTime,int64_t endTime,int32_t userId,string bundleName)1515 vector<BundleActiveEvent> BundleActiveUsageDatabase::QueryDatabaseEvents(int64_t beginTime, int64_t endTime,
1516     int32_t userId, string bundleName)
1517 {
1518     lock_guard<ffrt::mutex> lock(databaseMutex_);
1519     vector<BundleActiveEvent> databaseEvents;
1520     int64_t eventTableTime = ParseStartTime(eventTableName_);
1521     if (JudgeQueryCondition(beginTime, endTime, eventTableTime) == QUERY_CONDITION_INVALID) {
1522         return databaseEvents;
1523     }
1524     vector<string> queryCondition;
1525     int64_t diff = beginTime - eventTableTime;
1526     if (diff >= 0) {
1527         queryCondition.push_back(to_string(diff));
1528     } else {
1529         queryCondition.push_back(to_string(EVENT_TIME_IN_MILLIS_MIN));
1530     }
1531     queryCondition.push_back(to_string(endTime - eventTableTime));
1532     queryCondition.push_back(to_string(userId));
1533     string queryEventSql;
1534     if (bundleName.empty()) {
1535         queryEventSql = "select * from " + eventTableName_ + " where timeStamp >= ? and timeStamp <= ? and userId = ?";
1536     } else {
1537         queryCondition.push_back(bundleName);
1538         queryEventSql = "select * from " + eventTableName_ +
1539             " where timeStamp >= ? and timeStamp <= ? and userId = ? and bundleName = ?";
1540     }
1541     auto bundleActiveResult = QueryStatsInfoByStep(EVENT_DATABASE_INDEX,
1542         queryEventSql, queryCondition);
1543     if (bundleActiveResult == nullptr) {
1544         return databaseEvents;
1545     }
1546     int32_t tableRowNumber;
1547     bundleActiveResult->GetRowCount(tableRowNumber);
1548     BundleActiveEvent event;
1549     string relativeTimeStamp;
1550     for (int32_t i = 0; i < tableRowNumber; i++) {
1551         bundleActiveResult->GoToRow(i);
1552         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, event.bundleName_);
1553         bundleActiveResult->GetInt(EVENT_ID_COLUMN_INDEX, event.eventId_);
1554         bundleActiveResult->GetString(TIME_STAMP_COLUMN_INDEX, relativeTimeStamp);
1555         event.timeStamp_ = atoll(relativeTimeStamp.c_str()) + eventTableTime;
1556         bundleActiveResult->GetString(ABILITY_ID_COLUMN_INDEX, event.abilityId_);
1557         bundleActiveResult->GetInt(EVENT_UID_COLUMN_INDEX, event.uid_);
1558         databaseEvents.push_back(event);
1559     }
1560     return databaseEvents;
1561 }
1562 
OnPackageUninstalled(const int32_t userId,const string & bundleName,const int32_t uid,const int32_t appIndex)1563 void BundleActiveUsageDatabase::OnPackageUninstalled(const int32_t userId, const string& bundleName,
1564     const int32_t uid, const int32_t appIndex)
1565 {
1566     lock_guard<ffrt::mutex> lock(databaseMutex_);
1567     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
1568         if (sortedTableArray_.at(i).empty()) {
1569             continue;
1570         }
1571         for (uint32_t j = 0; j < sortedTableArray_.at(i).size(); j++) {
1572             string packageTableName = PACKAGE_LOG_TABLE + to_string(sortedTableArray_.at(i).at(j));
1573             DeleteUninstalledInfo(userId, bundleName, uid, packageTableName, i, appIndex);
1574         }
1575     }
1576     if (eventTableName_ != UNKNOWN_TABLE_NAME) {
1577         DeleteUninstalledInfo(userId, bundleName, uid, eventTableName_, EVENT_DATABASE_INDEX, appIndex);
1578     }
1579     if (bundleHistoryTableName_ != UNKNOWN_TABLE_NAME) {
1580         DeleteUninstalledInfo(userId, bundleName, uid, bundleHistoryTableName_, APP_GROUP_DATABASE_INDEX, appIndex);
1581     }
1582     if (moduleRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1583         DeleteUninstalledInfo(userId, bundleName, uid, moduleRecordsTableName_, APP_GROUP_DATABASE_INDEX, appIndex);
1584     }
1585     if (formRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1586         DeleteUninstalledInfo(userId, bundleName, uid, formRecordsTableName_, APP_GROUP_DATABASE_INDEX, appIndex);
1587     }
1588 }
1589 
DeleteUninstalledInfo(const int32_t userId,const string & bundleName,const int32_t uid,const string & tableName,uint32_t databaseType,const int32_t appIndex)1590 void BundleActiveUsageDatabase::DeleteUninstalledInfo(const int32_t userId, const string& bundleName,
1591     const int32_t uid, const string& tableName, uint32_t databaseType, const int32_t appIndex)
1592 {
1593     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
1594     if (rdbStore == nullptr) {
1595         BUNDLE_ACTIVE_LOGE("delete uninstalled info fail, rdbStore is nullptr");
1596         return;
1597     }
1598     int32_t deletedRows = BUNDLE_ACTIVE_FAIL;
1599     vector<string> queryCondition;
1600     queryCondition.push_back(to_string(userId));
1601     if (bundleName.empty()) {
1602         rdbStore->Delete(deletedRows, tableName, "userId = ?", queryCondition);
1603         return;
1604     }
1605     if (appIndex == MAIN_APP_INDEX) {
1606         queryCondition.push_back(bundleName);
1607         rdbStore->Delete(deletedRows, tableName, "userId = ? and bundleName = ?", queryCondition);
1608         return;
1609     }
1610     queryCondition.push_back(bundleName);
1611     queryCondition.push_back(to_string(uid));
1612     rdbStore->Delete(deletedRows, tableName, "userId = ? and bundleName = ? and uid = ?", queryCondition);
1613 }
1614 
GetSystemTimeMs()1615 int64_t BundleActiveUsageDatabase::GetSystemTimeMs()
1616 {
1617     time_t now;
1618     (void)time(&now);  // unit is seconds.
1619     if (static_cast<int64_t>(now) < 0) {
1620         BUNDLE_ACTIVE_LOGE("Get now time error");
1621         return 0;
1622     }
1623     auto tarEndTimePoint = std::chrono::system_clock::from_time_t(now);
1624     auto tarDuration = std::chrono::duration_cast<std::chrono::milliseconds>(tarEndTimePoint.time_since_epoch());
1625     int64_t tarDate = tarDuration.count();
1626     if (tarDate < 0) {
1627         BUNDLE_ACTIVE_LOGE("tarDuration is less than 0.");
1628         return -1;
1629     }
1630     return static_cast<int64_t>(tarDate);
1631 }
1632 
UpdateModuleData(const int32_t userId,std::map<std::string,std::shared_ptr<BundleActiveModuleRecord>> & moduleRecords,const int64_t timeStamp)1633 void BundleActiveUsageDatabase::UpdateModuleData(const int32_t userId,
1634     std::map<std::string, std::shared_ptr<BundleActiveModuleRecord>>& moduleRecords, const int64_t timeStamp)
1635 {
1636     lock_guard<ffrt::mutex> lock(databaseMutex_);
1637     CheckDatabaseFile(APP_GROUP_DATABASE_INDEX);
1638     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
1639     if (rdbStore == nullptr) {
1640         BUNDLE_ACTIVE_LOGE("update module data fail, rdbStore is nullptr");
1641         return;
1642     }
1643     CreateRecordTable(timeStamp);
1644     int64_t moduleTableTime = ParseStartTime(moduleRecordsTableName_);
1645     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
1646     std::vector<NativeRdb::ValuesBucket> moduleValuesBuckets;
1647     std::vector<NativeRdb::ValuesBucket> formValueBuckets;
1648     vector<string> queryCondition;
1649     for (const auto& oneModuleRecord : moduleRecords) {
1650         NativeRdb::ValuesBucket moduleValuesBucket;
1651         if (oneModuleRecord.second) {
1652             queryCondition.emplace_back(to_string(oneModuleRecord.second->userId_));
1653             queryCondition.emplace_back(oneModuleRecord.second->bundleName_);
1654             queryCondition.emplace_back(oneModuleRecord.second->moduleName_);
1655             queryCondition.emplace_back(to_string(oneModuleRecord.second->uid_));
1656             moduleValuesBucket.PutInt(BUNDLE_ACTIVE_DB_MODULE_LAUNCHED_COUNT, oneModuleRecord.second->launchedCount_);
1657             int64_t adjustLastTime = oneModuleRecord.second->lastModuleUsedTime_ != -1 ?
1658                 oneModuleRecord.second->lastModuleUsedTime_ - moduleTableTime : -1;
1659             moduleValuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME, adjustLastTime);
1660             rdbStore->Update(changeRow, moduleRecordsTableName_, moduleValuesBucket,
1661                 "userId = ? and bundleName = ? and moduleName = ? and uid = ?", queryCondition);
1662             if (changeRow == NO_UPDATE_ROW) {
1663                 moduleValuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, oneModuleRecord.second->userId_);
1664                 moduleValuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, oneModuleRecord.second->bundleName_);
1665                 moduleValuesBucket.PutString(BUNDLE_ACTIVE_DB_MODULE_NAME, oneModuleRecord.second->moduleName_);
1666                 moduleValuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, oneModuleRecord.second->uid_);
1667                 moduleValuesBuckets.push_back(moduleValuesBucket);
1668                 changeRow = BUNDLE_ACTIVE_FAIL;
1669             } else {
1670                 changeRow = BUNDLE_ACTIVE_FAIL;
1671             }
1672             queryCondition.clear();
1673             for (const auto& oneFormRecord : oneModuleRecord.second->formRecords_) {
1674                 UpdateFormData(oneModuleRecord.second->userId_, oneModuleRecord.second->bundleName_,
1675                     oneModuleRecord.second->moduleName_, oneFormRecord, rdbStore, formValueBuckets);
1676             }
1677         }
1678     }
1679     BatchInsert(rdbStore, moduleValuesBuckets, moduleRecordsTableName_);
1680     BatchInsert(rdbStore, formValueBuckets, formRecordsTableName_);
1681 }
1682 
CreateRecordTable(const int64_t timeStamp)1683 void BundleActiveUsageDatabase::CreateRecordTable(const int64_t timeStamp)
1684 {
1685     if (moduleRecordsTableName_ == UNKNOWN_TABLE_NAME) {
1686         CreateModuleRecordTable(APP_GROUP_DATABASE_INDEX, timeStamp);
1687     }
1688     if (formRecordsTableName_ == UNKNOWN_TABLE_NAME) {
1689         CreateFormRecordTable(APP_GROUP_DATABASE_INDEX, timeStamp);
1690     }
1691 }
1692 
UpdateFormData(const int32_t userId,const std::string bundleName,const string moduleName,const BundleActiveFormRecord & formRecord,std::shared_ptr<NativeRdb::RdbStore> rdbStore,std::vector<NativeRdb::ValuesBucket> & formValueBuckets)1693 void BundleActiveUsageDatabase::UpdateFormData(const int32_t userId, const std::string bundleName,
1694     const string moduleName, const BundleActiveFormRecord& formRecord,
1695     std::shared_ptr<NativeRdb::RdbStore> rdbStore, std::vector<NativeRdb::ValuesBucket>& formValueBuckets)
1696 {
1697     if (rdbStore == nullptr) {
1698         return;
1699     }
1700     NativeRdb::ValuesBucket formValueBucket;
1701     int64_t formRecordsTableTime = ParseStartTime(formRecordsTableName_);
1702     vector<string> queryCondition;
1703     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
1704     queryCondition.emplace_back(to_string(userId));
1705     queryCondition.emplace_back(bundleName);
1706     queryCondition.emplace_back(moduleName);
1707     queryCondition.emplace_back(formRecord.formName_);
1708     queryCondition.emplace_back(to_string(formRecord.formDimension_));
1709     queryCondition.emplace_back(to_string(formRecord.formId_));
1710     queryCondition.emplace_back(to_string(formRecord.uid_));
1711     formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_TOUCH_COUNT, formRecord.count_);
1712     int64_t adjustLastTime = formRecord.formLastUsedTime_ != -1 ? formRecord.formLastUsedTime_ -
1713         formRecordsTableTime : -1;
1714     formValueBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME, adjustLastTime);
1715     rdbStore->Update(changeRow, formRecordsTableName_, formValueBucket,
1716         "userId = ? and bundleName = ? and moduleName = ? and formName = ? and formDimension = ? "
1717         "and formId = ?",
1718         queryCondition);
1719     if (changeRow == NO_UPDATE_ROW) {
1720         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, userId);
1721         formValueBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, bundleName);
1722         formValueBucket.PutString(BUNDLE_ACTIVE_DB_MODULE_NAME, moduleName);
1723         formValueBucket.PutString(BUNDLE_ACTIVE_DB_FORM_NAME, formRecord.formName_);
1724         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_DIMENSION, formRecord.formDimension_);
1725         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_ID, formRecord.formId_);
1726         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_ID, formRecord.uid_);
1727         formValueBuckets.push_back(formValueBucket);
1728     }
1729 }
1730 
RemoveFormData(const int32_t userId,const std::string bundleName,const std::string moduleName,const std::string formName,const int32_t formDimension,const int64_t formId,const int32_t uid)1731 void BundleActiveUsageDatabase::RemoveFormData(const int32_t userId, const std::string bundleName,
1732     const std::string moduleName, const std::string formName, const int32_t formDimension,
1733     const int64_t formId, const int32_t uid)
1734 {
1735     lock_guard<ffrt::mutex> lock(databaseMutex_);
1736     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
1737     if (rdbStore == nullptr) {
1738         BUNDLE_ACTIVE_LOGE("remove for data fail, rdbStore is nullptr");
1739         return;
1740     }
1741     int32_t deletedRows = BUNDLE_ACTIVE_FAIL;
1742     if (formRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1743         vector<string> queryCondition;
1744         queryCondition.emplace_back(to_string(userId));
1745         queryCondition.emplace_back(bundleName);
1746         queryCondition.emplace_back(moduleName);
1747         queryCondition.emplace_back(formName);
1748         queryCondition.emplace_back(to_string(formDimension));
1749         queryCondition.emplace_back(to_string(formId));
1750         int32_t ret = rdbStore->Delete(deletedRows, formRecordsTableName_,
1751             "userId = ? and bundleName = ? and moduleName = ? and formName = ? and formDimension = ? "
1752             "and formId = ? and uid = ?",
1753             queryCondition);
1754         if (ret != NativeRdb::E_OK) {
1755             BUNDLE_ACTIVE_LOGE("delete event data failed, rdb error number: %{public}d", ret);
1756         }
1757     }
1758 }
1759 
LoadModuleData(const int32_t userId,std::map<std::string,std::shared_ptr<BundleActiveModuleRecord>> & moduleRecords)1760 void BundleActiveUsageDatabase::LoadModuleData(const int32_t userId, std::map<std::string,
1761     std::shared_ptr<BundleActiveModuleRecord>>& moduleRecords)
1762 {
1763     lock_guard<ffrt::mutex> lock(databaseMutex_);
1764     string queryModuleSql = "select * from " + moduleRecordsTableName_ + " where userId = ?";
1765     vector<string> queryCondition;
1766     queryCondition.emplace_back(to_string(userId));
1767     auto moduleRecordResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX, queryModuleSql,
1768         queryCondition);
1769     if (!moduleRecordResult) {
1770         return;
1771     }
1772     int64_t baseTime = ParseStartTime(moduleRecordsTableName_);
1773     int32_t numOfModuleRecord = 0;
1774     moduleRecordResult->GetRowCount(numOfModuleRecord);
1775     for (int32_t i = 0; i < numOfModuleRecord; i++) {
1776         shared_ptr<BundleActiveModuleRecord> oneModuleRecord = make_shared<BundleActiveModuleRecord>();
1777         moduleRecordResult->GoToRow(i);
1778         moduleRecordResult->GetInt(USER_ID_COLUMN_INDEX, oneModuleRecord->userId_);
1779         moduleRecordResult->GetString(BUNDLE_NAME_COLUMN_INDEX, oneModuleRecord->bundleName_);
1780         moduleRecordResult->GetString(MODULE_NAME_COLUMN_INDEX, oneModuleRecord->moduleName_);
1781         moduleRecordResult->GetInt(MODULE_USED_COUNT_COLUMN_INDEX, oneModuleRecord->launchedCount_);
1782         moduleRecordResult->GetInt(MODULE_UID_COLUMN_INDEX, oneModuleRecord->uid_);
1783         int64_t relativeLastTime = 0;
1784         moduleRecordResult->GetLong(MODULE_LAST_TIME_COLUMN_INDEX, relativeLastTime);
1785         oneModuleRecord->lastModuleUsedTime_ =  relativeLastTime != -1 ? relativeLastTime + baseTime : -1;
1786         string combinedInfo = oneModuleRecord->bundleName_
1787             + " " + to_string(oneModuleRecord->uid_) + " " + oneModuleRecord->moduleName_;
1788         moduleRecords[combinedInfo] = oneModuleRecord;
1789     }
1790 }
1791 
LoadFormData(const int32_t userId,std::map<std::string,std::shared_ptr<BundleActiveModuleRecord>> & moduleRecords)1792 void BundleActiveUsageDatabase::LoadFormData(const int32_t userId, std::map<std::string,
1793     std::shared_ptr<BundleActiveModuleRecord>>& moduleRecords)
1794 {
1795     lock_guard<ffrt::mutex> lock(databaseMutex_);
1796     string queryFormSql = "select * from " + formRecordsTableName_ + " where userId = ?";
1797     vector<string> queryCondition;
1798     queryCondition.emplace_back(to_string(userId));
1799     auto formRecordResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX, queryFormSql,
1800         queryCondition);
1801     if (!formRecordResult) {
1802         return;
1803     }
1804     int32_t numOfFormRecord = 0;
1805     int64_t baseTime = ParseStartTime(formRecordsTableName_);
1806     formRecordResult->GetRowCount(numOfFormRecord);
1807     for (int32_t i = 0; i < numOfFormRecord; i++) {
1808         BundleActiveFormRecord oneFormRecord;
1809         string moduleName = "";
1810         string bundleName = "";
1811         formRecordResult->GoToRow(i);
1812         formRecordResult->GetInt(USER_ID_COLUMN_INDEX, oneFormRecord.userId_);
1813         formRecordResult->GetString(BUNDLE_NAME_COLUMN_INDEX, bundleName);
1814         formRecordResult->GetString(MODULE_NAME_COLUMN_INDEX, moduleName);
1815         formRecordResult->GetString(FORM_NAME_COLUMN_INDEX, oneFormRecord.formName_);
1816         formRecordResult->GetInt(FORM_DIMENSION_COLUMN_INDEX, oneFormRecord.formDimension_);
1817         formRecordResult->GetLong(FORM_ID_COLUMN_INDEX, oneFormRecord.formId_);
1818         formRecordResult->GetInt(FORM_COUNT_COLUMN_INDEX, oneFormRecord.count_);
1819         formRecordResult->GetInt(FORM_UID_COLUMN_INDEX, oneFormRecord.uid_);
1820         int64_t relativeLastTime = 0;
1821         formRecordResult->GetLong(FORM_LAST_TIME_COLUMN_INDEX, relativeLastTime);
1822         oneFormRecord.formLastUsedTime_ = relativeLastTime != -1 ? relativeLastTime + baseTime : -1;
1823         auto it = moduleRecords.find(bundleName + " " + to_string(oneFormRecord.uid_) + " " + moduleName);
1824         if (it != moduleRecords.end() && it->second) {
1825             it->second->formRecords_.emplace_back(oneFormRecord);
1826         }
1827     }
1828 }
1829 
QueryDeviceEventStats(int32_t eventId,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & eventStats,int32_t userId)1830 void BundleActiveUsageDatabase::QueryDeviceEventStats(int32_t eventId, int64_t beginTime,
1831     int64_t endTime, std::map<std::string, BundleActiveEventStats>& eventStats, int32_t userId)
1832 {
1833     lock_guard<ffrt::mutex> lock(databaseMutex_);
1834     int64_t eventTableTime = ParseStartTime(eventTableName_);
1835     if (JudgeQueryCondition(beginTime, endTime, eventTableTime) == QUERY_CONDITION_INVALID) {
1836         return;
1837     }
1838     vector<string> queryCondition;
1839     int64_t diff = beginTime - eventTableTime;
1840     if (diff >= 0) {
1841         queryCondition.push_back(to_string(diff));
1842     } else {
1843         queryCondition.push_back(to_string(EVENT_TIME_IN_MILLIS_MIN));
1844     }
1845     queryCondition.push_back(to_string(endTime - eventTableTime));
1846     queryCondition.push_back(to_string(userId));
1847     queryCondition.push_back(to_string(eventId));
1848     string queryEventSql = "select * from " + eventTableName_ +
1849             " where timeStamp >= ? and timeStamp <= ? and userId = ? and eventId = ?";
1850     auto bundleActiveResult = QueryStatsInfoByStep(EVENT_DATABASE_INDEX,
1851         queryEventSql, queryCondition);
1852     if (bundleActiveResult == nullptr) {
1853         return;
1854     }
1855     int32_t tableRowNumber;
1856     bundleActiveResult->GetRowCount(tableRowNumber);
1857     if (tableRowNumber == 0) {
1858         return;
1859     }
1860     BundleActiveEventStats event;
1861     event.name_= GetSystemEventName(eventId);
1862     event.count_ = tableRowNumber;
1863     event.eventId_ = eventId;
1864     eventStats.insert(std::pair<std::string, BundleActiveEventStats>(event.name_, event));
1865 }
1866 
GetSystemEventName(const int32_t userId)1867 std::string BundleActiveUsageDatabase::GetSystemEventName(const int32_t userId)
1868 {
1869     std::string systemEventName = "";
1870     switch (userId) {
1871         case BundleActiveEvent::SYSTEM_LOCK:
1872             systemEventName = OPERATION_SYSTEM_LOCK;
1873             break;
1874         case BundleActiveEvent::SYSTEM_UNLOCK:
1875             systemEventName = OPERATION_SYSTEM_UNLOCK;
1876             break;
1877         case BundleActiveEvent::SYSTEM_SLEEP:
1878             systemEventName = OPERATION_SYSTEM_SLEEP;
1879             break;
1880         case BundleActiveEvent::SYSTEM_WAKEUP:
1881             systemEventName = OPERATION_SYSTEM_WAKEUP;
1882             break;
1883         default:
1884             break;
1885     }
1886     return systemEventName;
1887 }
1888 
QueryNotificationEventStats(int32_t eventId,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & notificationEventStats,int32_t userId)1889 void BundleActiveUsageDatabase::QueryNotificationEventStats(int32_t eventId, int64_t beginTime,
1890     int64_t endTime, std::map<std::string, BundleActiveEventStats>& notificationEventStats, int32_t userId)
1891 {
1892     lock_guard<ffrt::mutex> lock(databaseMutex_);
1893     int64_t eventTableTime = ParseStartTime(eventTableName_);
1894     if (JudgeQueryCondition(beginTime, endTime, eventTableTime) == QUERY_CONDITION_INVALID) {
1895         return;
1896     }
1897     vector<string> queryCondition;
1898     int64_t diff = beginTime - eventTableTime;
1899     if (diff >= 0) {
1900         queryCondition.push_back(to_string(diff));
1901     } else {
1902         queryCondition.push_back(to_string(EVENT_TIME_IN_MILLIS_MIN));
1903     }
1904     queryCondition.push_back(to_string(endTime - eventTableTime));
1905     queryCondition.push_back(to_string(userId));
1906     queryCondition.push_back(to_string(eventId));
1907     string queryEventSql = "select * from " + eventTableName_ +
1908             " where timeStamp >= ? and timeStamp <= ? and userId = ? and eventId = ?";
1909     auto bundleActiveResult = QueryStatsInfoByStep(EVENT_DATABASE_INDEX,
1910         queryEventSql, queryCondition);
1911     if (bundleActiveResult == nullptr) {
1912         return;
1913     }
1914     int32_t tableRowNumber;
1915     bundleActiveResult->GetRowCount(tableRowNumber);
1916     if (tableRowNumber == 0) {
1917         return;
1918     }
1919     BundleActiveEventStats event;
1920     std::map<std::string, BundleActiveEventStats>::iterator iter;
1921     for (int32_t i = 0; i < tableRowNumber; i++) {
1922         bundleActiveResult->GoToRow(i);
1923         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, event.name_);
1924         bundleActiveResult->GetInt(EVENT_ID_COLUMN_INDEX, event.eventId_);
1925         bundleActiveResult->GetInt(EVENT_UID_COLUMN_INDEX, event.uid_);
1926         iter = notificationEventStats.find(event.name_);
1927         if (iter != notificationEventStats.end()) {
1928             iter->second.count_++;
1929         } else {
1930             event.count_ = 1;
1931             notificationEventStats.insert(std::pair<std::string, BundleActiveEventStats>(event.name_, event));
1932         }
1933     }
1934 }
1935 
JudgeQueryCondition(const int64_t beginTime,const int64_t endTime,const int64_t eventTableTime)1936 int32_t BundleActiveUsageDatabase::JudgeQueryCondition(const int64_t beginTime,
1937     const int64_t endTime, const int64_t eventTableTime)
1938 {
1939     if (eventTableName_ == UNKNOWN_TABLE_NAME) {
1940         BUNDLE_ACTIVE_LOGE("eventTable does not exist");
1941         return QUERY_CONDITION_INVALID;
1942     }
1943     if (endTime <= beginTime) {
1944         BUNDLE_ACTIVE_LOGE("endTime(%{public}lld) <= beginTime(%{public}lld)",
1945             (long long)endTime, (long long)beginTime);
1946         return QUERY_CONDITION_INVALID;
1947     }
1948     if (endTime < eventTableTime) {
1949         BUNDLE_ACTIVE_LOGE("endTime(%{public}lld) <= eventTableTime(%{public}lld)",
1950             (long long)endTime, (long long)eventTableTime);
1951         return QUERY_CONDITION_INVALID;
1952     }
1953     return QUERY_CONDITION_VALID;
1954 }
1955 }  // namespace DeviceUsageStats
1956 }  // namespace OHOS
1957 
1958