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