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 };
40
WriteDeviceDuration()41 void BundleActiveUserHistory::WriteDeviceDuration()
42 {
43 database_.PutDurationData(bootBasedDuration_, ScreenOnDuration_);
44 }
45
WriteBundleUsage(const int32_t userId)46 void BundleActiveUserHistory::WriteBundleUsage(const int32_t userId)
47 {
48 BUNDLE_ACTIVE_LOGI("WriteBundleUsage called");
49 auto userHistory = GetUserHistory(userId, false);
50 if (userHistory == nullptr) {
51 BUNDLE_ACTIVE_LOGI("WriteBundleUsage called, no existed user history, return");
52 return;
53 }
54 database_.PutBundleHistoryData(userId, userHistory);
55 }
56
OnBundleUninstalled(const int32_t userId,const std::string bundleName,const int32_t uid,const int32_t appIndex)57 void BundleActiveUserHistory::OnBundleUninstalled(const int32_t userId, const std::string bundleName,
58 const int32_t uid, const int32_t appIndex)
59 {
60 database_.OnPackageUninstalled(userId, bundleName, uid, appIndex);
61 }
62
BundleActiveUserHistory(const int64_t bootBasedTimeStamp,const std::shared_ptr<BundleActiveCore> & bundleActiveCore)63 BundleActiveUserHistory::BundleActiveUserHistory(const int64_t bootBasedTimeStamp,
64 const std::shared_ptr<BundleActiveCore>& bundleActiveCore)
65 {
66 bootBasedTimeStamp_ = bootBasedTimeStamp;
67 screenOnTimeStamp_ = bootBasedTimeStamp;
68 database_.InitUsageGroupDatabase(APP_GROUP_DATABASE_INDEX, false);
69 auto bootAndScreenOnDuraton = database_.GetDurationData();
70 bootBasedDuration_ = bootAndScreenOnDuraton.first;
71 ScreenOnDuration_ = bootAndScreenOnDuraton.second;
72 isScreenOn_ = false;
73 if (bundleActiveCore) {
74 bundleActiveCore_ = bundleActiveCore;
75 }
76 }
77
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)78 int32_t BundleActiveUserHistory::GetLevelIndex(const string& bundleName, const int32_t userId,
79 const int64_t bootBasedTimeStamp, const std::vector<int64_t> screenTimeLevel,
80 const std::vector<int64_t> bootFromTimeLevel, const int32_t uid)
81 {
82 auto oneUserHistory = GetUserHistory(userId, false);
83 if (oneUserHistory == nullptr) {
84 return -1;
85 }
86 auto oneBundleHistory = GetUsageHistoryInUserHistory(oneUserHistory, bundleName, bootBasedTimeStamp, false, uid);
87 if (oneBundleHistory == nullptr) {
88 return -1;
89 }
90 int64_t screenDiff = GetScreenOnTimeStamp(bootBasedTimeStamp) - oneBundleHistory->lastScreenUsedTimeStamp_;
91 int64_t bootFromDiff = GetBootBasedTimeStamp(bootBasedTimeStamp) - oneBundleHistory->lastBootFromUsedTimeStamp_;
92 BUNDLE_ACTIVE_LOGI("screendiff is %{public}lld, bootfromdiff is %{public}lld, bundle name is %{public}s,"
93 "userid is %{public}d",
94 (long long)screenDiff, (long long)bootFromDiff, bundleName.c_str(), userId);
95 for (int32_t i = 3; i >= 0; i--) {
96 if (screenDiff >= screenTimeLevel[i] && bootFromDiff >= bootFromTimeLevel[i]) {
97 return i;
98 }
99 }
100 return -1;
101 }
102
GetBootBasedTimeStamp(int64_t bootBasedTimeStamp)103 int64_t BundleActiveUserHistory::GetBootBasedTimeStamp(int64_t bootBasedTimeStamp)
104 {
105 return bootBasedTimeStamp - bootBasedTimeStamp_ + bootBasedDuration_;
106 }
107
GetScreenOnTimeStamp(int64_t bootBasedTimeStamp)108 int64_t BundleActiveUserHistory::GetScreenOnTimeStamp(int64_t bootBasedTimeStamp)
109 {
110 int64_t result = ScreenOnDuration_;
111 if (isScreenOn_) {
112 result += bootBasedTimeStamp - screenOnTimeStamp_;
113 }
114 return result;
115 }
116
GetUserHistory(const int32_t userId,const bool create)117 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> BundleActiveUserHistory::GetUserHistory(
118 const int32_t userId, const bool create)
119 {
120 auto it = userHistory_.find(userId);
121 if ((it == userHistory_.end()) && create) {
122 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> usageHistoryInserted =
123 database_.GetBundleHistoryData(userId);
124 if (!usageHistoryInserted) {
125 BUNDLE_ACTIVE_LOGI("GetUserHistory READ FROM DATABASE FAILD");
126 usageHistoryInserted =
127 make_shared<map<string, shared_ptr<BundleActivePackageHistory>>>();
128 }
129 BUNDLE_ACTIVE_LOGI("GetUserHistory usageHistoryInserted not null");
130 userHistory_[userId] = usageHistoryInserted;
131 }
132
133 if (it == userHistory_.end() && !create) {
134 return nullptr;
135 }
136 return userHistory_[userId];
137 }
138
GetUsageHistoryInUserHistory(shared_ptr<map<string,shared_ptr<BundleActivePackageHistory>>> oneUserHistory,string bundleName,int64_t bootBasedTimeStamp,const bool create,const int32_t uid)139 shared_ptr<BundleActivePackageHistory> BundleActiveUserHistory::GetUsageHistoryInUserHistory(
140 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> oneUserHistory,
141 string bundleName, int64_t bootBasedTimeStamp, const bool create, const int32_t uid)
142 {
143 if (!oneUserHistory) {
144 return nullptr;
145 }
146 std::string userHistoryKey = BundleActiveUtil::GetBundleUsageKey(bundleName, uid);
147 auto it = oneUserHistory->find(userHistoryKey);
148 if ((it == oneUserHistory->end()) && create) {
149 shared_ptr<BundleActivePackageHistory> usageHistoryInserted =
150 make_shared<BundleActivePackageHistory>();
151 usageHistoryInserted->bundleName_ = bundleName;
152 usageHistoryInserted->lastBootFromUsedTimeStamp_ = GetBootBasedTimeStamp(bootBasedTimeStamp);
153 usageHistoryInserted->lastScreenUsedTimeStamp_ = GetScreenOnTimeStamp(bootBasedTimeStamp);
154 usageHistoryInserted->currentGroup_ = ACTIVE_GROUP_NEVER;
155 usageHistoryInserted->reasonInGroup_ = GROUP_CONTROL_REASON_DEFAULT;
156 usageHistoryInserted->bundleAliveTimeoutTimeStamp_ = 0;
157 usageHistoryInserted->bundleDailyTimeoutTimeStamp_ = 0;
158 usageHistoryInserted->uid_ = uid;
159 (*oneUserHistory)[userHistoryKey] = usageHistoryInserted;
160 }
161 return (*oneUserHistory)[userHistoryKey];
162 }
163
GetUsageHistoryForBundle(const string & bundleName,const int32_t userId,const int64_t bootBasedTimeStamp,const bool create,const int32_t uid)164 shared_ptr<BundleActivePackageHistory> BundleActiveUserHistory::GetUsageHistoryForBundle(
165 const string& bundleName, const int32_t userId, const int64_t bootBasedTimeStamp, const bool create,
166 const int32_t uid)
167 {
168 auto oneUserHistory = GetUserHistory(userId, create);
169 if (!oneUserHistory) {
170 return nullptr;
171 }
172 auto oneBundleHistory = GetUsageHistoryInUserHistory(oneUserHistory, bundleName, bootBasedTimeStamp, create, uid);
173 if (!oneBundleHistory) {
174 return nullptr;
175 }
176 return oneBundleHistory;
177 }
178
ReportUsage(shared_ptr<BundleActivePackageHistory> oneBundleUsageHistory,const string & bundleName,const int32_t newGroup,const uint32_t groupReason,const int64_t bootBasedTimeStamp,const int64_t timeUntilNextCheck,const int32_t userId,const int32_t uid)179 void BundleActiveUserHistory::ReportUsage(shared_ptr<BundleActivePackageHistory> oneBundleUsageHistory,
180 const string& bundleName, const int32_t newGroup, const uint32_t groupReason, const int64_t bootBasedTimeStamp,
181 const int64_t timeUntilNextCheck, const int32_t userId, const int32_t uid)
182 {
183 if ((oneBundleUsageHistory->reasonInGroup_ & GROUP_CONTROL_REASON_MASK) == GROUP_CONTROL_REASON_FORCED) {
184 return;
185 }
186 if (timeUntilNextCheck > bootBasedTimeStamp) {
187 int64_t nextCheckTimeStamp = bootBasedDuration_ + (timeUntilNextCheck - bootBasedTimeStamp_);
188 if (newGroup == ACTIVE_GROUP_ALIVE) {
189 oneBundleUsageHistory->bundleAliveTimeoutTimeStamp_ = max(nextCheckTimeStamp,
190 oneBundleUsageHistory->bundleAliveTimeoutTimeStamp_);
191 } else if (newGroup == ACTIVE_GROUP_DAILY) {
192 oneBundleUsageHistory->bundleDailyTimeoutTimeStamp_ = max(nextCheckTimeStamp,
193 oneBundleUsageHistory->bundleDailyTimeoutTimeStamp_);
194 } else {
195 return;
196 }
197 }
198 if (bootBasedTimeStamp > 0) {
199 oneBundleUsageHistory->lastBootFromUsedTimeStamp_ = bootBasedDuration_ +
200 (bootBasedTimeStamp - bootBasedTimeStamp_);
201 oneBundleUsageHistory->lastScreenUsedTimeStamp_ = GetScreenOnTimeStamp(bootBasedTimeStamp);
202 }
203 int32_t oldGroup = oneBundleUsageHistory->currentGroup_;
204 if (oneBundleUsageHistory->currentGroup_ > newGroup) {
205 oneBundleUsageHistory->currentGroup_ = newGroup;
206 }
207 oneBundleUsageHistory->reasonInGroup_ = GROUP_CONTROL_REASON_USAGE | groupReason;
208 oneBundleUsageHistory->isChanged_ = true;
209 BUNDLE_ACTIVE_LOGD("RegisterAppGroupCallBack will ReportUsage");
210 bool isGroupChanged = (oldGroup == oneBundleUsageHistory->currentGroup_) ? false : true;
211 if (isGroupChanged) {
212 AppGroupCallbackInfo callbackInfo(
213 userId, oldGroup, newGroup, oneBundleUsageHistory->reasonInGroup_, bundleName);
214 BUNDLE_ACTIVE_LOGI("RegisterAppGroupCallBack AppGroupCallbackInfo build success");
215 if (!bundleActiveCore_.expired()) {
216 BUNDLE_ACTIVE_LOGD("RegisterAppGroupCallBack will callback!");
217 bundleActiveCore_.lock()->OnAppGroupChanged(callbackInfo);
218 }
219 }
220 }
221
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)222 int32_t BundleActiveUserHistory::SetAppGroup(const string& bundleName, const int32_t userId, const int32_t uid,
223 const int64_t bootBasedTimeStamp, int32_t newGroup, uint32_t groupReason, const bool isFlush)
224 {
225 std::lock_guard<ffrt::mutex> lock(setGroupMutex_);
226 BUNDLE_ACTIVE_LOGI("set %{public}s to group %{public}d, reason is %{public}d, userId is %{public}d",
227 bundleName.c_str(), newGroup, groupReason, userId);
228 shared_ptr<map<string, shared_ptr<BundleActivePackageHistory>>> userBundleHistory = GetUserHistory(userId, false);
229 if (!userBundleHistory) {
230 return ERR_GET_BUNDLE_USED_HISTORY_FAILED;
231 }
232 shared_ptr<BundleActivePackageHistory> oneBundleHistory = GetUsageHistoryInUserHistory(userBundleHistory,
233 bundleName, bootBasedTimeStamp, false, uid);
234 if (!oneBundleHistory) {
235 return ERR_GET_BUNDLE_USED_HISTORY_FAILED;
236 }
237 if (oneBundleHistory->currentGroup_ == newGroup && oneBundleHistory->reasonInGroup_ == groupReason) {
238 BUNDLE_ACTIVE_LOGI("%{public}s group and reason is same as before, not update", bundleName.c_str());
239 return ERR_REPEAT_SET_APP_GROUP;
240 }
241 int32_t oldGroup = oneBundleHistory->currentGroup_;
242 oneBundleHistory->currentGroup_ = newGroup;
243 oneBundleHistory->reasonInGroup_ = groupReason;
244 oneBundleHistory->isChanged_ = true;
245 BUNDLE_ACTIVE_LOGI("SetAppGroup set success");
246 if (isFlush) {
247 WriteBundleUsage(userId);
248 }
249
250 bool isGroupChanged = (oldGroup == newGroup) ? true : false;
251 if (!isGroupChanged) {
252 AppGroupCallbackInfo callbackInfo(
253 userId, oldGroup, newGroup, oneBundleHistory->reasonInGroup_, bundleName);
254 if (!bundleActiveCore_.expired()) {
255 bundleActiveCore_.lock()->OnAppGroupChanged(callbackInfo);
256 }
257 }
258 return ERR_OK;
259 }
260
UpdateBootBasedAndScreenTime(const bool & isScreenOn,const int64_t bootBasedTimeStamp,const bool & isShutdown)261 void BundleActiveUserHistory::UpdateBootBasedAndScreenTime(const bool& isScreenOn, const int64_t bootBasedTimeStamp,
262 const bool& isShutdown)
263 {
264 if (isScreenOn_ == isScreenOn && isShutdown == false) {
265 return;
266 }
267 isScreenOn_ = isScreenOn;
268 if (isScreenOn_) {
269 screenOnTimeStamp_ = bootBasedTimeStamp;
270 } else {
271 ScreenOnDuration_ += bootBasedTimeStamp - screenOnTimeStamp_;
272 bootBasedDuration_ += bootBasedTimeStamp - bootBasedTimeStamp_;
273 bootBasedTimeStamp_ = bootBasedTimeStamp;
274 }
275 database_.PutDurationData(bootBasedDuration_, ScreenOnDuration_);
276 }
277
PrintData(int32_t userId)278 void BundleActiveUserHistory::PrintData(int32_t userId)
279 {
280 auto oneUserHistory = GetUserHistory(userId, false);
281 BUNDLE_ACTIVE_LOGI("PrintData screen is %{public}d", isScreenOn_);
282 if (oneUserHistory == nullptr) {
283 return;
284 }
285 for (auto oneBundleUsage : (*oneUserHistory)) {
286 BUNDLE_ACTIVE_LOGI("bundle name is %{public}s, lastBootFromUsedTimeStamp_ is %{public}lld, "
287 "lastScreenUsedTimeStamp_ is %{public}lld, currentGroup_ is %{public}d, reasonInGroup_ is %{public}d, "
288 "daily time out %{public}lld, alive time out %{public}lld", oneBundleUsage.first.c_str(),
289 (long long)oneBundleUsage.second->lastBootFromUsedTimeStamp_,
290 (long long)oneBundleUsage.second->lastScreenUsedTimeStamp_,
291 oneBundleUsage.second->currentGroup_, oneBundleUsage.second->reasonInGroup_,
292 (long long)oneBundleUsage.second->bundleDailyTimeoutTimeStamp_,
293 (long long)oneBundleUsage.second->bundleAliveTimeoutTimeStamp_);
294 }
295 }
296 } // namespace DeviceUsageStats
297 } // namespace OHOS
298
299