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     for (uint32_t i = 0; i < tableTime.length(); i++) {
424         if (tableTime[i] >= '0' && tableTime[i] <= '9') {
425             tableTime = tableTime.substr(i);
426             break;
427         }
428     }
429     return atoll(tableTime.c_str());
430 }
431 
CheckDatabaseVersion()432 void BundleActiveUsageDatabase::CheckDatabaseVersion()
433 {
434     if (access(BUNDLE_ACTIVE_DATABASE_DIR.c_str(), F_OK) == 0) {
435         int32_t oldVersion = GetOldDbVersion();
436         if (oldVersion != BUNDLE_ACTIVE_FAIL && oldVersion < BUNDLE_ACTIVE_CURRENT_VERSION) {
437             UpgradleDatabase(oldVersion, BUNDLE_ACTIVE_CURRENT_VERSION);
438         }
439         ofstream openVersionFile;
440         openVersionFile.open(BUNDLE_ACTIVE_VERSION_DIRECTORY_PATH, ios::out);
441         if (openVersionFile) {
442             openVersionFile << "version : " << BUNDLE_ACTIVE_CURRENT_VERSION;
443         }
444         openVersionFile.close();
445     }
446 }
447 
GetOldDbVersion()448 int32_t BundleActiveUsageDatabase::GetOldDbVersion()
449 {
450     int32_t oldVersion = -1;
451     if (access(BUNDLE_ACTIVE_DATABASE_DIR.c_str(), F_OK) == 0) {
452         ifstream openVersionFile;
453         openVersionFile.open(BUNDLE_ACTIVE_VERSION_DIRECTORY_PATH, ios::in);
454         if (openVersionFile) {
455             char str[FILE_VERSION_LINE_NUM] = {0};
456             openVersionFile.getline(str, FILE_VERSION_LINE_NUM);
457             oldVersion = GetVersionByFileInput(str);
458         }
459         openVersionFile.close();
460     }
461     return oldVersion;
462 }
463 
GetVersionByFileInput(const std::string & FileVersionInput)464 int32_t BundleActiveUsageDatabase::GetVersionByFileInput(const std::string& FileVersionInput)
465 {
466     if (FileVersionInput.empty()) {
467         return BUNDLE_ACTIVE_FAIL;
468     }
469     string databaseVersion = FileVersionInput;
470     for (uint32_t i = 0; i < databaseVersion.length(); i++) {
471         if (databaseVersion[i] >= '0' && databaseVersion[i] <= '9') {
472             databaseVersion = databaseVersion.substr(i);
473             break;
474         }
475     }
476     return atoi(databaseVersion.c_str());
477 }
478 
UpgradleDatabase(const int32_t oldVersion,const int32_t curVersion)479 void BundleActiveUsageDatabase::UpgradleDatabase(const int32_t oldVersion, const int32_t curVersion)
480 {
481     BUNDLE_ACTIVE_LOGI("upgradle database oldVersion: %{public}d, curVersion: %{public}d", oldVersion, curVersion);
482     if (oldVersion < curVersion && curVersion == BUNDLE_ACTIVE_CURRENT_VERSION) {
483         if (oldVersion == BUNDLE_ACTIVE_VERSION_V1) {
484             SupportAppTwin();
485         }
486     }
487 }
488 
SupportAppTwin()489 void BundleActiveUsageDatabase::SupportAppTwin()
490 {
491     vector<vector<string>> allTableName = vector<vector<string>>(ALL_TABLE_ARRAY_NUMBER);
492     for (uint32_t i = 0; i <databaseFiles_.size(); i++) {
493         HandleAllTableName(i, allTableName);
494     }
495 
496     map<string, int32_t> bundleNameUidMap;
497     vector<int32_t> activatedOsAccountIds;
498     BundleActiveAccountHelper::GetActiveUserId(activatedOsAccountIds);
499     for (uint32_t i = 0; i < allTableName.size(); i++) {
500         auto tableNames = allTableName.at(i);
501         shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(i);
502         if (!rdbStore) {
503             BUNDLE_ACTIVE_LOGI("get RdbStore fail, databaseType: %{public}u", i);
504             continue;
505         }
506         for (string tableName: tableNames) {
507             if (DURATION_LOG_TABLE == tableName) {
508                 continue;
509             }
510             AddRdbColumn(rdbStore, tableName, BUNDLE_ACTIVE_DB_UID, RDB_STORE_COLUMN_TYPE_INT);
511             for (auto userId: activatedOsAccountIds) {
512                 UpdateOldDataUid(rdbStore, tableName, userId, bundleNameUidMap);
513             }
514         }
515     }
516 }
517 
AddRdbColumn(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const string & columnName,const string & columnType)518 void BundleActiveUsageDatabase::AddRdbColumn(const shared_ptr<NativeRdb::RdbStore> store,
519     const string& tableName, const string& columnName, const string& columnType)
520 {
521     string sqlStr = "";
522     if (columnType == RDB_STORE_COLUMN_TYPE_INT) {
523         sqlStr = "ALTER TABLE " + tableName + " ADD " + columnName + " " + columnType + " NOT NULL DEFAULT -1";
524     }
525     store->ExecuteSql(sqlStr);
526 }
527 
UpdateOldDataUid(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const int32_t userId,map<string,int32_t> & bundleNameUidMap)528 void BundleActiveUsageDatabase::UpdateOldDataUid(const shared_ptr<NativeRdb::RdbStore> store,
529     const string& tableName, const int32_t userId, map<string, int32_t>& bundleNameUidMap)
530 {
531     vector<string> queryCondition;
532     string querySql = "select * from " + tableName;
533     shared_ptr<NativeRdb::ResultSet> bundleActiveResult;
534     bundleActiveResult = store->QueryByStep(querySql);
535     int32_t tableRowNumber = 0;
536     bundleActiveResult->GetRowCount(tableRowNumber);
537     string bundleName;
538     int32_t uid;
539     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
540     NativeRdb::ValuesBucket valuesBucket;
541     for (int32_t i = 0; i < tableRowNumber; i++) {
542         bundleActiveResult->GoToRow(i);
543         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, bundleName);
544         AppExecFwk::ApplicationInfo appInfo;
545         string bundleNameUserIdKey = bundleName + to_string(userId);
546         auto it = bundleNameUidMap.find(bundleNameUserIdKey);
547         if (it == bundleNameUidMap.end()) {
548             BundleActiveBundleMgrHelper::GetInstance()->GetApplicationInfo(bundleName,
549                 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, appInfo);
550             uid = appInfo.uid;
551             bundleNameUidMap[bundleNameUserIdKey] = uid;
552         } else {
553             uid = it->second;
554         }
555         queryCondition.push_back(to_string(userId));
556         queryCondition.push_back(bundleName);
557         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, uid);
558         store->Update(changeRow, tableName, valuesBucket, "userId = ? and bundleName = ?", queryCondition);
559         queryCondition.clear();
560         valuesBucket.Clear();
561         changeRow = BUNDLE_ACTIVE_FAIL;
562     }
563 }
564 
GetBundleActiveRdbStore(uint32_t databaseType)565 shared_ptr<NativeRdb::RdbStore> WEAK_FUNC BundleActiveUsageDatabase::GetBundleActiveRdbStore(uint32_t databaseType)
566 {
567     shared_ptr<NativeRdb::RdbStore> rdbStore;
568     string file = databaseFiles_.at(databaseType);
569     if (bundleActiveRdbStoreCache_.find(file) == bundleActiveRdbStoreCache_.end()) {
570         int32_t errCode(BUNDLE_ACTIVE_FAIL);
571         string currDatabaseFileConfig = BUNDLE_ACTIVE_DATABASE_DIR + databaseFiles_.at(databaseType);
572         RdbStoreConfig config(currDatabaseFileConfig);
573         BundleActiveOpenCallback rdbDataCallBack;
574         config.SetJournalMode(NativeRdb::JournalMode::MODE_OFF);
575         config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
576         rdbStore = RdbHelper::GetRdbStore(config, BUNDLE_ACTIVE_RDB_VERSION, rdbDataCallBack, errCode);
577         if ((rdbStore == nullptr)) {
578             BUNDLE_ACTIVE_LOGE("get bundle active rdbStore fail, rdbStore is nullptr");
579             return nullptr;
580         }
581         bundleActiveRdbStoreCache_.insert(pair {file, rdbStore});
582     } else {
583         rdbStore = bundleActiveRdbStoreCache_[file];
584     }
585     if (rdbStore == nullptr) {
586         BUNDLE_ACTIVE_LOGE("get bundle active rdbStore fail, rdbStore is nullptr");
587         return nullptr;
588     }
589     return rdbStore;
590 }
591 
CheckDatabaseFile(uint32_t databaseType)592 void BundleActiveUsageDatabase::CheckDatabaseFile(uint32_t databaseType)
593 {
594     std::string databaseFileName = databaseFiles_.at(databaseType);
595     for (uint32_t i = 0; i < sizeof(SUFFIX_TYPE) / sizeof(SUFFIX_TYPE[0]); i++) {
596         std::string dbFile = BUNDLE_ACTIVE_DATABASE_DIR + DATABASE_TYPE[databaseType] + SUFFIX_TYPE[i];
597         if ((access(dbFile.c_str(), F_OK) != 0)
598             && (bundleActiveRdbStoreCache_.find(databaseFileName) != bundleActiveRdbStoreCache_.end())) {
599             bundleActiveRdbStoreCache_.erase(databaseFileName);
600             std::string rdbStorePath = BUNDLE_ACTIVE_DATABASE_DIR + DATABASE_TYPE[databaseType] + SUFFIX_TYPE[0];
601             RdbHelper::DeleteRdbStore(rdbStorePath);
602             if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
603                 sortedTableArray_.at(databaseType).clear();
604             } else if (databaseType == EVENT_DATABASE_INDEX) {
605                 eventTableName_ = UNKNOWN_TABLE_NAME;
606             } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
607                 durationTableName_ = UNKNOWN_TABLE_NAME;
608                 bundleHistoryTableName_ = UNKNOWN_TABLE_NAME;
609                 moduleRecordsTableName_ = UNKNOWN_TABLE_NAME;
610                 formRecordsTableName_ = UNKNOWN_TABLE_NAME;
611             }
612             return;
613         }
614     }
615 }
616 
CreateEventLogTable(uint32_t databaseType,int64_t currentTimeMillis)617 int32_t BundleActiveUsageDatabase::CreateEventLogTable(uint32_t databaseType, int64_t currentTimeMillis)
618 {
619     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
620     if (rdbStore == nullptr) {
621         BUNDLE_ACTIVE_LOGE(" create event log table faile, rdbStore is nullptr");
622         return BUNDLE_ACTIVE_FAIL;
623     }
624     string eventTable = EVENT_LOG_TABLE + to_string(currentTimeMillis);
625     eventTableName_ = eventTable;
626     const string createEventTableSql = "CREATE TABLE IF NOT EXISTS "
627                                            + eventTable
628                                            + " ("
629                                            + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
630                                            + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
631                                            + BUNDLE_ACTIVE_DB_EVENT_ID + " INTEGER NOT NULL, "
632                                            + BUNDLE_ACTIVE_DB_TIME_STAMP + " INTEGER NOT NULL, "
633                                            + BUNDLE_ACTIVE_DB_ABILITY_ID + " TEXT NOT NULL, "
634                                            + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
635     int32_t createEventTable = rdbStore->ExecuteSql(createEventTableSql);
636     if (createEventTable != NativeRdb::E_OK) {
637         BUNDLE_ACTIVE_LOGE("create event table failed, rdb error number: %{public}d", createEventTable);
638         return createEventTable;
639     }
640     string createEventTableIndex = GetTableIndexSql(EVENT_DATABASE_INDEX, currentTimeMillis, true);
641     int32_t createResult = rdbStore->ExecuteSql(createEventTableIndex);
642     if (createResult != NativeRdb::E_OK) {
643         BUNDLE_ACTIVE_LOGE("create event table index failed, rdb error number: %{public}d", createResult);
644         return BUNDLE_ACTIVE_FAIL;
645     }
646     return BUNDLE_ACTIVE_SUCCESS;
647 }
648 
CreatePackageLogTable(uint32_t databaseType,int64_t currentTimeMillis)649 int32_t BundleActiveUsageDatabase::CreatePackageLogTable(uint32_t databaseType, int64_t currentTimeMillis)
650 {
651     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
652     if (rdbStore == nullptr) {
653         BUNDLE_ACTIVE_LOGE(" create package log table fail, rdbStore is nullptr");
654         return BUNDLE_ACTIVE_FAIL;
655     }
656     string packageTable = PACKAGE_LOG_TABLE + to_string(currentTimeMillis);
657     string createPackageTableSql = "CREATE TABLE IF NOT EXISTS "
658                                         + packageTable
659                                         + " ("
660                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
661                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
662                                         + BUNDLE_ACTIVE_DB_BUNDLE_STARTED_COUNT + " INTEGER NOT NULL, "
663                                         + BUNDLE_ACTIVE_DB_LAST_TIME + " INTEGER NOT NULL, "
664                                         + BUNDLE_ACTIVE_DB_LAST_TIME_CONTINUOUS_TASK + " INTEGER NOT NULL, "
665                                         + BUNDLE_ACTIVE_DB_TOTAL_TIME + " INTEGER NOT NULL, "
666                                         + BUNDLE_ACTIVE_DB_TOTAL_TIME_CONTINUOUS_TASK + " INTEGER NOT NULL, "
667                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
668     int32_t createPackageTable = rdbStore->ExecuteSql(createPackageTableSql);
669     if (createPackageTable != NativeRdb::E_OK) {
670         BUNDLE_ACTIVE_LOGE("create packageLog table failed, rdb error number: %{public}d", createPackageTable);
671         return BUNDLE_ACTIVE_FAIL;
672     }
673     string createPackageTableIndex = GetTableIndexSql(databaseType, currentTimeMillis, true);
674     int32_t createResult = rdbStore->ExecuteSql(createPackageTableIndex);
675     if (createResult != NativeRdb::E_OK) {
676         BUNDLE_ACTIVE_LOGE("create package table index failed, rdb error number: %{public}d", createResult);
677         return BUNDLE_ACTIVE_FAIL;
678     }
679     return BUNDLE_ACTIVE_SUCCESS;
680 }
681 
CreateModuleRecordTable(uint32_t databaseType,int64_t timeStamp)682 int32_t BundleActiveUsageDatabase::CreateModuleRecordTable(uint32_t databaseType, int64_t timeStamp)
683 {
684     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
685     if (rdbStore == nullptr) {
686         BUNDLE_ACTIVE_LOGE("create module record table fail, rdbStore is nullptr");
687         return BUNDLE_ACTIVE_FAIL;
688     }
689     string moduleRecord = MODULE_RECORD_LOG_TABLE + to_string(timeStamp);
690     moduleRecordsTableName_ = moduleRecord;
691     string createModuleRecordTableSql = "CREATE TABLE IF NOT EXISTS "
692                                         + moduleRecord
693                                         + " ("
694                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
695                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
696                                         + BUNDLE_ACTIVE_DB_MODULE_NAME + " TEXT NOT NULL, "
697                                         + BUNDLE_ACTIVE_DB_MODULE_LAUNCHED_COUNT + " INTEGER NOT NULL, "
698                                         + BUNDLE_ACTIVE_DB_LAST_TIME + " INTEGER NOT NULL, "
699                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
700     int32_t createModuleRecordTable = rdbStore->ExecuteSql(createModuleRecordTableSql);
701     if (createModuleRecordTable != NativeRdb::E_OK) {
702         BUNDLE_ACTIVE_LOGE("create ModuleRecord table failed, rdb error number: %{public}d", createModuleRecordTable);
703         return BUNDLE_ACTIVE_FAIL;
704     }
705     string createModuleTableIndex = GetTableIndexSql(databaseType, timeStamp, true, BUNDLE_ACTIVE_DB_INDEX_MODULE);
706     int32_t createResult = rdbStore->ExecuteSql(createModuleTableIndex);
707     if (createResult != NativeRdb::E_OK) {
708         BUNDLE_ACTIVE_LOGE("create module table index failed, rdb error number: %{public}d", createResult);
709         return BUNDLE_ACTIVE_FAIL;
710     }
711     return BUNDLE_ACTIVE_SUCCESS;
712 }
713 
CreateFormRecordTable(uint32_t databaseType,int64_t timeStamp)714 int32_t BundleActiveUsageDatabase::CreateFormRecordTable(uint32_t databaseType, int64_t timeStamp)
715 {
716     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
717     if (rdbStore == nullptr) {
718         BUNDLE_ACTIVE_LOGE("create form record table fail, rdbStore is nullptr");
719         return BUNDLE_ACTIVE_FAIL;
720     }
721     string formRecord = FORM_RECORD_LOG_TABLE + to_string(timeStamp);
722     formRecordsTableName_ = formRecord;
723     string createFormRecordTableSql = "CREATE TABLE IF NOT EXISTS "
724                                         + formRecord
725                                         + " ("
726                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
727                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
728                                         + BUNDLE_ACTIVE_DB_MODULE_NAME + " TEXT NOT NULL, "
729                                         + BUNDLE_ACTIVE_DB_FORM_NAME + " TEXT NOT NULL, "
730                                         + BUNDLE_ACTIVE_DB_FORM_DIMENSION + " INTEGER NOT NULL, "
731                                         + BUNDLE_ACTIVE_DB_FORM_ID + " INTEGER NOT NULL, "
732                                         + BUNDLE_ACTIVE_DB_FORM_TOUCH_COUNT + " INTEGER NOT NULL, "
733                                         + BUNDLE_ACTIVE_DB_LAST_TIME + " INTEGER NOT NULL, "
734                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
735     int32_t createFormRecordTable = rdbStore->ExecuteSql(createFormRecordTableSql);
736     if (createFormRecordTable != NativeRdb::E_OK) {
737         BUNDLE_ACTIVE_LOGE("create ModuleRecord table failed, rdb error number: %{public}d", createFormRecordTable);
738         return BUNDLE_ACTIVE_FAIL;
739     }
740     string createFormTableIndex = GetTableIndexSql(databaseType, timeStamp, true, BUNDLE_ACTIVE_DB_INDEX_FORM);
741     int32_t createResult = rdbStore->ExecuteSql(createFormTableIndex);
742     if (createResult != NativeRdb::E_OK) {
743         BUNDLE_ACTIVE_LOGE("create module table index failed, rdb error number: %{public}d", createResult);
744         return BUNDLE_ACTIVE_FAIL;
745     }
746     return BUNDLE_ACTIVE_SUCCESS;
747 }
748 
CreateDurationTable(uint32_t databaseType)749 int32_t BundleActiveUsageDatabase::CreateDurationTable(uint32_t databaseType)
750 {
751     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
752     if (rdbStore == nullptr) {
753         BUNDLE_ACTIVE_LOGE("create duration table fail, rdbStore is nullptr");
754         return BUNDLE_ACTIVE_FAIL;
755     }
756     string createDurationTableSql = "CREATE TABLE IF NOT EXISTS "
757                                         + DURATION_LOG_TABLE
758                                         + " ("
759                                         + BUNDLE_ACTIVE_DB_BOOT_BASED_DURATION + " INTEGER NOT NULL, "
760                                         + BUNDLE_ACTIVE_DB_SCREEN_ON_DURATION + " INTEGER NOT NULL);";
761     int32_t createDurationTable = rdbStore->ExecuteSql(createDurationTableSql);
762     if (createDurationTable != NativeRdb::E_OK) {
763         BUNDLE_ACTIVE_LOGE("create duration table failed, rdb error number: %{public}d", createDurationTable);
764         return BUNDLE_ACTIVE_FAIL;
765     }
766     return BUNDLE_ACTIVE_SUCCESS;
767 }
768 
CreateBundleHistoryTable(uint32_t databaseType)769 int32_t BundleActiveUsageDatabase::CreateBundleHistoryTable(uint32_t databaseType)
770 {
771     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
772     if (rdbStore == nullptr) {
773         BUNDLE_ACTIVE_LOGE("create bundle history table fail, rdbStore is nullptr");
774         return BUNDLE_ACTIVE_FAIL;
775     }
776     string createBundleHistoryTableSql = "CREATE TABLE IF NOT EXISTS "
777                                         + BUNDLE_HISTORY_LOG_TABLE
778                                         + " ("
779                                         + BUNDLE_ACTIVE_DB_USER_ID + " INTEGER NOT NULL, "
780                                         + BUNDLE_ACTIVE_DB_BUNDLE_NAME + " TEXT NOT NULL, "
781                                         + BUNDLE_ACTIVE_DB_LAST_BOOT_FROM_USED_TIME + " INTEGER NOT NULL, "
782                                         + BUNDLE_ACTIVE_DB_LAST_SCREEN_USED_TIME + " INTEGER NOT NULL, "
783                                         + BUNDLE_ACTIVE_DB_CURRENT_GROUP + " INTEGER NOT NULL, "
784                                         + BUNDLE_ACTIVE_DB_REASON_IN_GROUP + " INTEGER NOT NULL, "
785                                         + BUNDLE_ACTIVE_DB_BUNDLE_ALIVE_TIMEOUT_TIME + " INTEGER NOT NULL, "
786                                         + BUNDLE_ACTIVE_DB_BUNDLE_DAILY_TIMEOUT_TIME + " INTEGER NOT NULL, "
787                                         + BUNDLE_ACTIVE_DB_UID + " INTEGER NOT NULL DEFAULT -1);";
788     int32_t createBundleHistoryTable = rdbStore->ExecuteSql(createBundleHistoryTableSql);
789     if (createBundleHistoryTable != NativeRdb::E_OK) {
790         BUNDLE_ACTIVE_LOGE("create bundleHistory table failed, rdb error number: %{public}d", createBundleHistoryTable);
791         return createBundleHistoryTable;
792     }
793     int32_t time = 0;
794     string createBundleHistoryTableIndex = GetTableIndexSql(databaseType, time, true);
795     int32_t createResult = rdbStore->ExecuteSql(createBundleHistoryTableIndex);
796     if (createResult != NativeRdb::E_OK) {
797         BUNDLE_ACTIVE_LOGE("create bundleHistory table index failed, rdb error number: %{public}d", createResult);
798         return BUNDLE_ACTIVE_FAIL;
799     }
800     return BUNDLE_ACTIVE_SUCCESS;
801 }
802 
PutBundleHistoryData(int32_t userId,shared_ptr<map<string,shared_ptr<BundleActivePackageHistory>>> userHistory)803 void BundleActiveUsageDatabase::PutBundleHistoryData(int32_t userId,
804     shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> userHistory)
805 {
806     lock_guard<ffrt::mutex> lock(databaseMutex_);
807     if (userHistory == nullptr) {
808         return;
809     }
810     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
811     if (userHistory == nullptr || rdbStore == nullptr) {
812         return;
813     }
814     CheckDatabaseFileAndTable();
815     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
816     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
817     NativeRdb::ValuesBucket valuesBucket;
818     vector<string> queryCondition;
819     int32_t updatedcount = 0;
820     int32_t unupdatedcount = 0;
821     for (auto iter = userHistory->begin(); iter != userHistory->end(); iter++) {
822         if (iter->second == nullptr || !iter->second->isChanged_) {
823             unupdatedcount++;
824             continue;
825         }
826         queryCondition.push_back(to_string(userId));
827         queryCondition.push_back(iter->second->bundleName_);
828         queryCondition.push_back(to_string(iter->second->uid_));
829         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_BOOT_FROM_USED_TIME, iter->second->lastBootFromUsedTimeStamp_);
830         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_SCREEN_USED_TIME, iter->second->lastScreenUsedTimeStamp_);
831         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_CURRENT_GROUP, iter->second->currentGroup_);
832         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_REASON_IN_GROUP, static_cast<int32_t>(iter->second->reasonInGroup_));
833         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BUNDLE_ALIVE_TIMEOUT_TIME, iter->second->bundleAliveTimeoutTimeStamp_);
834         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BUNDLE_DAILY_TIMEOUT_TIME, iter->second->bundleDailyTimeoutTimeStamp_);
835         rdbStore->Update(changeRow, BUNDLE_HISTORY_LOG_TABLE, valuesBucket,
836             "userId = ? and bundleName = ? and uid = ?", queryCondition);
837         if (changeRow == NO_UPDATE_ROW) {
838             valuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, iter->second->bundleName_);
839             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, userId);
840             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, iter->second->uid_);
841             rdbStore->Insert(outRowId, BUNDLE_HISTORY_LOG_TABLE, valuesBucket);
842             outRowId = BUNDLE_ACTIVE_FAIL;
843         } else {
844             changeRow = BUNDLE_ACTIVE_FAIL;
845         }
846         valuesBucket.Clear();
847         queryCondition.clear();
848         iter->second->isChanged_ = false;
849         updatedcount++;
850     }
851     BUNDLE_ACTIVE_LOGI("update %{public}d bundles, keep %{public}d bundles group", updatedcount, unupdatedcount);
852 }
853 
CheckDatabaseFileAndTable()854 void BundleActiveUsageDatabase::CheckDatabaseFileAndTable()
855 {
856     CheckDatabaseFile(APP_GROUP_DATABASE_INDEX);
857     if (bundleHistoryTableName_ == UNKNOWN_TABLE_NAME) {
858         CreateBundleHistoryTable(APP_GROUP_DATABASE_INDEX);
859         bundleHistoryTableName_ = BUNDLE_HISTORY_LOG_TABLE;
860     }
861 }
862 
GetBundleHistoryData(int32_t userId)863 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> BundleActiveUsageDatabase::GetBundleHistoryData(
864     int32_t userId)
865 {
866     lock_guard<ffrt::mutex> lock(databaseMutex_);
867     if (bundleHistoryTableName_ == UNKNOWN_TABLE_NAME) {
868         return nullptr;
869     }
870     string queryHistoryDataSql = "select * from " + BUNDLE_HISTORY_LOG_TABLE + " where userId = ?";
871     vector<string> queryCondition;
872     queryCondition.push_back(to_string(userId));
873     auto bundleActiveResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX,
874         queryHistoryDataSql, queryCondition);
875     if (bundleActiveResult == nullptr) {
876         return nullptr;
877     }
878     int32_t tableRowNumber;
879     bundleActiveResult->GetRowCount(tableRowNumber);
880     if (tableRowNumber == TABLE_ROW_ZERO) {
881         return nullptr;
882     }
883     shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> userUsageHistory =
884         make_shared<map<string, shared_ptr<BundleActivePackageHistory>>>();
885     int32_t currentBundleGroupReason = 0;
886     for (int32_t i = 0; i < tableRowNumber; i++) {
887         bundleActiveResult->GoToRow(i);
888         shared_ptr<BundleActivePackageHistory> usageHistory = make_shared<BundleActivePackageHistory>();
889         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, usageHistory->bundleName_);
890         bundleActiveResult->GetLong(LAST_BOOT_FROM_USED_TIME_COLUMN_INDEX, usageHistory->lastBootFromUsedTimeStamp_);
891         bundleActiveResult->GetLong(LAST_SCREEN_USED_TIME_COLUMN_INDEX, usageHistory->lastScreenUsedTimeStamp_);
892         bundleActiveResult->GetInt(CURRENT_GROUP_COLUMN_INDEX, usageHistory->currentGroup_);
893         bundleActiveResult->GetInt(REASON_IN_GROUP_COLUMN_INDEX, currentBundleGroupReason);
894         usageHistory->reasonInGroup_ = static_cast<uint32_t>(currentBundleGroupReason);
895         bundleActiveResult->GetLong(BUNDLE_ALIVE_TIMEOUT_TIME_COLUMN_INDEX,
896             usageHistory->bundleAliveTimeoutTimeStamp_);
897         bundleActiveResult->GetLong(BUNDLE_DAILY_TIMEOUT_TIME_COLUMN_INDEX,
898             usageHistory->bundleDailyTimeoutTimeStamp_);
899         bundleActiveResult->GetInt(BUNDLE_HISTORY_LOG_UID_COLUMN_INDEX, usageHistory->uid_);
900         string usageHistoryKey = usageHistory->bundleName_ + to_string(usageHistory->uid_);
901         userUsageHistory->insert(pair<string, shared_ptr<BundleActivePackageHistory>>(usageHistoryKey,
902             usageHistory));
903     }
904     return userUsageHistory;
905 }
906 
PutDurationData(int64_t bootBasedDuration,int64_t screenOnDuration)907 void BundleActiveUsageDatabase::PutDurationData(int64_t bootBasedDuration, int64_t screenOnDuration)
908 {
909     lock_guard<ffrt::mutex> lock(databaseMutex_);
910     CheckDatabaseFile(APP_GROUP_DATABASE_INDEX);
911     if (durationTableName_ == UNKNOWN_TABLE_NAME) {
912         CreateDurationTable(APP_GROUP_DATABASE_INDEX);
913         durationTableName_ = DURATION_LOG_TABLE;
914     }
915     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
916     if (rdbStore == nullptr) {
917         return;
918     }
919     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
920     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
921     NativeRdb::ValuesBucket valuesBucket;
922     valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BOOT_BASED_DURATION, bootBasedDuration);
923     valuesBucket.PutLong(BUNDLE_ACTIVE_DB_SCREEN_ON_DURATION, screenOnDuration);
924     rdbStore->Update(changeRow, DURATION_LOG_TABLE, valuesBucket);
925     if (changeRow == NO_UPDATE_ROW) {
926         rdbStore->Insert(outRowId, DURATION_LOG_TABLE, valuesBucket);
927     }
928 }
929 
GetDurationData()930 pair<int64_t, int64_t> BundleActiveUsageDatabase::GetDurationData()
931 {
932     lock_guard<ffrt::mutex> lock(databaseMutex_);
933     pair<int64_t, int64_t> durationData;
934     if (durationTableName_ == UNKNOWN_TABLE_NAME) {
935         return durationData;
936     }
937     string queryDurationDataSql = "select * from " + DURATION_LOG_TABLE;
938     auto bundleActiveResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX,
939         queryDurationDataSql,
940         vector<string> {});
941     if (bundleActiveResult == nullptr) {
942         return durationData;
943     }
944     int32_t tableRowNumber;
945     bundleActiveResult->GetRowCount(tableRowNumber);
946     if (tableRowNumber == DURATION_TABLE_ROW_NUMBER) {
947         bundleActiveResult->GoToRow(tableRowNumber - DURATION_TABLE_ROW_NUMBER);
948         bundleActiveResult->GetLong(BOOT_BASED_DURATION_COLUMN_INDEX, durationData.first);
949         bundleActiveResult->GetLong(SCREEN_ON_DURATION_COLUMN_INDEX, durationData.second);
950     }
951     return durationData;
952 }
953 
FlushPackageInfo(uint32_t databaseType,const BundleActivePeriodStats & stats)954 void BundleActiveUsageDatabase::FlushPackageInfo(uint32_t databaseType, const BundleActivePeriodStats &stats)
955 {
956     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
957     if (rdbStore == nullptr) {
958         BUNDLE_ACTIVE_LOGE("flush package info fail, rdbStore is nullptr");
959         return;
960     }
961     string tableName = PACKAGE_LOG_TABLE + to_string(stats.beginTime_);
962     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
963     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
964     NativeRdb::ValuesBucket valuesBucket;
965     vector<string> queryCondition;
966     for (auto iter = stats.bundleStats_.begin(); iter != stats.bundleStats_.end(); iter++) {
967         if (iter->second == nullptr || (iter->second->totalInFrontTime_ == 0 &&
968             iter->second->totalContiniousTaskUsedTime_ == 0)) {
969             continue;
970         }
971         queryCondition.push_back(to_string(stats.userId_));
972         queryCondition.push_back(iter->second->bundleName_);
973         queryCondition.push_back(to_string(iter->second->uid_));
974         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_BUNDLE_STARTED_COUNT, iter->second->startCount_);
975         int64_t lastTimeUsedAdjusted = iter->second->lastTimeUsed_ == -1 ?
976             iter->second->lastTimeUsed_ : iter->second->lastTimeUsed_ - stats.beginTime_;
977         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME, lastTimeUsedAdjusted);
978         int64_t lastContinuousTaskUsedAdjusted = iter->second->lastContiniousTaskUsed_ == -1 ?
979             iter->second->lastContiniousTaskUsed_ : iter->second->lastContiniousTaskUsed_ - stats.beginTime_;
980         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME_CONTINUOUS_TASK, lastContinuousTaskUsedAdjusted);
981         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_TOTAL_TIME, iter->second->totalInFrontTime_);
982         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_TOTAL_TIME_CONTINUOUS_TASK, iter->second->totalContiniousTaskUsedTime_);
983         rdbStore->Update(changeRow, tableName, valuesBucket, "userId = ? and bundleName = ? and uid = ?",
984             queryCondition);
985         if (changeRow == NO_UPDATE_ROW) {
986             valuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, iter->second->bundleName_);
987             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, stats.userId_);
988             valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, iter->second->uid_);
989             rdbStore->Insert(outRowId, tableName, valuesBucket);
990             outRowId = BUNDLE_ACTIVE_FAIL;
991         } else {
992             changeRow = BUNDLE_ACTIVE_FAIL;
993         }
994         valuesBucket.Clear();
995         queryCondition.clear();
996     }
997 }
998 
GetCurrentUsageData(int32_t databaseType,int32_t userId)999 shared_ptr<BundleActivePeriodStats> BundleActiveUsageDatabase::GetCurrentUsageData(int32_t databaseType,
1000     int32_t userId)
1001 {
1002     lock_guard<ffrt::mutex> lock(databaseMutex_);
1003     if (databaseType < 0 || databaseType >= static_cast<int32_t>(sortedTableArray_.size())) {
1004         return nullptr;
1005     }
1006     int32_t tableNumber = static_cast<int32_t>(sortedTableArray_.at(databaseType).size());
1007     if (tableNumber == TABLE_NOT_EXIST) {
1008         return nullptr;
1009     }
1010     int64_t currentPackageTime = sortedTableArray_.at(databaseType).at(tableNumber - 1);
1011     auto intervalStats = make_shared<BundleActivePeriodStats>(userId, currentPackageTime);
1012     string packageTableName = PACKAGE_LOG_TABLE + to_string(currentPackageTime);
1013     string queryPackageSql = "select * from " + packageTableName + " where userId = ?";
1014     vector<string> queryCondition;
1015     queryCondition.push_back(to_string(userId));
1016     auto bundleActiveResult = QueryStatsInfoByStep(databaseType, queryPackageSql, queryCondition);
1017     if (bundleActiveResult == nullptr) {
1018         return nullptr;
1019     }
1020     int32_t tableRowNumber;
1021     bundleActiveResult->GetRowCount(tableRowNumber);
1022     map<string, shared_ptr<BundleActivePackageStats>> bundleStats;
1023     int64_t relativeLastTimeUsed;
1024     int64_t relativeLastTimeFrontServiceUsed;
1025     for (int32_t i = 0; i < tableRowNumber; i++) {
1026         shared_ptr<BundleActivePackageStats> usageStats = make_shared<BundleActivePackageStats>();
1027         bundleActiveResult->GoToRow(i);
1028         bundleActiveResult->GetInt(USER_ID_COLUMN_INDEX, intervalStats->userId_);
1029         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, usageStats->bundleName_);
1030         bundleActiveResult->GetInt(BUNDLE_STARTED_COUNT_COLUMN_INDEX, usageStats->startCount_);
1031         bundleActiveResult->GetLong(LAST_TIME_COLUMN_INDEX, relativeLastTimeUsed);
1032         usageStats->lastTimeUsed_ = relativeLastTimeUsed == -1 ? -1 : relativeLastTimeUsed + currentPackageTime;
1033         bundleActiveResult->GetLong(LAST_TIME_CONTINUOUS_TASK_COLUMN_INDEX, relativeLastTimeFrontServiceUsed);
1034         usageStats->lastContiniousTaskUsed_ = relativeLastTimeFrontServiceUsed == -1 ? -1 :
1035             relativeLastTimeFrontServiceUsed + currentPackageTime;
1036         bundleActiveResult->GetLong(TOTAL_TIME_COLUMN_INDEX, usageStats->totalInFrontTime_);
1037         bundleActiveResult->GetLong(TOTAL_TIME_CONTINUOUS_TASK_COLUMN_INDEX, usageStats->totalContiniousTaskUsedTime_);
1038         bundleActiveResult->GetInt(PACKAGE_LOG_UID_COLUMN_INDEX, usageStats->uid_);
1039         string bundleStatsKey = usageStats->bundleName_ + std::to_string(usageStats->uid_);
1040         BundleActiveBundleMgrHelper::GetInstance()->InsertPackageUid(usageStats->bundleName_, usageStats->uid_);
1041         bundleStats.insert(pair<string, shared_ptr<BundleActivePackageStats>>(bundleStatsKey, usageStats));
1042     }
1043     intervalStats->bundleStats_ = bundleStats;
1044     if (databaseType == DAILY_DATABASE_INDEX) {
1045         eventBeginTime_ = currentPackageTime;
1046     }
1047     int64_t systemTime = GetSystemTimeMs();
1048     intervalStats->lastTimeSaved_ = systemTime;
1049     return intervalStats;
1050 }
1051 
FlushEventInfo(uint32_t databaseType,BundleActivePeriodStats & stats)1052 void BundleActiveUsageDatabase::FlushEventInfo(uint32_t databaseType, BundleActivePeriodStats &stats)
1053 {
1054     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
1055     if (rdbStore == nullptr) {
1056         BUNDLE_ACTIVE_LOGE("flush event info fail, rdbStore is nullptr");
1057         return;
1058     }
1059     if (eventTableName_ == UNKNOWN_TABLE_NAME) {
1060         CreateEventLogTable(databaseType, stats.beginTime_);
1061     }
1062     int64_t eventTableTime = ParseStartTime(eventTableName_);
1063     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
1064     NativeRdb::ValuesBucket valuesBucket;
1065     for (int32_t i = 0; i < stats.events_.Size(); i++) {
1066         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, stats.userId_);
1067         valuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, stats.events_.events_.at(i).bundleName_);
1068         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_EVENT_ID, stats.events_.events_.at(i).eventId_);
1069         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_TIME_STAMP, stats.events_.events_.at(i).timeStamp_ - eventTableTime);
1070         valuesBucket.PutString(BUNDLE_ACTIVE_DB_ABILITY_ID, stats.events_.events_.at(i).abilityId_);
1071         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, stats.events_.events_.at(i).uid_);
1072         rdbStore->Insert(outRowId, eventTableName_, valuesBucket);
1073         valuesBucket.Clear();
1074     }
1075 }
1076 
GetTableIndexSql(uint32_t databaseType,int64_t tableTime,bool createFlag,int32_t indexFlag)1077 string BundleActiveUsageDatabase::GetTableIndexSql(uint32_t databaseType, int64_t tableTime, bool createFlag,
1078     int32_t indexFlag)
1079 {
1080     string tableIndexSql;
1081     if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
1082         string packageTableIndex = PACKAGE_LOG_TABLE_INDEX_PREFIX + to_string(tableTime);
1083         string PackageTableName = PACKAGE_LOG_TABLE + to_string(tableTime);
1084         if (createFlag) {
1085             tableIndexSql = "CREATE INDEX " + packageTableIndex + " ON "
1086                 + PackageTableName + " (userId, lastTime, bundleName);";
1087         } else {
1088             tableIndexSql = "DROP INDEX " + packageTableIndex;
1089         }
1090     } else if (databaseType == EVENT_DATABASE_INDEX) {
1091         string eventTableIndex = EVENT_LOG_TABLE_INDEX_PREFIX + to_string(tableTime);
1092         string eventTableName = EVENT_LOG_TABLE + to_string(tableTime);
1093         if (createFlag) {
1094             tableIndexSql = "CREATE INDEX " + eventTableIndex + " ON " + eventTableName +
1095                 " (timeStamp, userId, bundleName);";
1096         } else {
1097             tableIndexSql = "DROP INDEX " + eventTableIndex;
1098         }
1099     } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
1100         if (createFlag) {
1101             if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_NORMAL) {
1102                 tableIndexSql = "CREATE INDEX " + BUNDLE_HISTORY_LOG_TABLE_INDEX_PREFIX
1103                     + " ON " + BUNDLE_HISTORY_LOG_TABLE + " (userId, bundleName);";
1104             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_MODULE) {
1105                 tableIndexSql = "CREATE INDEX " + MODULE_RECORD_LOG_TABLE_INDEX_PREFIX
1106                     + " ON " + MODULE_RECORD_LOG_TABLE + to_string(tableTime) + " (userId, bundleName, moduleName);";
1107             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_FORM) {
1108                 tableIndexSql = "CREATE INDEX " + FORM_RECORD_LOG_TABLE_INDEX_PREFIX
1109                     + " ON " + FORM_RECORD_LOG_TABLE + to_string(tableTime) +
1110                     " (userId, moduleName, formName, formDimension, formId);";
1111             }
1112         } else {
1113             if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_NORMAL) {
1114                 tableIndexSql = "DROP INDEX " + BUNDLE_HISTORY_LOG_TABLE_INDEX_PREFIX;
1115             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_MODULE) {
1116                 tableIndexSql = "DROP INDEX " + MODULE_RECORD_LOG_TABLE_INDEX_PREFIX;
1117             } else if (indexFlag == BUNDLE_ACTIVE_DB_INDEX_FORM) {
1118                 tableIndexSql = "DROP INDEX " + FORM_RECORD_LOG_TABLE_INDEX_PREFIX;
1119             }
1120         }
1121     } else {
1122         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}d", databaseType);
1123     }
1124     return tableIndexSql;
1125 }
1126 
SetNewIndexWhenTimeChanged(uint32_t databaseType,int64_t tableOldTime,int64_t tableNewTime,std::shared_ptr<NativeRdb::RdbStore> rdbStore)1127 int32_t BundleActiveUsageDatabase::SetNewIndexWhenTimeChanged(uint32_t databaseType, int64_t tableOldTime,
1128     int64_t tableNewTime, std::shared_ptr<NativeRdb::RdbStore> rdbStore)
1129 {
1130     if (rdbStore == nullptr) {
1131         return BUNDLE_ACTIVE_FAIL;
1132     }
1133     if (databaseType == APP_GROUP_DATABASE_INDEX) {
1134         string oldModuleTableIndex = GetTableIndexSql(databaseType, tableOldTime, false,
1135             BUNDLE_ACTIVE_DB_INDEX_MODULE);
1136         int32_t deleteResult = rdbStore->ExecuteSql(oldModuleTableIndex);
1137         if (deleteResult != NativeRdb::E_OK) {
1138             return BUNDLE_ACTIVE_FAIL;
1139         }
1140         string newModuleTableIndex = GetTableIndexSql(databaseType, tableNewTime, true,
1141             BUNDLE_ACTIVE_DB_INDEX_MODULE);
1142         int32_t createResult = rdbStore->ExecuteSql(newModuleTableIndex);
1143         if (createResult != NativeRdb::E_OK) {
1144             return BUNDLE_ACTIVE_FAIL;
1145         }
1146         string oldFormTableIndex = GetTableIndexSql(databaseType, tableOldTime, false,
1147             BUNDLE_ACTIVE_DB_INDEX_FORM);
1148         deleteResult = rdbStore->ExecuteSql(oldFormTableIndex);
1149         if (deleteResult != NativeRdb::E_OK) {
1150             return BUNDLE_ACTIVE_FAIL;
1151         }
1152         string newFormTableIndex = GetTableIndexSql(databaseType, tableNewTime, true,
1153             BUNDLE_ACTIVE_DB_INDEX_FORM);
1154         createResult = rdbStore->ExecuteSql(newFormTableIndex);
1155         if (createResult != NativeRdb::E_OK) {
1156             return BUNDLE_ACTIVE_FAIL;
1157         }
1158     } else {
1159         string oldTableIndex = GetTableIndexSql(databaseType, tableOldTime, false);
1160         int32_t deleteResult = rdbStore->ExecuteSql(oldTableIndex);
1161         if (deleteResult != NativeRdb::E_OK) {
1162             return BUNDLE_ACTIVE_FAIL;
1163         }
1164         string newTableIndex = GetTableIndexSql(databaseType, tableNewTime, true);
1165         int32_t createResult = rdbStore->ExecuteSql(newTableIndex);
1166         if (createResult != NativeRdb::E_OK) {
1167             return BUNDLE_ACTIVE_FAIL;
1168         }
1169     }
1170     return BUNDLE_ACTIVE_SUCCESS;
1171 }
1172 
RenameTableName(uint32_t databaseType,int64_t tableOldTime,int64_t tableNewTime)1173 int32_t BundleActiveUsageDatabase::RenameTableName(uint32_t databaseType, int64_t tableOldTime,
1174     int64_t tableNewTime)
1175 {
1176     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
1177     if (rdbStore == nullptr) {
1178         return BUNDLE_ACTIVE_FAIL;
1179     }
1180     if (databaseType >= 0 && databaseType < sortedTableArray_.size()) {
1181         if (ExecuteRenameTableName(PACKAGE_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1182             return BUNDLE_ACTIVE_FAIL;
1183         }
1184     } else if (databaseType == EVENT_DATABASE_INDEX) {
1185         if (ExecuteRenameTableName(EVENT_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1186             return BUNDLE_ACTIVE_FAIL;
1187         }
1188     } else if (databaseType == APP_GROUP_DATABASE_INDEX) {
1189         if (ExecuteRenameTableName(MODULE_RECORD_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1190             return BUNDLE_ACTIVE_FAIL;
1191         }
1192         if (ExecuteRenameTableName(FORM_RECORD_LOG_TABLE, tableOldTime, tableNewTime, rdbStore) != ERR_OK) {
1193             return BUNDLE_ACTIVE_FAIL;
1194         }
1195     }
1196     int32_t setResult = SetNewIndexWhenTimeChanged(databaseType, tableOldTime, tableNewTime, rdbStore);
1197     if (setResult != BUNDLE_ACTIVE_SUCCESS) {
1198         return BUNDLE_ACTIVE_FAIL;
1199     }
1200     return BUNDLE_ACTIVE_SUCCESS;
1201 }
1202 
ExecuteRenameTableName(std::string tablePrefix,int64_t tableOldTime,int64_t tableNewTime,std::shared_ptr<NativeRdb::RdbStore> rdbStore)1203 int32_t BundleActiveUsageDatabase::ExecuteRenameTableName(std::string tablePrefix, int64_t tableOldTime,
1204     int64_t tableNewTime, std::shared_ptr<NativeRdb::RdbStore> rdbStore)
1205 {
1206     if (!rdbStore) {
1207         BUNDLE_ACTIVE_LOGE("execute rename table name fail, rdbstore is nullptr");
1208         return BUNDLE_ACTIVE_FAIL;
1209     }
1210     string oldTableName = tablePrefix + to_string(tableOldTime);
1211     string newTableName = tablePrefix + to_string(tableNewTime);
1212     string renameTableNameSql = "alter table " + oldTableName + " rename to " + newTableName;
1213     int32_t renameTableName = rdbStore->ExecuteSql(renameTableNameSql);
1214     if (renameTableName != NativeRdb::E_OK) {
1215         BUNDLE_ACTIVE_LOGE("Rename table failed");
1216         return BUNDLE_ACTIVE_FAIL;
1217     }
1218     return ERR_OK;
1219 }
1220 
GetOptimalIntervalType(int64_t beginTime,int64_t endTime)1221 int32_t BundleActiveUsageDatabase::GetOptimalIntervalType(int64_t beginTime, int64_t endTime)
1222 {
1223     lock_guard<ffrt::mutex> lock(databaseMutex_);
1224     int32_t optimalIntervalType = -1;
1225     int64_t leastTimeDiff = numeric_limits<int64_t>::max();
1226     for (int32_t i = static_cast<int32_t>(sortedTableArray_.size() - 1); i >= 0; i--) {
1227         int32_t index = NearIndexOnOrBeforeCurrentTime(beginTime, sortedTableArray_.at(i));
1228         int32_t size = static_cast<int32_t>(sortedTableArray_.at(i).size());
1229         if (index >= 0 && index < size) {
1230             int64_t diff = abs(sortedTableArray_.at(i).at(index) - beginTime);
1231             if (diff < leastTimeDiff) {
1232                 leastTimeDiff = diff;
1233                 optimalIntervalType = i;
1234             }
1235         }
1236     }
1237     BUNDLE_ACTIVE_LOGI("optimalIntervalType is %{public}d", optimalIntervalType);
1238     return optimalIntervalType;
1239 }
1240 
RemoveOldData(int64_t currentTime)1241 void BundleActiveUsageDatabase::RemoveOldData(int64_t currentTime)
1242 {
1243     lock_guard<ffrt::mutex> lock(databaseMutex_);
1244     calendar_->SetMilliseconds(currentTime);
1245     calendar_->IncreaseYears(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[YEARLY_DATABASE_INDEX]);
1246     std::unique_ptr<std::vector<int64_t>> overdueYearsTableCreateTime = GetOverdueTableCreateTime(YEARLY_DATABASE_INDEX,
1247         calendar_->GetMilliseconds());
1248     if (overdueYearsTableCreateTime != nullptr) {
1249         for (uint32_t i = 0; i < overdueYearsTableCreateTime->size(); i++) {
1250             DeleteInvalidTable(YEARLY_DATABASE_INDEX, overdueYearsTableCreateTime->at(i));
1251         }
1252     }
1253     calendar_->SetMilliseconds(currentTime);
1254     calendar_->IncreaseMonths(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[MONTHLY_DATABASE_INDEX]);
1255     std::unique_ptr<std::vector<int64_t>> overdueMonthsTableCreateTime
1256         = GetOverdueTableCreateTime(MONTHLY_DATABASE_INDEX, calendar_->GetMilliseconds());
1257     if (overdueMonthsTableCreateTime != nullptr) {
1258         for (uint32_t i = 0; i < overdueMonthsTableCreateTime->size(); i++) {
1259             DeleteInvalidTable(MONTHLY_DATABASE_INDEX, overdueMonthsTableCreateTime->at(i));
1260         }
1261     }
1262     calendar_->SetMilliseconds(currentTime);
1263     calendar_->IncreaseWeeks(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[WEEKLY_DATABASE_INDEX]);
1264     std::unique_ptr<std::vector<int64_t>> overdueWeeksTableCreateTime = GetOverdueTableCreateTime(WEEKLY_DATABASE_INDEX,
1265         calendar_->GetMilliseconds());
1266     if (overdueWeeksTableCreateTime != nullptr) {
1267         for (uint32_t i = 0; i < overdueWeeksTableCreateTime->size(); i++) {
1268             DeleteInvalidTable(WEEKLY_DATABASE_INDEX, overdueWeeksTableCreateTime->at(i));
1269         }
1270     }
1271     calendar_->SetMilliseconds(currentTime);
1272     calendar_->IncreaseDays(-1 * MAX_FILES_EVERY_INTERVAL_TYPE[DAILY_DATABASE_INDEX]);
1273     std::unique_ptr<std::vector<int64_t>> overdueDaysTableCreateTime = GetOverdueTableCreateTime(DAILY_DATABASE_INDEX,
1274         calendar_->GetMilliseconds());
1275     if (overdueDaysTableCreateTime != nullptr) {
1276         for (uint32_t i = 0; i < overdueDaysTableCreateTime->size(); i++) {
1277             DeleteInvalidTable(DAILY_DATABASE_INDEX, overdueDaysTableCreateTime->at(i));
1278         }
1279     }
1280     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
1281         HandleTableInfo(i);
1282         DeleteExcessiveTableData(i);
1283     }
1284 }
1285 
RenewTableTime(int64_t timeDiffMillis)1286 void BundleActiveUsageDatabase::RenewTableTime(int64_t timeDiffMillis)
1287 {
1288     lock_guard<ffrt::mutex> lock(databaseMutex_);
1289     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
1290         if (sortedTableArray_.at(i).empty()) {
1291             continue;
1292         }
1293         vector<int64_t> tableArray = sortedTableArray_.at(i);
1294         for (uint32_t j = 0; j < tableArray.size(); j++) {
1295             int64_t newTime = tableArray.at(j) + timeDiffMillis;
1296             BUNDLE_ACTIVE_LOGI("new table time is %{public}lld", (long long)newTime);
1297             if (newTime < 0) {
1298                 DeleteInvalidTable(i, tableArray.at(j));
1299             } else {
1300                 RenameTableName(i, tableArray.at(j), newTime);
1301             }
1302         }
1303         sortedTableArray_.at(i).clear();
1304         HandleTableInfo(i);
1305         DeleteExcessiveTableData(i);
1306     }
1307     if (eventTableName_ != UNKNOWN_TABLE_NAME) {
1308         int64_t oldTime = ParseStartTime(eventTableName_);
1309         int64_t newTime = oldTime + timeDiffMillis;
1310         if (newTime < 0) {
1311             int32_t deletedResult = DeleteInvalidTable(EVENT_DATABASE_INDEX, oldTime);
1312             if (deletedResult == BUNDLE_ACTIVE_SUCCESS) {
1313                 eventTableName_ = UNKNOWN_TABLE_NAME;
1314             }
1315         } else {
1316             int32_t renamedResult = RenameTableName(EVENT_DATABASE_INDEX, oldTime, newTime);
1317             if (renamedResult == BUNDLE_ACTIVE_SUCCESS) {
1318                 eventTableName_ = EVENT_LOG_TABLE + to_string(newTime);
1319             }
1320         }
1321     }
1322     if (formRecordsTableName_ != UNKNOWN_TABLE_NAME && moduleRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1323         int64_t oldTime = ParseStartTime(moduleRecordsTableName_);
1324         int64_t newTime = oldTime + timeDiffMillis;
1325         int32_t renamedResult = RenameTableName(APP_GROUP_DATABASE_INDEX, oldTime, newTime);
1326         if (renamedResult == BUNDLE_ACTIVE_SUCCESS) {
1327             moduleRecordsTableName_ = MODULE_RECORD_LOG_TABLE + to_string(newTime);
1328             formRecordsTableName_ = FORM_RECORD_LOG_TABLE + to_string(newTime);
1329         }
1330     }
1331 }
1332 
UpdateEventData(int32_t databaseType,BundleActivePeriodStats & stats)1333 void BundleActiveUsageDatabase::UpdateEventData(int32_t databaseType, BundleActivePeriodStats &stats)
1334 {
1335     lock_guard<ffrt::mutex> lock(databaseMutex_);
1336     CheckDatabaseFile(databaseType);
1337     if (databaseType != DAILY_DATABASE_INDEX) {
1338         return;
1339     }
1340     if (stats.events_.Size() != 0) {
1341         CheckDatabaseFile(EVENT_DATABASE_INDEX);
1342         FlushEventInfo(EVENT_DATABASE_INDEX, stats);
1343     }
1344 }
1345 
UpdateBundleUsageData(int32_t databaseType,BundleActivePeriodStats & stats)1346 void BundleActiveUsageDatabase::UpdateBundleUsageData(int32_t databaseType, BundleActivePeriodStats &stats)
1347 {
1348     lock_guard<ffrt::mutex> lock(databaseMutex_);
1349     if (databaseType < 0 || databaseType >= EVENT_DATABASE_INDEX) {
1350         BUNDLE_ACTIVE_LOGE("databaseType is invalid : %{public}d", databaseType);
1351         return;
1352     }
1353     CheckDatabaseFile(databaseType);
1354     int32_t packageTableIndex = BundleActiveBinarySearch::GetInstance()->BinarySearch(
1355         sortedTableArray_.at(databaseType), stats.beginTime_);
1356     if (packageTableIndex < 0) {
1357         CreatePackageLogTable(databaseType, stats.beginTime_);
1358         if (databaseType == DAILY_DATABASE_INDEX) {
1359             eventBeginTime_ = stats.beginTime_;
1360             DeleteExcessiveTableData(EVENT_DATABASE_INDEX);
1361         }
1362         sortedTableArray_.at(databaseType).push_back(stats.beginTime_);
1363         sort(sortedTableArray_.at(databaseType).begin(), sortedTableArray_.at(databaseType).end());
1364         DeleteExcessiveTableData(databaseType);
1365     }
1366     FlushPackageInfo(databaseType, stats);
1367     int64_t systemTime = GetSystemTimeMs();
1368     stats.lastTimeSaved_ = systemTime;
1369 }
1370 
GetDbIndex(const int64_t beginTime,const int64_t endTime,const int32_t databaseType,int32_t & startIndex,int32_t & endIndex)1371 bool BundleActiveUsageDatabase::GetDbIndex(const int64_t beginTime, const int64_t endTime,
1372     const int32_t databaseType, int32_t &startIndex, int32_t &endIndex)
1373 {
1374     if (databaseType < 0 || databaseType >= static_cast<int32_t>(sortedTableArray_.size())) {
1375         BUNDLE_ACTIVE_LOGE("databaseType is invalid, databaseType = %{public}d", databaseType);
1376         return false;
1377     }
1378     if (endTime <= beginTime) {
1379         BUNDLE_ACTIVE_LOGE("endTime(%{public}lld) <= beginTime(%{public}lld)",
1380             (long long)endTime, (long long)beginTime);
1381         return false;
1382     }
1383     startIndex = NearIndexOnOrBeforeCurrentTime(beginTime, sortedTableArray_.at(databaseType));
1384     if (startIndex < 0) {
1385         startIndex = 0;
1386     }
1387     endIndex = NearIndexOnOrBeforeCurrentTime(endTime, sortedTableArray_.at(databaseType));
1388     if (endIndex < 0) {
1389         return false;
1390     }
1391     if (sortedTableArray_.at(databaseType).at(endIndex) == endTime) {
1392         endIndex--;
1393         if (endIndex < 0) {
1394         return false;
1395         }
1396     }
1397     return true;
1398 }
1399 
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)1400 void BundleActiveUsageDatabase::GetQuerySqlCommand(const int64_t beginTime,
1401     const int64_t endTime, const int32_t databaseType,
1402     const int32_t index, const int32_t startIndex, const int32_t endIndex, const int32_t userId,
1403     std::vector<std::string> &queryCondition, std::string &queryPackageSql)
1404 {
1405     string packageTableName;
1406     int64_t packageTableTime = sortedTableArray_.at(databaseType).at(index);
1407     packageTableName = PACKAGE_LOG_TABLE + to_string(packageTableTime);
1408     queryCondition.push_back(to_string(userId));
1409     if (startIndex == endIndex) {
1410         int64_t diff = beginTime - packageTableTime;
1411         if (diff >= 0) {
1412             queryCondition.push_back(to_string(diff));
1413         } else {
1414             queryCondition.push_back(to_string(LAST_TIME_IN_MILLIS_MIN));
1415         }
1416         queryCondition.push_back(to_string(endTime - packageTableTime));
1417         queryPackageSql = "select * from " + packageTableName +
1418             " where userId = ? and lastTime >= ? and lastTime <= ?";
1419     } else {
1420         if (index == startIndex) {
1421             int64_t diff = beginTime - packageTableTime;
1422             if (diff >= 0) {
1423                 queryCondition.push_back(to_string(diff));
1424             } else {
1425                 queryCondition.push_back(to_string(LAST_TIME_IN_MILLIS_MIN));
1426             }
1427             queryPackageSql = "select * from " + packageTableName + " where userId = ? and lastTime >= ?";
1428         } else if (index == endIndex) {
1429             queryCondition.push_back(to_string(endTime - packageTableTime));
1430             queryPackageSql = "select * from " + packageTableName + " where userId = ? and lastTime <= ?";
1431         } else {
1432             queryPackageSql = "select * from " + packageTableName + " where userId = ?";
1433         }
1434     }
1435 }
1436 
QueryDatabaseUsageStats(int32_t databaseType,int64_t beginTime,int64_t endTime,int32_t userId,const std::string & bundleName)1437 vector<BundleActivePackageStats> BundleActiveUsageDatabase::QueryDatabaseUsageStats(int32_t databaseType,
1438     int64_t beginTime, int64_t endTime, int32_t userId, const std::string& bundleName)
1439 {
1440     lock_guard<ffrt::mutex> lock(databaseMutex_);
1441     vector<BundleActivePackageStats> databaseUsageStats;
1442     int32_t startIndex = 0;
1443     int32_t endIndex = 0;
1444     if (!GetDbIndex(beginTime, endTime, databaseType, startIndex, endIndex)) {
1445         return databaseUsageStats;
1446     }
1447     for (int32_t i = startIndex; i <= endIndex; i++) {
1448         string queryPackageSql;
1449         vector<string> queryCondition;
1450 
1451         GetQuerySqlCommand(beginTime, endTime, databaseType, i, startIndex,
1452             endIndex, userId, queryCondition, queryPackageSql);
1453         if (bundleName != "") {
1454             queryCondition.push_back(bundleName);
1455             queryPackageSql += " and bundleName = ?";
1456         }
1457         auto bundleActiveResult = QueryStatsInfoByStep(databaseType, queryPackageSql,
1458             queryCondition);
1459         if (bundleActiveResult == nullptr) {
1460             return databaseUsageStats;
1461         }
1462         int32_t tableRowNumber;
1463         bundleActiveResult->GetRowCount(tableRowNumber);
1464         BundleActivePackageStats usageStats;
1465         int64_t relativeLastTimeUsed;
1466         int64_t relativeLastTimeFrontServiceUsed;
1467         int64_t packageTableTime = sortedTableArray_.at(databaseType).at(i);
1468         for (int32_t j = 0; j < tableRowNumber; j++) {
1469             bundleActiveResult->GoToRow(j);
1470             bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, usageStats.bundleName_);
1471             bundleActiveResult->GetInt(BUNDLE_STARTED_COUNT_COLUMN_INDEX, usageStats.startCount_);
1472             bundleActiveResult->GetLong(LAST_TIME_COLUMN_INDEX, usageStats.lastTimeUsed_);
1473             bundleActiveResult->GetLong(LAST_TIME_COLUMN_INDEX, relativeLastTimeUsed);
1474             usageStats.lastTimeUsed_ = relativeLastTimeUsed == -1 ? -1 :
1475                 relativeLastTimeUsed + packageTableTime;
1476             bundleActiveResult->GetLong(LAST_TIME_CONTINUOUS_TASK_COLUMN_INDEX, relativeLastTimeFrontServiceUsed);
1477             usageStats.lastContiniousTaskUsed_ = relativeLastTimeFrontServiceUsed == -1 ? -1 :
1478                 relativeLastTimeFrontServiceUsed + packageTableTime;
1479             bundleActiveResult->GetLong(TOTAL_TIME_COLUMN_INDEX, usageStats.totalInFrontTime_);
1480             bundleActiveResult->GetLong(TOTAL_TIME_CONTINUOUS_TASK_COLUMN_INDEX,
1481                 usageStats.totalContiniousTaskUsedTime_);
1482             bundleActiveResult->GetInt(PACKAGE_LOG_UID_COLUMN_INDEX, usageStats.uid_);
1483             usageStats.userId_ = userId;
1484             databaseUsageStats.push_back(usageStats);
1485         }
1486         queryCondition.clear();
1487     }
1488     return databaseUsageStats;
1489 }
1490 
QueryDatabaseEvents(int64_t beginTime,int64_t endTime,int32_t userId,string bundleName)1491 vector<BundleActiveEvent> BundleActiveUsageDatabase::QueryDatabaseEvents(int64_t beginTime, int64_t endTime,
1492     int32_t userId, string bundleName)
1493 {
1494     lock_guard<ffrt::mutex> lock(databaseMutex_);
1495     vector<BundleActiveEvent> databaseEvents;
1496     int64_t eventTableTime = ParseStartTime(eventTableName_);
1497     if (JudgeQueryCondition(beginTime, endTime, eventTableTime) == QUERY_CONDITION_INVALID) {
1498         return databaseEvents;
1499     }
1500     vector<string> queryCondition;
1501     int64_t diff = beginTime - eventTableTime;
1502     if (diff >= 0) {
1503         queryCondition.push_back(to_string(diff));
1504     } else {
1505         queryCondition.push_back(to_string(EVENT_TIME_IN_MILLIS_MIN));
1506     }
1507     queryCondition.push_back(to_string(endTime - eventTableTime));
1508     queryCondition.push_back(to_string(userId));
1509     string queryEventSql;
1510     if (bundleName.empty()) {
1511         queryEventSql = "select * from " + eventTableName_ + " where timeStamp >= ? and timeStamp <= ? and userId = ?";
1512     } else {
1513         queryCondition.push_back(bundleName);
1514         queryEventSql = "select * from " + eventTableName_ +
1515             " where timeStamp >= ? and timeStamp <= ? and userId = ? and bundleName = ?";
1516     }
1517     auto bundleActiveResult = QueryStatsInfoByStep(EVENT_DATABASE_INDEX,
1518         queryEventSql, queryCondition);
1519     if (bundleActiveResult == nullptr) {
1520         return databaseEvents;
1521     }
1522     int32_t tableRowNumber;
1523     bundleActiveResult->GetRowCount(tableRowNumber);
1524     BundleActiveEvent event;
1525     string relativeTimeStamp;
1526     for (int32_t i = 0; i < tableRowNumber; i++) {
1527         bundleActiveResult->GoToRow(i);
1528         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, event.bundleName_);
1529         bundleActiveResult->GetInt(EVENT_ID_COLUMN_INDEX, event.eventId_);
1530         bundleActiveResult->GetString(TIME_STAMP_COLUMN_INDEX, relativeTimeStamp);
1531         event.timeStamp_ = atoll(relativeTimeStamp.c_str()) + eventTableTime;
1532         bundleActiveResult->GetString(ABILITY_ID_COLUMN_INDEX, event.abilityId_);
1533         bundleActiveResult->GetInt(EVENT_UID_COLUMN_INDEX, event.uid_);
1534         databaseEvents.push_back(event);
1535     }
1536     return databaseEvents;
1537 }
1538 
OnPackageUninstalled(const int32_t userId,const string & bundleName,const int32_t uid,const int32_t appIndex)1539 void BundleActiveUsageDatabase::OnPackageUninstalled(const int32_t userId, const string& bundleName,
1540     const int32_t uid, const int32_t appIndex)
1541 {
1542     lock_guard<ffrt::mutex> lock(databaseMutex_);
1543     for (uint32_t i = 0; i < sortedTableArray_.size(); i++) {
1544         if (sortedTableArray_.at(i).empty()) {
1545             continue;
1546         }
1547         for (uint32_t j = 0; j < sortedTableArray_.at(i).size(); j++) {
1548             string packageTableName = PACKAGE_LOG_TABLE + to_string(sortedTableArray_.at(i).at(j));
1549             DeleteUninstalledInfo(userId, bundleName, uid, packageTableName, i, appIndex);
1550         }
1551     }
1552     if (eventTableName_ != UNKNOWN_TABLE_NAME) {
1553         DeleteUninstalledInfo(userId, bundleName, uid, eventTableName_, EVENT_DATABASE_INDEX, appIndex);
1554     }
1555     if (bundleHistoryTableName_ != UNKNOWN_TABLE_NAME) {
1556         DeleteUninstalledInfo(userId, bundleName, uid, bundleHistoryTableName_, APP_GROUP_DATABASE_INDEX, appIndex);
1557     }
1558     if (moduleRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1559         DeleteUninstalledInfo(userId, bundleName, uid, moduleRecordsTableName_, APP_GROUP_DATABASE_INDEX, appIndex);
1560     }
1561     if (formRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1562         DeleteUninstalledInfo(userId, bundleName, uid, formRecordsTableName_, APP_GROUP_DATABASE_INDEX, appIndex);
1563     }
1564 }
1565 
DeleteUninstalledInfo(const int32_t userId,const string & bundleName,const int32_t uid,const string & tableName,uint32_t databaseType,const int32_t appIndex)1566 void BundleActiveUsageDatabase::DeleteUninstalledInfo(const int32_t userId, const string& bundleName,
1567     const int32_t uid, const string& tableName, uint32_t databaseType, const int32_t appIndex)
1568 {
1569     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(databaseType);
1570     if (rdbStore == nullptr) {
1571         BUNDLE_ACTIVE_LOGE("delete uninstalled info fail, rdbStore is nullptr");
1572         return;
1573     }
1574     int32_t deletedRows = BUNDLE_ACTIVE_FAIL;
1575     vector<string> queryCondition;
1576     queryCondition.push_back(to_string(userId));
1577     if (bundleName.empty()) {
1578         rdbStore->Delete(deletedRows, tableName, "userId = ?", queryCondition);
1579         return;
1580     }
1581     if (appIndex == MAIN_APP_INDEX) {
1582         queryCondition.push_back(bundleName);
1583         rdbStore->Delete(deletedRows, tableName, "userId = ? and bundleName = ?", queryCondition);
1584         return;
1585     }
1586     queryCondition.push_back(bundleName);
1587     queryCondition.push_back(to_string(uid));
1588     rdbStore->Delete(deletedRows, tableName, "userId = ? and bundleName = ? and uid = ?", queryCondition);
1589 }
1590 
GetSystemTimeMs()1591 int64_t BundleActiveUsageDatabase::GetSystemTimeMs()
1592 {
1593     time_t now;
1594     (void)time(&now);  // unit is seconds.
1595     if (static_cast<int64_t>(now) < 0) {
1596         BUNDLE_ACTIVE_LOGE("Get now time error");
1597         return 0;
1598     }
1599     auto tarEndTimePoint = std::chrono::system_clock::from_time_t(now);
1600     auto tarDuration = std::chrono::duration_cast<std::chrono::milliseconds>(tarEndTimePoint.time_since_epoch());
1601     int64_t tarDate = tarDuration.count();
1602     if (tarDate < 0) {
1603         BUNDLE_ACTIVE_LOGE("tarDuration is less than 0.");
1604         return -1;
1605     }
1606     return static_cast<int64_t>(tarDate);
1607 }
1608 
UpdateModuleData(const int32_t userId,std::map<std::string,std::shared_ptr<BundleActiveModuleRecord>> & moduleRecords,const int64_t timeStamp)1609 void BundleActiveUsageDatabase::UpdateModuleData(const int32_t userId,
1610     std::map<std::string, std::shared_ptr<BundleActiveModuleRecord>>& moduleRecords, const int64_t timeStamp)
1611 {
1612     lock_guard<ffrt::mutex> lock(databaseMutex_);
1613     CheckDatabaseFile(APP_GROUP_DATABASE_INDEX);
1614     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
1615     if (rdbStore == nullptr) {
1616         BUNDLE_ACTIVE_LOGE("update module data fail, rdbStore is nullptr");
1617         return;
1618     }
1619     CreateRecordTable(timeStamp);
1620     int64_t moduleTableTime = ParseStartTime(moduleRecordsTableName_);
1621     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
1622     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
1623     NativeRdb::ValuesBucket moduleValuesBucket;
1624     vector<string> queryCondition;
1625     for (const auto& oneModuleRecord : moduleRecords) {
1626         if (oneModuleRecord.second) {
1627             queryCondition.emplace_back(to_string(oneModuleRecord.second->userId_));
1628             queryCondition.emplace_back(oneModuleRecord.second->bundleName_);
1629             queryCondition.emplace_back(oneModuleRecord.second->moduleName_);
1630             queryCondition.emplace_back(to_string(oneModuleRecord.second->uid_));
1631             moduleValuesBucket.PutInt(BUNDLE_ACTIVE_DB_MODULE_LAUNCHED_COUNT, oneModuleRecord.second->launchedCount_);
1632             int64_t adjustLastTime = oneModuleRecord.second->lastModuleUsedTime_ != -1 ?
1633                 oneModuleRecord.second->lastModuleUsedTime_ - moduleTableTime : -1;
1634             moduleValuesBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME, adjustLastTime);
1635             rdbStore->Update(changeRow, moduleRecordsTableName_, moduleValuesBucket,
1636                 "userId = ? and bundleName = ? and moduleName = ? and uid = ?", queryCondition);
1637             if (changeRow == NO_UPDATE_ROW) {
1638                 moduleValuesBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, oneModuleRecord.second->userId_);
1639                 moduleValuesBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, oneModuleRecord.second->bundleName_);
1640                 moduleValuesBucket.PutString(BUNDLE_ACTIVE_DB_MODULE_NAME, oneModuleRecord.second->moduleName_);
1641                 moduleValuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, oneModuleRecord.second->uid_);
1642                 rdbStore->Insert(outRowId, moduleRecordsTableName_, moduleValuesBucket);
1643                 outRowId = BUNDLE_ACTIVE_FAIL;
1644                 changeRow = BUNDLE_ACTIVE_FAIL;
1645             } else {
1646                 changeRow = BUNDLE_ACTIVE_FAIL;
1647             }
1648             moduleValuesBucket.Clear();
1649             queryCondition.clear();
1650             for (const auto& oneFormRecord : oneModuleRecord.second->formRecords_) {
1651                 UpdateFormData(oneModuleRecord.second->userId_, oneModuleRecord.second->bundleName_,
1652                     oneModuleRecord.second->moduleName_, oneFormRecord, rdbStore);
1653             }
1654         }
1655     }
1656 }
1657 
CreateRecordTable(const int64_t timeStamp)1658 void BundleActiveUsageDatabase::CreateRecordTable(const int64_t timeStamp)
1659 {
1660     if (moduleRecordsTableName_ == UNKNOWN_TABLE_NAME) {
1661         CreateModuleRecordTable(APP_GROUP_DATABASE_INDEX, timeStamp);
1662     }
1663     if (formRecordsTableName_ == UNKNOWN_TABLE_NAME) {
1664         CreateFormRecordTable(APP_GROUP_DATABASE_INDEX, timeStamp);
1665     }
1666 }
1667 
UpdateFormData(const int32_t userId,const std::string bundleName,const string moduleName,const BundleActiveFormRecord & formRecord,std::shared_ptr<NativeRdb::RdbStore> rdbStore)1668 void BundleActiveUsageDatabase::UpdateFormData(const int32_t userId, const std::string bundleName,
1669     const string moduleName, const BundleActiveFormRecord& formRecord,
1670     std::shared_ptr<NativeRdb::RdbStore> rdbStore)
1671 {
1672     if (rdbStore == nullptr) {
1673         return;
1674     }
1675     int64_t formRecordsTableTime = ParseStartTime(formRecordsTableName_);
1676     NativeRdb::ValuesBucket formValueBucket;
1677     vector<string> queryCondition;
1678     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
1679     int64_t outRowId = BUNDLE_ACTIVE_FAIL;
1680     queryCondition.emplace_back(to_string(userId));
1681     queryCondition.emplace_back(bundleName);
1682     queryCondition.emplace_back(moduleName);
1683     queryCondition.emplace_back(formRecord.formName_);
1684     queryCondition.emplace_back(to_string(formRecord.formDimension_));
1685     queryCondition.emplace_back(to_string(formRecord.formId_));
1686     queryCondition.emplace_back(to_string(formRecord.uid_));
1687     formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_TOUCH_COUNT, formRecord.count_);
1688     int64_t adjustLastTime = formRecord.formLastUsedTime_ != -1 ? formRecord.formLastUsedTime_ -
1689         formRecordsTableTime : -1;
1690     formValueBucket.PutLong(BUNDLE_ACTIVE_DB_LAST_TIME, adjustLastTime);
1691     rdbStore->Update(changeRow, formRecordsTableName_, formValueBucket,
1692         "userId = ? and bundleName = ? and moduleName = ? and formName = ? and formDimension = ? "
1693         "and formId = ?",
1694         queryCondition);
1695     if (changeRow == NO_UPDATE_ROW) {
1696         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_USER_ID, userId);
1697         formValueBucket.PutString(BUNDLE_ACTIVE_DB_BUNDLE_NAME, bundleName);
1698         formValueBucket.PutString(BUNDLE_ACTIVE_DB_MODULE_NAME, moduleName);
1699         formValueBucket.PutString(BUNDLE_ACTIVE_DB_FORM_NAME, formRecord.formName_);
1700         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_DIMENSION, formRecord.formDimension_);
1701         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_ID, formRecord.formId_);
1702         formValueBucket.PutInt(BUNDLE_ACTIVE_DB_FORM_ID, formRecord.uid_);
1703         rdbStore->Insert(outRowId, formRecordsTableName_, formValueBucket);
1704     }
1705 }
1706 
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)1707 void BundleActiveUsageDatabase::RemoveFormData(const int32_t userId, const std::string bundleName,
1708     const std::string moduleName, const std::string formName, const int32_t formDimension,
1709     const int64_t formId, const int32_t uid)
1710 {
1711     lock_guard<ffrt::mutex> lock(databaseMutex_);
1712     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
1713     if (rdbStore == nullptr) {
1714         BUNDLE_ACTIVE_LOGE("remove for data fail, rdbStore is nullptr");
1715         return;
1716     }
1717     int32_t deletedRows = BUNDLE_ACTIVE_FAIL;
1718     if (formRecordsTableName_ != UNKNOWN_TABLE_NAME) {
1719         vector<string> queryCondition;
1720         queryCondition.emplace_back(to_string(userId));
1721         queryCondition.emplace_back(bundleName);
1722         queryCondition.emplace_back(moduleName);
1723         queryCondition.emplace_back(formName);
1724         queryCondition.emplace_back(to_string(formDimension));
1725         queryCondition.emplace_back(to_string(formId));
1726         int32_t ret = rdbStore->Delete(deletedRows, formRecordsTableName_,
1727             "userId = ? and bundleName = ? and moduleName = ? and formName = ? and formDimension = ? "
1728             "and formId = ? and uid = ?",
1729             queryCondition);
1730         if (ret != NativeRdb::E_OK) {
1731             BUNDLE_ACTIVE_LOGE("delete event data failed, rdb error number: %{public}d", ret);
1732         }
1733     }
1734 }
1735 
LoadModuleData(const int32_t userId,std::map<std::string,std::shared_ptr<BundleActiveModuleRecord>> & moduleRecords)1736 void BundleActiveUsageDatabase::LoadModuleData(const int32_t userId, std::map<std::string,
1737     std::shared_ptr<BundleActiveModuleRecord>>& moduleRecords)
1738 {
1739     lock_guard<ffrt::mutex> lock(databaseMutex_);
1740     string queryModuleSql = "select * from " + moduleRecordsTableName_ + " where userId = ?";
1741     vector<string> queryCondition;
1742     queryCondition.emplace_back(to_string(userId));
1743     auto moduleRecordResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX, queryModuleSql,
1744         queryCondition);
1745     if (!moduleRecordResult) {
1746         return;
1747     }
1748     int64_t baseTime = ParseStartTime(moduleRecordsTableName_);
1749     int32_t numOfModuleRecord = 0;
1750     moduleRecordResult->GetRowCount(numOfModuleRecord);
1751     for (int32_t i = 0; i < numOfModuleRecord; i++) {
1752         shared_ptr<BundleActiveModuleRecord> oneModuleRecord = make_shared<BundleActiveModuleRecord>();
1753         moduleRecordResult->GoToRow(i);
1754         moduleRecordResult->GetInt(USER_ID_COLUMN_INDEX, oneModuleRecord->userId_);
1755         moduleRecordResult->GetString(BUNDLE_NAME_COLUMN_INDEX, oneModuleRecord->bundleName_);
1756         moduleRecordResult->GetString(MODULE_NAME_COLUMN_INDEX, oneModuleRecord->moduleName_);
1757         moduleRecordResult->GetInt(MODULE_USED_COUNT_COLUMN_INDEX, oneModuleRecord->launchedCount_);
1758         moduleRecordResult->GetInt(MODULE_UID_COLUMN_INDEX, oneModuleRecord->uid_);
1759         int64_t relativeLastTime = 0;
1760         moduleRecordResult->GetLong(MODULE_LAST_TIME_COLUMN_INDEX, relativeLastTime);
1761         oneModuleRecord->lastModuleUsedTime_ =  relativeLastTime != -1 ? relativeLastTime + baseTime : -1;
1762         string combinedInfo = oneModuleRecord->bundleName_
1763             + " " + to_string(oneModuleRecord->uid_) + " " + oneModuleRecord->moduleName_;
1764         moduleRecords[combinedInfo] = oneModuleRecord;
1765     }
1766 }
1767 
LoadFormData(const int32_t userId,std::map<std::string,std::shared_ptr<BundleActiveModuleRecord>> & moduleRecords)1768 void BundleActiveUsageDatabase::LoadFormData(const int32_t userId, std::map<std::string,
1769     std::shared_ptr<BundleActiveModuleRecord>>& moduleRecords)
1770 {
1771     lock_guard<ffrt::mutex> lock(databaseMutex_);
1772     string queryFormSql = "select * from " + formRecordsTableName_ + " where userId = ?";
1773     vector<string> queryCondition;
1774     queryCondition.emplace_back(to_string(userId));
1775     auto formRecordResult = QueryStatsInfoByStep(APP_GROUP_DATABASE_INDEX, queryFormSql,
1776         queryCondition);
1777     if (!formRecordResult) {
1778         return;
1779     }
1780     int32_t numOfFormRecord = 0;
1781     int64_t baseTime = ParseStartTime(formRecordsTableName_);
1782     formRecordResult->GetRowCount(numOfFormRecord);
1783     for (int32_t i = 0; i < numOfFormRecord; i++) {
1784         BundleActiveFormRecord oneFormRecord;
1785         string moduleName = "";
1786         string bundleName = "";
1787         formRecordResult->GoToRow(i);
1788         formRecordResult->GetInt(USER_ID_COLUMN_INDEX, oneFormRecord.userId_);
1789         formRecordResult->GetString(BUNDLE_NAME_COLUMN_INDEX, bundleName);
1790         formRecordResult->GetString(MODULE_NAME_COLUMN_INDEX, moduleName);
1791         formRecordResult->GetString(FORM_NAME_COLUMN_INDEX, oneFormRecord.formName_);
1792         formRecordResult->GetInt(FORM_DIMENSION_COLUMN_INDEX, oneFormRecord.formDimension_);
1793         formRecordResult->GetLong(FORM_ID_COLUMN_INDEX, oneFormRecord.formId_);
1794         formRecordResult->GetInt(FORM_COUNT_COLUMN_INDEX, oneFormRecord.count_);
1795         formRecordResult->GetInt(FORM_UID_COLUMN_INDEX, oneFormRecord.uid_);
1796         int64_t relativeLastTime = 0;
1797         formRecordResult->GetLong(FORM_LAST_TIME_COLUMN_INDEX, relativeLastTime);
1798         oneFormRecord.formLastUsedTime_ = relativeLastTime != -1 ? relativeLastTime + baseTime : -1;
1799         auto it = moduleRecords.find(bundleName + " " + to_string(oneFormRecord.uid_) + " " + moduleName);
1800         if (it != moduleRecords.end() && it->second) {
1801             it->second->formRecords_.emplace_back(oneFormRecord);
1802         }
1803     }
1804 }
1805 
QueryDeviceEventStats(int32_t eventId,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & eventStats,int32_t userId)1806 void BundleActiveUsageDatabase::QueryDeviceEventStats(int32_t eventId, int64_t beginTime,
1807     int64_t endTime, std::map<std::string, BundleActiveEventStats>& eventStats, int32_t userId)
1808 {
1809     lock_guard<ffrt::mutex> lock(databaseMutex_);
1810     int64_t eventTableTime = ParseStartTime(eventTableName_);
1811     if (JudgeQueryCondition(beginTime, endTime, eventTableTime) == QUERY_CONDITION_INVALID) {
1812         return;
1813     }
1814     vector<string> queryCondition;
1815     int64_t diff = beginTime - eventTableTime;
1816     if (diff >= 0) {
1817         queryCondition.push_back(to_string(diff));
1818     } else {
1819         queryCondition.push_back(to_string(EVENT_TIME_IN_MILLIS_MIN));
1820     }
1821     queryCondition.push_back(to_string(endTime - eventTableTime));
1822     queryCondition.push_back(to_string(userId));
1823     queryCondition.push_back(to_string(eventId));
1824     string queryEventSql = "select * from " + eventTableName_ +
1825             " where timeStamp >= ? and timeStamp <= ? and userId = ? and eventId = ?";
1826     auto bundleActiveResult = QueryStatsInfoByStep(EVENT_DATABASE_INDEX,
1827         queryEventSql, queryCondition);
1828     if (bundleActiveResult == nullptr) {
1829         return;
1830     }
1831     int32_t tableRowNumber;
1832     bundleActiveResult->GetRowCount(tableRowNumber);
1833     if (tableRowNumber == 0) {
1834         return;
1835     }
1836     BundleActiveEventStats event;
1837     event.name_= GetSystemEventName(eventId);
1838     event.count_ = tableRowNumber;
1839     event.eventId_ = eventId;
1840     eventStats.insert(std::pair<std::string, BundleActiveEventStats>(event.name_, event));
1841 }
1842 
GetSystemEventName(const int32_t userId)1843 std::string BundleActiveUsageDatabase::GetSystemEventName(const int32_t userId)
1844 {
1845     std::string systemEventName = "";
1846     switch (userId) {
1847         case BundleActiveEvent::SYSTEM_LOCK:
1848             systemEventName = OPERATION_SYSTEM_LOCK;
1849             break;
1850         case BundleActiveEvent::SYSTEM_UNLOCK:
1851             systemEventName = OPERATION_SYSTEM_UNLOCK;
1852             break;
1853         case BundleActiveEvent::SYSTEM_SLEEP:
1854             systemEventName = OPERATION_SYSTEM_SLEEP;
1855             break;
1856         case BundleActiveEvent::SYSTEM_WAKEUP:
1857             systemEventName = OPERATION_SYSTEM_WAKEUP;
1858             break;
1859         default:
1860             break;
1861     }
1862     return systemEventName;
1863 }
1864 
QueryNotificationEventStats(int32_t eventId,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & notificationEventStats,int32_t userId)1865 void BundleActiveUsageDatabase::QueryNotificationEventStats(int32_t eventId, int64_t beginTime,
1866     int64_t endTime, std::map<std::string, BundleActiveEventStats>& notificationEventStats, int32_t userId)
1867 {
1868     lock_guard<ffrt::mutex> lock(databaseMutex_);
1869     int64_t eventTableTime = ParseStartTime(eventTableName_);
1870     if (JudgeQueryCondition(beginTime, endTime, eventTableTime) == QUERY_CONDITION_INVALID) {
1871         return;
1872     }
1873     vector<string> queryCondition;
1874     int64_t diff = beginTime - eventTableTime;
1875     if (diff >= 0) {
1876         queryCondition.push_back(to_string(diff));
1877     } else {
1878         queryCondition.push_back(to_string(EVENT_TIME_IN_MILLIS_MIN));
1879     }
1880     queryCondition.push_back(to_string(endTime - eventTableTime));
1881     queryCondition.push_back(to_string(userId));
1882     queryCondition.push_back(to_string(eventId));
1883     string queryEventSql = "select * from " + eventTableName_ +
1884             " where timeStamp >= ? and timeStamp <= ? and userId = ? and eventId = ?";
1885     auto bundleActiveResult = QueryStatsInfoByStep(EVENT_DATABASE_INDEX,
1886         queryEventSql, queryCondition);
1887     if (bundleActiveResult == nullptr) {
1888         return;
1889     }
1890     int32_t tableRowNumber;
1891     bundleActiveResult->GetRowCount(tableRowNumber);
1892     if (tableRowNumber == 0) {
1893         return;
1894     }
1895     BundleActiveEventStats event;
1896     std::map<std::string, BundleActiveEventStats>::iterator iter;
1897     for (int32_t i = 0; i < tableRowNumber; i++) {
1898         bundleActiveResult->GoToRow(i);
1899         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, event.name_);
1900         bundleActiveResult->GetInt(EVENT_ID_COLUMN_INDEX, event.eventId_);
1901         bundleActiveResult->GetInt(EVENT_UID_COLUMN_INDEX, event.uid_);
1902         iter = notificationEventStats.find(event.name_);
1903         if (iter != notificationEventStats.end()) {
1904             iter->second.count_++;
1905         } else {
1906             event.count_ = 1;
1907             notificationEventStats.insert(std::pair<std::string, BundleActiveEventStats>(event.name_, event));
1908         }
1909     }
1910 }
1911 
JudgeQueryCondition(const int64_t beginTime,const int64_t endTime,const int64_t eventTableTime)1912 int32_t BundleActiveUsageDatabase::JudgeQueryCondition(const int64_t beginTime,
1913     const int64_t endTime, const int64_t eventTableTime)
1914 {
1915     if (eventTableName_ == UNKNOWN_TABLE_NAME) {
1916         BUNDLE_ACTIVE_LOGE("eventTable does not exist");
1917         return QUERY_CONDITION_INVALID;
1918     }
1919     if (endTime <= beginTime) {
1920         BUNDLE_ACTIVE_LOGE("endTime(%{public}lld) <= beginTime(%{public}lld)",
1921             (long long)endTime, (long long)beginTime);
1922         return QUERY_CONDITION_INVALID;
1923     }
1924     if (endTime < eventTableTime) {
1925         BUNDLE_ACTIVE_LOGE("endTime(%{public}lld) <= eventTableTime(%{public}lld)",
1926             (long long)endTime, (long long)eventTableTime);
1927         return QUERY_CONDITION_INVALID;
1928     }
1929     return QUERY_CONDITION_VALID;
1930 }
1931 }  // namespace DeviceUsageStats
1932 }  // namespace OHOS
1933 
1934