1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "bundle_active_core.h"
16 #include "app_group_callback_info.h"
17 #include "bundle_active_user_history.h"
18 #include "bundle_active_log.h"
19 #include "bundle_active_util.h"
20
21 namespace OHOS {
22 namespace DeviceUsageStats {
23 using namespace DeviceUsageStatsGroupConst;
24 using namespace std;
25
BundleActivePackageHistory()26 BundleActivePackageHistory::BundleActivePackageHistory()
27 {
28 bundleName_ = "";
29 lastBootFromUsedTimeStamp_ = 0;
30 lastScreenUsedTimeStamp_ = 0;
31 lastGroupCalculatedTimeStamp_ = 0;
32 currentGroup_ = DeviceUsageStatsGroupConst::ACTIVE_GROUP_NEVER;
33 reasonInGroup_ = DeviceUsageStatsGroupConst::GROUP_CONTROL_REASON_DEFAULT;
34 bundleAliveTimeoutTimeStamp_ = 0;
35 bundleDailyTimeoutTimeStamp_ = 0;
36 uid_ = 0;
37 lastCalculatedGroup_ = ACTIVE_GROUP_NEVER;
38 isChanged_ = false;
39 bundlefirstUseTimeStamp_ = MAX_END_TIME;
40 };
41
WriteDeviceDuration()42 void BundleActiveUserHistory::WriteDeviceDuration()
43 {
44 database_.PutDurationData(bootBasedDuration_, ScreenOnDuration_);
45 }
46
WriteBundleUsage(const int32_t userId)47 void BundleActiveUserHistory::WriteBundleUsage(const int32_t userId)
48 {
49 BUNDLE_ACTIVE_LOGI("WriteBundleUsage called");
50 auto userHistory = GetUserHistory(userId, false);
51 if (userHistory == nullptr) {
52 BUNDLE_ACTIVE_LOGI("WriteBundleUsage called, no existed user history, return");
53 return;
54 }
55 database_.PutBundleHistoryData(userId, userHistory);
56 }
57
OnBundleUninstalled(const int32_t userId,const std::string bundleName,const int32_t uid,const int32_t appIndex)58 void BundleActiveUserHistory::OnBundleUninstalled(const int32_t userId, const std::string bundleName,
59 const int32_t uid, const int32_t appIndex)
60 {
61 database_.OnPackageUninstalled(userId, bundleName, uid, appIndex);
62 }
63
BundleActiveUserHistory(const int64_t bootBasedTimeStamp,const std::shared_ptr<BundleActiveCore> & bundleActiveCore)64 BundleActiveUserHistory::BundleActiveUserHistory(const int64_t bootBasedTimeStamp,
65 const std::shared_ptr<BundleActiveCore>& bundleActiveCore)
66 {
67 bootBasedTimeStamp_ = bootBasedTimeStamp;
68 screenOnTimeStamp_ = bootBasedTimeStamp;
69 database_.InitUsageGroupDatabase(APP_GROUP_DATABASE_INDEX, false);
70 auto bootAndScreenOnDuraton = database_.GetDurationData();
71 bootBasedDuration_ = bootAndScreenOnDuraton.first;
72 ScreenOnDuration_ = bootAndScreenOnDuraton.second;
73 isScreenOn_ = false;
74 if (bundleActiveCore) {
75 bundleActiveCore_ = bundleActiveCore;
76 }
77 }
78
GetLevelIndex(const string & bundleName,const int32_t userId,const int64_t bootBasedTimeStamp,const std::vector<int64_t> screenTimeLevel,const std::vector<int64_t> bootFromTimeLevel,const int32_t uid)79 int32_t BundleActiveUserHistory::GetLevelIndex(const string& bundleName, const int32_t userId,
80 const int64_t bootBasedTimeStamp, const std::vector<int64_t> screenTimeLevel,
81 const std::vector<int64_t> bootFromTimeLevel, const int32_t uid)
82 {
83 auto oneUserHistory = GetUserHistory(userId, false);
84 if (oneUserHistory == nullptr) {
85 return -1;
86 }
87 auto oneBundleHistory = GetUsageHistoryInUserHistory(oneUserHistory, bundleName, bootBasedTimeStamp, false, uid);
88 if (oneBundleHistory == nullptr) {
89 return -1;
90 }
91 int64_t screenDiff = GetScreenOnTimeStamp(bootBasedTimeStamp) - oneBundleHistory->lastScreenUsedTimeStamp_;
92 int64_t bootFromDiff = GetBootBasedTimeStamp(bootBasedTimeStamp) - oneBundleHistory->lastBootFromUsedTimeStamp_;
93 BUNDLE_ACTIVE_LOGD("screendiff is %{public}lld, bootfromdiff is %{public}lld, bundle name is %{public}s,"
94 "userid is %{public}d",
95 (long long)screenDiff, (long long)bootFromDiff, bundleName.c_str(), userId);
96 for (int32_t i = 3; i >= 0; i--) {
97 if (screenDiff >= screenTimeLevel[i] && bootFromDiff >= bootFromTimeLevel[i]) {
98 return i;
99 }
100 }
101 return -1;
102 }
103
GetBootBasedTimeStamp(int64_t bootBasedTimeStamp)104 int64_t BundleActiveUserHistory::GetBootBasedTimeStamp(int64_t bootBasedTimeStamp)
105 {
106 return bootBasedTimeStamp - bootBasedTimeStamp_ + bootBasedDuration_;
107 }
108
GetScreenOnTimeStamp(int64_t bootBasedTimeStamp)109 int64_t BundleActiveUserHistory::GetScreenOnTimeStamp(int64_t bootBasedTimeStamp)
110 {
111 int64_t result = ScreenOnDuration_;
112 if (isScreenOn_) {
113 result += bootBasedTimeStamp - screenOnTimeStamp_;
114 }
115 return result;
116 }
117
GetUserHistory(const int32_t userId,const bool create)118 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> BundleActiveUserHistory::GetUserHistory(
119 const int32_t userId, const bool create)
120 {
121 auto it = userHistory_.find(userId);
122 if ((it == userHistory_.end()) && create) {
123 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> usageHistoryInserted =
124 database_.GetBundleHistoryData(userId);
125 if (!usageHistoryInserted) {
126 BUNDLE_ACTIVE_LOGI("GetUserHistory READ FROM DATABASE FAILD");
127 usageHistoryInserted =
128 make_shared<map<string, shared_ptr<BundleActivePackageHistory>>>();
129 }
130 BUNDLE_ACTIVE_LOGI("GetUserHistory usageHistoryInserted not null");
131 userHistory_[userId] = usageHistoryInserted;
132 }
133
134 if (it == userHistory_.end() && !create) {
135 return nullptr;
136 }
137 return userHistory_[userId];
138 }
139
GetUsageHistoryInUserHistory(shared_ptr<map<string,shared_ptr<BundleActivePackageHistory>>> oneUserHistory,string bundleName,int64_t bootBasedTimeStamp,const bool create,const int32_t uid)140 shared_ptr<BundleActivePackageHistory> BundleActiveUserHistory::GetUsageHistoryInUserHistory(
141 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> oneUserHistory,
142 string bundleName, int64_t bootBasedTimeStamp, const bool create, const int32_t uid)
143 {
144 if (!oneUserHistory) {
145 return nullptr;
146 }
147 std::string userHistoryKey = BundleActiveUtil::GetBundleUsageKey(bundleName, uid);
148 auto it = oneUserHistory->find(userHistoryKey);
149 if ((it == oneUserHistory->end()) && create) {
150 shared_ptr<BundleActivePackageHistory> usageHistoryInserted =
151 make_shared<BundleActivePackageHistory>();
152 usageHistoryInserted->bundleName_ = bundleName;
153 usageHistoryInserted->lastBootFromUsedTimeStamp_ = GetBootBasedTimeStamp(bootBasedTimeStamp);
154 usageHistoryInserted->lastScreenUsedTimeStamp_ = GetScreenOnTimeStamp(bootBasedTimeStamp);
155 usageHistoryInserted->currentGroup_ = ACTIVE_GROUP_NEVER;
156 usageHistoryInserted->reasonInGroup_ = GROUP_CONTROL_REASON_DEFAULT;
157 usageHistoryInserted->bundleAliveTimeoutTimeStamp_ = 0;
158 usageHistoryInserted->bundleDailyTimeoutTimeStamp_ = 0;
159 usageHistoryInserted->uid_ = uid;
160 usageHistoryInserted->bundlefirstUseTimeStamp_ = INT64_MAX;
161 (*oneUserHistory)[userHistoryKey] = usageHistoryInserted;
162 }
163 return (*oneUserHistory)[userHistoryKey];
164 }
165
GetUsageHistoryForBundle(const string & bundleName,const int32_t userId,const int64_t bootBasedTimeStamp,const bool create,const int32_t uid)166 shared_ptr<BundleActivePackageHistory> BundleActiveUserHistory::GetUsageHistoryForBundle(
167 const string& bundleName, const int32_t userId, const int64_t bootBasedTimeStamp, const bool create,
168 const int32_t uid)
169 {
170 auto oneUserHistory = GetUserHistory(userId, create);
171 if (!oneUserHistory) {
172 return nullptr;
173 }
174 auto oneBundleHistory = GetUsageHistoryInUserHistory(oneUserHistory, bundleName, bootBasedTimeStamp, create, uid);
175 if (!oneBundleHistory) {
176 return nullptr;
177 }
178 return oneBundleHistory;
179 }
180
ReportUsage(shared_ptr<BundleActivePackageHistory> oneBundleUsageHistory,const BundleActiveEvent & event,const int32_t newGroup,const uint32_t groupReason,const int64_t bootBasedTimeStamp,const int64_t timeUntilNextCheck,const int32_t userId)181 void BundleActiveUserHistory::ReportUsage(shared_ptr<BundleActivePackageHistory> oneBundleUsageHistory,
182 const BundleActiveEvent& event, const int32_t newGroup, const uint32_t groupReason,
183 const int64_t bootBasedTimeStamp, const int64_t timeUntilNextCheck, const int32_t userId)
184 {
185 string bundleName = event.bundleName_;
186 int32_t uid = event.uid_;
187 oneBundleUsageHistory->bundlefirstUseTimeStamp_ =
188 std::min(oneBundleUsageHistory->bundlefirstUseTimeStamp_, event.timeStamp_);
189 if ((oneBundleUsageHistory->reasonInGroup_ & GROUP_CONTROL_REASON_MASK) == GROUP_CONTROL_REASON_FORCED) {
190 return;
191 }
192 if (timeUntilNextCheck > bootBasedTimeStamp) {
193 int64_t nextCheckTimeStamp = bootBasedDuration_ + (timeUntilNextCheck - bootBasedTimeStamp_);
194 if (newGroup == ACTIVE_GROUP_ALIVE) {
195 oneBundleUsageHistory->bundleAliveTimeoutTimeStamp_ = max(nextCheckTimeStamp,
196 oneBundleUsageHistory->bundleAliveTimeoutTimeStamp_);
197 } else if (newGroup == ACTIVE_GROUP_DAILY) {
198 oneBundleUsageHistory->bundleDailyTimeoutTimeStamp_ = max(nextCheckTimeStamp,
199 oneBundleUsageHistory->bundleDailyTimeoutTimeStamp_);
200 } else {
201 return;
202 }
203 }
204 if (bootBasedTimeStamp > 0) {
205 oneBundleUsageHistory->lastBootFromUsedTimeStamp_ = bootBasedDuration_ +
206 (bootBasedTimeStamp - bootBasedTimeStamp_);
207 oneBundleUsageHistory->lastScreenUsedTimeStamp_ = GetScreenOnTimeStamp(bootBasedTimeStamp);
208 }
209 int32_t oldGroup = oneBundleUsageHistory->currentGroup_;
210 if (oneBundleUsageHistory->currentGroup_ > newGroup) {
211 oneBundleUsageHistory->currentGroup_ = newGroup;
212 }
213 oneBundleUsageHistory->reasonInGroup_ = GROUP_CONTROL_REASON_USAGE | groupReason;
214 oneBundleUsageHistory->isChanged_ = true;
215 BUNDLE_ACTIVE_LOGD("RegisterAppGroupCallBack will ReportUsage");
216 bool isGroupChanged = (oldGroup == oneBundleUsageHistory->currentGroup_) ? false : true;
217 if (isGroupChanged) {
218 AppGroupCallbackInfo callbackInfo(
219 userId, oldGroup, newGroup, oneBundleUsageHistory->reasonInGroup_, bundleName);
220 BUNDLE_ACTIVE_LOGI("RegisterAppGroupCallBack AppGroupCallbackInfo build success");
221 if (!bundleActiveCore_.expired()) {
222 BUNDLE_ACTIVE_LOGD("RegisterAppGroupCallBack will callback!");
223 bundleActiveCore_.lock()->OnAppGroupChanged(callbackInfo);
224 }
225 }
226 }
227
SetAppGroup(const string & bundleName,const int32_t userId,const int32_t uid,const int64_t bootBasedTimeStamp,int32_t newGroup,uint32_t groupReason,const bool isFlush)228 int32_t BundleActiveUserHistory::SetAppGroup(const string& bundleName, const int32_t userId, const int32_t uid,
229 const int64_t bootBasedTimeStamp, int32_t newGroup, uint32_t groupReason, const bool isFlush)
230 {
231 std::lock_guard<ffrt::mutex> lock(setGroupMutex_);
232 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> userBundleHistory = GetUserHistory(userId, false);
233 if (!userBundleHistory) {
234 return ERR_GET_BUNDLE_USED_HISTORY_FAILED;
235 }
236 shared_ptr<BundleActivePackageHistory> oneBundleHistory = GetUsageHistoryInUserHistory(userBundleHistory,
237 bundleName, bootBasedTimeStamp, false, uid);
238 if (!oneBundleHistory) {
239 return ERR_GET_BUNDLE_USED_HISTORY_FAILED;
240 }
241 if (oneBundleHistory->currentGroup_ == newGroup && oneBundleHistory->reasonInGroup_ == groupReason) {
242 BUNDLE_ACTIVE_LOGI("%{public}s group and reason is same as before, not update", bundleName.c_str());
243 return ERR_REPEAT_SET_APP_GROUP;
244 }
245 int32_t oldGroup = oneBundleHistory->currentGroup_;
246 oneBundleHistory->currentGroup_ = newGroup;
247 oneBundleHistory->reasonInGroup_ = groupReason;
248 oneBundleHistory->isChanged_ = true;
249 BUNDLE_ACTIVE_LOGI("set %{public}s to group %{public}d, reason is %{public}d, userId is %{public}d",
250 bundleName.c_str(), newGroup, groupReason, userId);
251 if (isFlush) {
252 WriteBundleUsage(userId);
253 }
254
255 bool isGroupChanged = (oldGroup == newGroup) ? true : false;
256 if (!isGroupChanged) {
257 AppGroupCallbackInfo callbackInfo(
258 userId, oldGroup, newGroup, oneBundleHistory->reasonInGroup_, bundleName);
259 if (!bundleActiveCore_.expired()) {
260 bundleActiveCore_.lock()->OnAppGroupChanged(callbackInfo);
261 }
262 }
263 return ERR_OK;
264 }
265
UpdateBootBasedAndScreenTime(const bool & isScreenOn,const int64_t bootBasedTimeStamp,const bool & isShutdown)266 void BundleActiveUserHistory::UpdateBootBasedAndScreenTime(const bool& isScreenOn, const int64_t bootBasedTimeStamp,
267 const bool& isShutdown)
268 {
269 if (isScreenOn_ == isScreenOn && isShutdown == false) {
270 return;
271 }
272 isScreenOn_ = isScreenOn;
273 if (isScreenOn_) {
274 screenOnTimeStamp_ = bootBasedTimeStamp;
275 } else {
276 ScreenOnDuration_ += bootBasedTimeStamp - screenOnTimeStamp_;
277 bootBasedDuration_ += bootBasedTimeStamp - bootBasedTimeStamp_;
278 bootBasedTimeStamp_ = bootBasedTimeStamp;
279 }
280 database_.PutDurationData(bootBasedDuration_, ScreenOnDuration_);
281 }
282
PrintData(int32_t userId)283 void BundleActiveUserHistory::PrintData(int32_t userId)
284 {
285 auto oneUserHistory = GetUserHistory(userId, false);
286 BUNDLE_ACTIVE_LOGI("PrintData screen is %{public}d", isScreenOn_);
287 if (oneUserHistory == nullptr) {
288 return;
289 }
290 for (auto oneBundleUsage : (*oneUserHistory)) {
291 BUNDLE_ACTIVE_LOGI("bundle name is %{public}s, lastBootFromUsedTimeStamp_ is %{public}lld, "
292 "lastScreenUsedTimeStamp_ is %{public}lld, currentGroup_ is %{public}d, reasonInGroup_ is %{public}d, "
293 "daily time out %{public}lld, alive time out %{public}lld", oneBundleUsage.first.c_str(),
294 (long long)oneBundleUsage.second->lastBootFromUsedTimeStamp_,
295 (long long)oneBundleUsage.second->lastScreenUsedTimeStamp_,
296 oneBundleUsage.second->currentGroup_, oneBundleUsage.second->reasonInGroup_,
297 (long long)oneBundleUsage.second->bundleDailyTimeoutTimeStamp_,
298 (long long)oneBundleUsage.second->bundleAliveTimeoutTimeStamp_);
299 }
300 }
301
GetFirstUseTime(const std::string & bundleName,const int32_t userId)302 int64_t BundleActiveUserHistory::GetFirstUseTime(const std::string& bundleName, const int32_t userId)
303 {
304 int64_t firstUseTime = MAX_END_TIME;
305 auto userHistory = GetUserHistory(userId, false);
306 if (userHistory == nullptr) {
307 BUNDLE_ACTIVE_LOGI("WriteBundleUsage called, no existed user history, return");
308 return firstUseTime;
309 }
310 for (auto packageHistoryIter : *userHistory) {
311 if (packageHistoryIter.first.find(bundleName) == std::string::npos || packageHistoryIter.second == nullptr) {
312 continue;
313 }
314 firstUseTime = std::min(firstUseTime, packageHistoryIter.second->bundlefirstUseTimeStamp_);
315 }
316 return firstUseTime;
317 }
318 } // namespace DeviceUsageStats
319 } // namespace OHOS
320
321