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