• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <unistd.h>
17 #include <cstdlib>
18 #include <map>
19 #include <limits>
20 #include "bundle_active_constant.h"
21 #include "bundle_active_log.h"
22 #include "bundle_active_package_stats.h"
23 #include "bundle_active_period_stats.h"
24 #include "bundle_active_usage_database.h"
25 #include "bundle_active_account_helper.h"
26 #include "bundle_active_bundle_mgr_helper.h"
27 #include "bundle_active_util.h"
28 
29 namespace OHOS {
30 namespace DeviceUsageStats {
31 using namespace OHOS::NativeRdb;
32 using namespace std;
33 namespace {
34     const int64_t MIN_START_TIME = 0;
35 }
UpgradeDatabase(const int32_t oldVersion,const int32_t curVersion)36 void BundleActiveUsageDatabase::UpgradeDatabase(const int32_t oldVersion, const int32_t curVersion)
37 {
38     BUNDLE_ACTIVE_LOGI("upgradle database oldVersion: %{public}d, curVersion: %{public}d", oldVersion, curVersion);
39     if (oldVersion < curVersion && curVersion == BUNDLE_ACTIVE_CURRENT_VERSION) {
40         if (oldVersion == BUNDLE_ACTIVE_VERSION_V1) {
41             SupportAppTwin();
42             SupportFirstUseTime();
43         }
44         if (oldVersion == BUNDLE_ACTIVE_VERSION_V2) {
45             SupportFirstUseTime();
46         }
47         currentVersion_ = curVersion;
48     }
49 }
50 
SupportAppTwin()51 void BundleActiveUsageDatabase::SupportAppTwin()
52 {
53     vector<vector<string>> allTableName = vector<vector<string>>(ALL_TABLE_ARRAY_NUMBER);
54     for (uint32_t i = 0; i <databaseFiles_.size(); i++) {
55         HandleAllTableName(i, allTableName);
56     }
57 
58     map<string, int32_t> bundleNameUidMap;
59     vector<int32_t> activatedOsAccountIds;
60     BundleActiveAccountHelper::GetActiveUserId(activatedOsAccountIds);
61     for (uint32_t i = 0; i < allTableName.size(); i++) {
62         auto tableNames = allTableName.at(i);
63         shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(i);
64         if (!rdbStore) {
65             BUNDLE_ACTIVE_LOGI("get RdbStore fail, databaseType: %{public}u", i);
66             continue;
67         }
68         for (string tableName: tableNames) {
69             if (DURATION_LOG_TABLE == tableName) {
70                 continue;
71             }
72             AddRdbColumn(rdbStore, tableName, BUNDLE_ACTIVE_DB_UID, RDB_STORE_COLUMN_TYPE_INT);
73             for (auto userId: activatedOsAccountIds) {
74                 UpdateOldDataUid(rdbStore, tableName, userId, bundleNameUidMap);
75             }
76         }
77     }
78 }
79 
SupportFirstUseTime()80 void BundleActiveUsageDatabase::SupportFirstUseTime()
81 {
82     shared_ptr<NativeRdb::RdbStore> rdbStore = GetBundleActiveRdbStore(APP_GROUP_DATABASE_INDEX);
83     if (!rdbStore) {
84         BUNDLE_ACTIVE_LOGE("get RdbStore fail, databaseType: %{public}u", APP_GROUP_DATABASE_INDEX);
85         return;
86     }
87     vector<vector<string>> allTableName = vector<vector<string>>(ALL_TABLE_ARRAY_NUMBER);
88     {
89         lock_guard<ffrt::mutex> lock(databaseMutex_);
90         for (uint32_t i = 0; i < databaseFiles_.size(); i++) {
91             HandleTableInfo(i);
92         }
93         HandleAllTableName(APP_GROUP_DATABASE_INDEX, allTableName);
94     }
95     auto it = std::find(allTableName.at(APP_GROUP_DATABASE_INDEX).begin(),
96         allTableName.at(APP_GROUP_DATABASE_INDEX).end(), BUNDLE_HISTORY_LOG_TABLE);
97     if (it == allTableName.at(APP_GROUP_DATABASE_INDEX).end()) {
98         BUNDLE_ACTIVE_LOGE("not have bundle history table");
99         return;
100     }
101     vector<int32_t> activatedOsAccountIds;
102     BundleActiveAccountHelper::GetActiveUserId(activatedOsAccountIds);
103     {
104         lock_guard<ffrt::mutex> lock(databaseMutex_);
105         AddRdbColumn(rdbStore, BUNDLE_HISTORY_LOG_TABLE, BUNDLE_ACTIVE_DB_FIRST_USE_TIME, RDB_STORE_COLUMN_TYPE_INT);
106     }
107     for (auto userId: activatedOsAccountIds) {
108         UpdateFirstUseTime(rdbStore, BUNDLE_HISTORY_LOG_TABLE, userId);
109     }
110 }
111 
AddRdbColumn(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const string & columnName,const string & columnType)112 void BundleActiveUsageDatabase::AddRdbColumn(const shared_ptr<NativeRdb::RdbStore> store,
113     const string& tableName, const string& columnName, const string& columnType)
114 {
115     if (columnType != RDB_STORE_COLUMN_TYPE_INT) {
116         return;
117     }
118     string sqlStr = "";
119     sqlStr = "ALTER TABLE " + tableName + " ADD " + columnName + " " + columnType;
120     if (columnName == BUNDLE_ACTIVE_DB_UID) {
121         sqlStr += " NOT NULL DEFAULT -1";
122     }
123     if (columnName == BUNDLE_ACTIVE_DB_FIRST_USE_TIME) {
124         sqlStr += " NOT NULL DEFAULT " + std::to_string(MAX_END_TIME);
125     }
126     auto ret = store->ExecuteSql(sqlStr);
127     if (ret != E_OK) {
128         BUNDLE_ACTIVE_LOGE("add column failed columnName %{public}s", columnName.c_str());
129     }
130 }
131 
UpdateOldDataUid(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const int32_t userId,map<string,int32_t> & bundleNameUidMap)132 void BundleActiveUsageDatabase::UpdateOldDataUid(const shared_ptr<NativeRdb::RdbStore> store,
133     const string& tableName, const int32_t userId, map<string, int32_t>& bundleNameUidMap)
134 {
135     vector<string> queryCondition;
136     string querySql = "select * from " + tableName;
137     shared_ptr<NativeRdb::ResultSet> bundleActiveResult;
138     bundleActiveResult = store->QueryByStep(querySql);
139     int32_t tableRowNumber = 0;
140     bundleActiveResult->GetRowCount(tableRowNumber);
141     string bundleName;
142     int32_t uid;
143     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
144     NativeRdb::ValuesBucket valuesBucket;
145     for (int32_t i = 0; i < tableRowNumber; i++) {
146         bundleActiveResult->GoToRow(i);
147         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, bundleName);
148         AppExecFwk::ApplicationInfo appInfo;
149         string bundleNameUserIdKey = bundleName + to_string(userId);
150         auto it = bundleNameUidMap.find(bundleNameUserIdKey);
151         if (it == bundleNameUidMap.end()) {
152             BundleActiveBundleMgrHelper::GetInstance()->GetApplicationInfo(bundleName,
153                 AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, userId, appInfo);
154             uid = appInfo.uid;
155             bundleNameUidMap[bundleNameUserIdKey] = uid;
156         } else {
157             uid = it->second;
158         }
159         queryCondition.push_back(to_string(userId));
160         queryCondition.push_back(bundleName);
161         valuesBucket.PutInt(BUNDLE_ACTIVE_DB_UID, uid);
162         store->Update(changeRow, tableName, valuesBucket, "userId = ? and bundleName = ?", queryCondition);
163         queryCondition.clear();
164         valuesBucket.Clear();
165         changeRow = BUNDLE_ACTIVE_FAIL;
166     }
167     bundleActiveResult->Close();
168 }
169 
UpdateFirstUseTime(const shared_ptr<NativeRdb::RdbStore> store,const string & tableName,const int32_t userId)170 void BundleActiveUsageDatabase::UpdateFirstUseTime(const shared_ptr<NativeRdb::RdbStore> store,
171     const string& tableName, const int32_t userId)
172 {
173     map<string, int64_t> allBundleFirstUseTime = GetAllBundleFirstUseTime(userId);
174     lock_guard<ffrt::mutex> lock(databaseMutex_);
175     vector<string> queryCondition;
176     string querySql = "select * from " + tableName;
177     shared_ptr<NativeRdb::ResultSet> bundleActiveResult;
178     bundleActiveResult = store->QueryByStep(querySql);
179     int32_t tableRowNumber = 0;
180     bundleActiveResult->GetRowCount(tableRowNumber);
181     int32_t uid;
182     string bundleName;
183     int32_t changeRow = BUNDLE_ACTIVE_FAIL;
184     int64_t firstUseTime = MAX_END_TIME;
185     NativeRdb::ValuesBucket valuesBucket;
186     for (int32_t i = 0; i < tableRowNumber; i++) {
187         bundleActiveResult->GoToRow(i);
188         bundleActiveResult->GetInt(BUNDLE_HISTORY_LOG_UID_COLUMN_INDEX, uid);
189         bundleActiveResult->GetString(BUNDLE_NAME_COLUMN_INDEX, bundleName);
190         string bundleUidKey = BundleActiveUtil::GetBundleUsageKey(bundleName, uid);
191         auto it = allBundleFirstUseTime.find(bundleUidKey);
192         if (it != allBundleFirstUseTime.end()) {
193             firstUseTime = it->second;
194         }
195         queryCondition.push_back(to_string(userId));
196         queryCondition.push_back(bundleName);
197         queryCondition.push_back(to_string(uid));
198         valuesBucket.PutLong(BUNDLE_ACTIVE_DB_FIRST_USE_TIME, firstUseTime);
199         store->Update(changeRow, tableName, valuesBucket, "userId = ? and bundleName = ? and uid = ?", queryCondition);
200         queryCondition.clear();
201         valuesBucket.Clear();
202         changeRow = BUNDLE_ACTIVE_FAIL;
203     }
204     bundleActiveResult->Close();
205 }
206 
GetAllBundleFirstUseTime(const int32_t userId)207 map<string, int64_t> BundleActiveUsageDatabase::GetAllBundleFirstUseTime(const int32_t userId)
208 {
209     vector<BundleActiveEvent> events = QueryDatabaseEvents(MIN_START_TIME, MAX_END_TIME, userId, "");
210     map<string, int64_t> allBundleFirstUseTime;
211     for (auto event : events) {
212         string bundleUidKey = BundleActiveUtil::GetBundleUsageKey(event.bundleName_, event.uid_);
213         auto it = allBundleFirstUseTime.find(bundleUidKey);
214         if (it == allBundleFirstUseTime.end()) {
215             allBundleFirstUseTime[bundleUidKey] = event.timeStamp_;
216             continue;
217         }
218         allBundleFirstUseTime[bundleUidKey] = std::min(allBundleFirstUseTime[bundleUidKey], event.timeStamp_);
219     }
220 
221     vector<BundleActivePackageStats> packageStatsVector = QueryDatabaseUsageStats(YEARLY_DATABASE_INDEX,
222         MIN_START_TIME, MAX_END_TIME, userId, "");
223     for (auto packageStats : packageStatsVector) {
224         string bundleUidKey = BundleActiveUtil::GetBundleUsageKey(packageStats.bundleName_, packageStats.uid_);
225         auto it = allBundleFirstUseTime.find(bundleUidKey);
226         if (it == allBundleFirstUseTime.end()) {
227             allBundleFirstUseTime[bundleUidKey] = packageStats.lastTimeUsed_;
228             continue;
229         }
230         allBundleFirstUseTime[bundleUidKey] = std::min(allBundleFirstUseTime[bundleUidKey], packageStats.lastTimeUsed_);
231     }
232     return allBundleFirstUseTime;
233 }
234 }  // namespace DeviceUsageStats
235 }  // namespace OHOS
236