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