• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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