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