• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "time_service_client.h"
17 
18 #include "bundle_active_user_history.h"
19 #include "bundle_active_group_handler.h"
20 #include "ibundle_active_service.h"
21 #include "bundle_active_group_controller.h"
22 
23 namespace OHOS {
24 namespace DeviceUsageStats {
25 using namespace DeviceUsageStatsGroupConst;
BundleActiveGroupHandlerObject()26 BundleActiveGroupHandlerObject::BundleActiveGroupHandlerObject()
27 {
28         bundleName_ = "";
29         userId_ = -1;
30 }
31 
32 
BundleActiveGroupController(const bool debug)33 BundleActiveGroupController::BundleActiveGroupController(const bool debug)
34 {
35     timeoutForDirectlyUse_ = debug ? THREE_MINUTE : ONE_HOUR;
36     timeoutForNotifySeen_ = debug ? ONE_MINUTE : TWELVE_HOUR;
37     timeoutForSystemInteraction_ = debug ? ONE_MINUTE : TEN_MINUTE;
38     screenTimeLevel_ = {0, 0, debug ? TWO_MINUTE : ONE_HOUR, debug ? FOUR_MINUTE : TWO_HOUR};
39     bootTimeLevel_ = {0, debug ? TWO_MINUTE : TWELVE_HOUR, debug ? FOUR_MINUTE : TWENTY_FOUR_HOUR,
40         debug ? SIXTEEN_MINUTE : FOURTY_EIGHT_HOUR};
41     eventIdMatchReason_ = {
42         {BundleActiveEvent::ABILITY_FOREGROUND, GROUP_EVENT_REASON_FOREGROUND},
43         {BundleActiveEvent::ABILITY_BACKGROUND, GROUP_EVENT_REASON_BACKGROUND},
44         {BundleActiveEvent::SYSTEM_INTERACTIVE, GROUP_EVENT_REASON_SYSTEM},
45         {BundleActiveEvent::USER_INTERACTIVE, GROUP_EVENT_REASON_USER_INTERACTION},
46         {BundleActiveEvent::NOTIFICATION_SEEN, GROUP_EVENT_REASON_NOTIFY_SEEN},
47         {BundleActiveEvent::LONG_TIME_TASK_STARTTED, GROUP_EVENT_REASON_LONG_TIME_TASK_STARTTED},
48     };
49 }
50 
RestoreDurationToDatabase()51 void BundleActiveGroupController::RestoreDurationToDatabase()
52 {
53     std::lock_guard<std::mutex> lock(mutex_);
54     bundleUserHistory_->WriteDeviceDuration();
55 }
56 
RestoreToDatabase(const int32_t userId)57 void BundleActiveGroupController::RestoreToDatabase(const int32_t userId)
58 {
59     std::lock_guard<std::mutex> lock(mutex_);
60     bundleUserHistory_->WriteBundleUsage(userId);
61 }
62 
OnUserRemoved(const int32_t userId)63 void BundleActiveGroupController::OnUserRemoved(const int32_t userId)
64 {
65     std::lock_guard<std::mutex> lock(mutex_);
66     bundleUserHistory_->userHistory_.erase(userId);
67     if (!activeGroupHandler_.expired()) {
68         activeGroupHandler_.lock()->RemoveEvent(BundleActiveGroupHandler::MSG_CHECK_IDLE_STATE);
69     }
70 }
71 
OnUserSwitched(const int32_t userId,const int32_t currentUsedUser)72 void BundleActiveGroupController::OnUserSwitched(const int32_t userId, const int32_t currentUsedUser)
73 {
74     BUNDLE_ACTIVE_LOGI("last time check for user %{public}d", currentUsedUser);
75     CheckEachBundleState(currentUsedUser);
76     bundleUserHistory_->WriteBundleUsage(currentUsedUser);
77     std::lock_guard<std::mutex> lock(mutex_);
78     if (!activeGroupHandler_.expired()) {
79         activeGroupHandler_.lock()->RemoveEvent(BundleActiveGroupHandler::MSG_CHECK_IDLE_STATE);
80         activeGroupHandler_.lock()->RemoveEvent(BundleActiveGroupHandler::MSG_CHECK_BUNDLE_STATE);
81     }
82     PeriodCheckBundleState(userId);
83 }
84 
OnScreenChanged(const bool & isScreenOn,const int64_t bootFromTimeStamp)85 void BundleActiveGroupController::OnScreenChanged(const bool& isScreenOn, const int64_t bootFromTimeStamp)
86 {
87     std::lock_guard<std::mutex> lock(mutex_);
88     bundleUserHistory_->UpdateBootBasedAndScreenTime(isScreenOn, bootFromTimeStamp);
89 }
90 
SetHandlerAndCreateUserHistory(const std::shared_ptr<BundleActiveGroupHandler> & groupHandler,const int64_t bootFromTimeStamp,const std::shared_ptr<BundleActiveCore> & bundleActiveCore)91 void BundleActiveGroupController::SetHandlerAndCreateUserHistory(
92     const std::shared_ptr<BundleActiveGroupHandler>& groupHandler, const int64_t bootFromTimeStamp,
93     const std::shared_ptr<BundleActiveCore>& bundleActiveCore)
94 {
95     if (bundleUserHistory_ == nullptr) {
96         BUNDLE_ACTIVE_LOGI("SetHandlerAndCreateUserHistory bundleUserHistory_ is null, "
97             "called constructor, bootstamp is %{public}lld", (long long)bootFromTimeStamp);
98         bundleUserHistory_ = std::make_shared<BundleActiveUserHistory>(bootFromTimeStamp, bundleActiveCore);
99     }
100     OnScreenChanged(IsScreenOn(), bootFromTimeStamp);
101     activeGroupHandler_ = groupHandler;
102 }
103 
OnBundleUninstalled(const int32_t userId,const std::string bundleName)104 void BundleActiveGroupController::OnBundleUninstalled(const int32_t userId, const std::string bundleName)
105 {
106     std::lock_guard<std::mutex> lock(mutex_);
107     BUNDLE_ACTIVE_LOGI("OnBundleUninstalled called, userId is %{public}d, bundlename is %{public}s",
108         userId, bundleName.c_str());
109     auto oneUserHistory = bundleUserHistory_->GetUserHistory(userId, false);
110     if (oneUserHistory == nullptr) {
111         return;
112     }
113     oneUserHistory->erase(bundleName);
114     bundleUserHistory_->OnBundleUninstalled(userId, bundleName);
115 }
116 
GetBundleMgrProxy()117 bool BundleActiveGroupController::GetBundleMgrProxy()
118 {
119     if (!sptrBundleMgr_) {
120         sptr<ISystemAbilityManager> systemAbilityManager =
121             SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
122         if (!systemAbilityManager) {
123             BUNDLE_ACTIVE_LOGE("Failed to get system ability mgr.");
124             return false;
125         }
126         sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
127         if (!remoteObject) {
128                 BUNDLE_ACTIVE_LOGE("Failed to get bundle manager service.");
129                 return false;
130         }
131         sptrBundleMgr_ = iface_cast<IBundleMgr>(remoteObject);
132         if (!sptrBundleMgr_) {
133             BUNDLE_ACTIVE_LOGE("Failed to get system bundle manager services ability, sptrBundleMgr_");
134             return false;
135         }
136         auto object = sptrBundleMgr_->AsObject();
137         if (!object) {
138             BUNDLE_ACTIVE_LOGE("Failed to get system bundle manager services ability");
139             return false;
140         }
141     }
142     return true;
143 }
144 
PeriodCheckBundleState(const int32_t userId)145 void BundleActiveGroupController::PeriodCheckBundleState(const int32_t userId)
146 {
147     BUNDLE_ACTIVE_LOGI("PeriodCheckBundleState called");
148     if (!activeGroupHandler_.expired()) {
149         BundleActiveGroupHandlerObject tmpGroupHandlerObj;
150         tmpGroupHandlerObj.userId_ = userId;
151         std::shared_ptr<BundleActiveGroupHandlerObject> handlerobjToPtr =
152             std::make_shared<BundleActiveGroupHandlerObject>(tmpGroupHandlerObj);
153         auto handlerEvent = AppExecFwk::InnerEvent::Get(BundleActiveGroupHandler::MSG_CHECK_IDLE_STATE,
154             handlerobjToPtr);
155         activeGroupHandler_.lock()->SendEvent(handlerEvent, FIVE_SECOND);
156     }
157 }
158 
CheckEachBundleState(const int32_t userId)159 bool BundleActiveGroupController::CheckEachBundleState(const int32_t userId)
160 {
161     BUNDLE_ACTIVE_LOGI("CheckEachBundleState called, userid is %{public}d", userId);
162     std::vector<ApplicationInfo> allBundlesForUser;
163     if (!GetBundleMgrProxy()) {
164         BUNDLE_ACTIVE_LOGE("CheckEachBundleState get bundle manager proxy failed!");
165         return false;
166     }
167     sptrBundleMgr_->GetApplicationInfos(flag, userId, allBundlesForUser);
168     std::vector<std::string> bundleNamesOfUser;
169     for (auto oneBundle : allBundlesForUser) {
170         bundleNamesOfUser.push_back(oneBundle.bundleName);
171     }
172     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
173     int64_t bootBasedTimeStamp = timer->GetBootTimeMs();
174     for (auto oneBundleName : bundleNamesOfUser) {
175         CheckAndUpdateGroup(oneBundleName, userId, bootBasedTimeStamp);
176     }
177     return true;
178 }
179 
CheckIdleStatsOneTime()180 void BundleActiveGroupController::CheckIdleStatsOneTime()
181 {
182     auto handlerEvent = AppExecFwk::InnerEvent::Get(
183         BundleActiveGroupHandler::MSG_ONE_TIME_CHECK_BUNDLE_STATE);
184     if (!activeGroupHandler_.expired()) {
185         activeGroupHandler_.lock()->SendEvent(handlerEvent);
186     }
187 }
188 
GetNewGroup(const std::string & bundleName,const int32_t userId,const int64_t bootBasedTimeStamp)189 int32_t BundleActiveGroupController::GetNewGroup(const std::string& bundleName, const int32_t userId,
190     const int64_t bootBasedTimeStamp)
191 {
192     int32_t groupIndex = bundleUserHistory_->GetLevelIndex(bundleName, userId, bootBasedTimeStamp, screenTimeLevel_,
193         bootTimeLevel_);
194     if (groupIndex < 0) {
195         return -1;
196     }
197     return LEVEL_GROUP[groupIndex];
198 }
199 
calculationTimeOut(const std::shared_ptr<BundleActivePackageHistory> & oneBundleHistory,const int64_t bootBasedTimeStamp)200 bool BundleActiveGroupController::calculationTimeOut(
201     const std::shared_ptr<BundleActivePackageHistory>& oneBundleHistory, const int64_t bootBasedTimeStamp)
202 {
203     if (oneBundleHistory == nullptr) {
204         return false;
205     }
206     int64_t lastGroupCalculatedTimeStamp = oneBundleHistory->lastGroupCalculatedTimeStamp_;
207     return lastGroupCalculatedTimeStamp > 0 && bundleUserHistory_->GetBootBasedTimeStamp(bootBasedTimeStamp)
208         - lastGroupCalculatedTimeStamp > timeoutCalculated_;
209 }
210 
ReportEvent(const BundleActiveEvent & event,const int64_t bootBasedTimeStamp,const int32_t userId)211 void BundleActiveGroupController::ReportEvent(const BundleActiveEvent& event, const int64_t bootBasedTimeStamp,
212     const int32_t userId)
213 {
214     if (bundleGroupEnable_ == false) {
215         return;
216     }
217     std::lock_guard<std::mutex> lock(mutex_);
218     if (IsBundleInstalled(event.bundleName_, userId) == false) {
219         BUNDLE_ACTIVE_LOGE("Report an uninstalled package event, return!");
220         return;
221     }
222     int32_t eventId = event.eventId_;
223     auto item  = eventIdMatchReason_.find(eventId);
224     if (item != eventIdMatchReason_.end()) {
225         std::shared_ptr<BundleActivePackageHistory> bundleUsageHistory = bundleUserHistory_->GetUsageHistoryForBundle(
226             event.bundleName_, userId, bootBasedTimeStamp, true);
227         if (bundleUsageHistory == nullptr) {
228             return;
229         }
230         int64_t timeUntilNextCheck;
231         uint32_t eventReason = item->second;
232         switch (eventId) {
233             case BundleActiveEvent::NOTIFICATION_SEEN:
234                 bundleUserHistory_->ReportUsage(bundleUsageHistory, event.bundleName_, ACTIVE_GROUP_DAILY,
235                     eventReason, 0, bootBasedTimeStamp + timeoutForNotifySeen_, userId);
236                 timeUntilNextCheck = timeoutForNotifySeen_;
237                 break;
238             case BundleActiveEvent::SYSTEM_INTERACTIVE:
239                 bundleUserHistory_->ReportUsage(bundleUsageHistory, event.bundleName_, ACTIVE_GROUP_ALIVE,
240                     eventReason, 0, bootBasedTimeStamp + timeoutForSystemInteraction_, userId);
241                 timeUntilNextCheck = timeoutForSystemInteraction_;
242                 break;
243             default:
244                 bundleUserHistory_->ReportUsage(bundleUsageHistory, event.bundleName_, ACTIVE_GROUP_ALIVE,
245                     eventReason, bootBasedTimeStamp, bootBasedTimeStamp + timeoutForDirectlyUse_, userId);
246                 timeUntilNextCheck = timeoutForDirectlyUse_;
247                 break;
248         }
249         BundleActiveGroupHandlerObject tmpGroupHandlerObj;
250         tmpGroupHandlerObj.userId_ = userId;
251         tmpGroupHandlerObj.bundleName_ = event.bundleName_;
252         std::shared_ptr<BundleActiveGroupHandlerObject> handlerobjToPtr =
253             std::make_shared<BundleActiveGroupHandlerObject>(tmpGroupHandlerObj);
254         auto handlerEvent = AppExecFwk::InnerEvent::Get(BundleActiveGroupHandler::MSG_CHECK_BUNDLE_STATE,
255             handlerobjToPtr);
256         if (!activeGroupHandler_.expired()) {
257             activeGroupHandler_.lock()->SendEvent(handlerEvent, timeUntilNextCheck);
258         }
259     }
260 }
261 
CheckAndUpdateGroup(const std::string & bundleName,const int32_t userId,const int64_t bootBasedTimeStamp)262 void BundleActiveGroupController::CheckAndUpdateGroup(const std::string& bundleName, const int32_t userId,
263     const int64_t bootBasedTimeStamp)
264 {
265     std::lock_guard<std::mutex> lock(mutex_);
266     auto oneBundleHistory = bundleUserHistory_->GetUsageHistoryForBundle(bundleName, userId, bootBasedTimeStamp, true);
267     if (oneBundleHistory == nullptr) {
268         return;
269     }
270     uint32_t groupReason = oneBundleHistory->reasonInGroup_;
271     uint32_t oldGroupControlReason = groupReason & GROUP_CONTROL_REASON_MASK;
272     if (oldGroupControlReason == GROUP_CONTROL_REASON_FORCED) {
273         BUNDLE_ACTIVE_LOGI("%{public}s is forced set, return", bundleName.c_str());
274         return;
275     }
276     int32_t oldGroup = oneBundleHistory->currentGroup_;
277     int32_t newGroup = std::max(oldGroup, ACTIVE_GROUP_ALIVE);
278     if (oldGroupControlReason == GROUP_CONTROL_REASON_DEFAULT ||
279         oldGroupControlReason == GROUP_CONTROL_REASON_USAGE ||
280         oldGroupControlReason == GROUP_CONTROL_REASON_TIMEOUT) {
281         newGroup = GetNewGroup(bundleName, userId, bootBasedTimeStamp);
282         if (newGroup < 0) {
283             return;
284         }
285         groupReason = GROUP_CONTROL_REASON_TIMEOUT;
286     }
287     int64_t bootBasedTimeStampAdjusted = bundleUserHistory_->GetBootBasedTimeStamp(bootBasedTimeStamp);
288     bool notTimeout = false;
289     if (newGroup >= ACTIVE_GROUP_ALIVE && oneBundleHistory->bundleAliveTimeoutTimeStamp_ >
290         bootBasedTimeStampAdjusted) {
291         newGroup = ACTIVE_GROUP_ALIVE;
292         groupReason = GROUP_CONTROL_REASON_USAGE | GROUP_EVENT_REASON_ALIVE_NOT_TIMEOUT;
293         notTimeout = true;
294     } else if (newGroup >= ACTIVE_GROUP_DAILY && oneBundleHistory->bundleDailyTimeoutTimeStamp_ >
295         bootBasedTimeStampAdjusted) {
296         newGroup = ACTIVE_GROUP_DAILY;
297         groupReason = GROUP_CONTROL_REASON_USAGE | GROUP_EVENT_REASON_ALIVE_TIMEOUT;
298         notTimeout = true;
299     }
300     if (oldGroup < newGroup || notTimeout) {
301         BUNDLE_ACTIVE_LOGI("CheckAndUpdateGroup called SetAppGroup");
302         bundleUserHistory_->SetAppGroup(bundleName, userId, bootBasedTimeStamp, newGroup, groupReason, false);
303     }
304 }
305 
SetAppGroup(const std::string & bundleName,const int32_t userId,int32_t newGroup,uint32_t reason,const int64_t bootBasedTimeStamp,const bool isFlush)306 ErrCode BundleActiveGroupController::SetAppGroup(const std::string& bundleName, const int32_t userId,
307     int32_t newGroup, uint32_t reason, const int64_t bootBasedTimeStamp, const bool isFlush)
308 {
309     std::lock_guard<std::mutex> lock(mutex_);
310     if (!IsBundleInstalled(bundleName, userId)) {
311         return ERR_NO_APP_GROUP_INFO_IN_DATABASE;
312     }
313     auto oneBundleHistory = bundleUserHistory_->GetUsageHistoryForBundle(bundleName, userId, bootBasedTimeStamp, true);
314     if (!oneBundleHistory) {
315         return ERR_NO_APP_GROUP_INFO_IN_DATABASE;
316     }
317     return bundleUserHistory_->SetAppGroup(bundleName, userId, bootBasedTimeStamp, newGroup, reason, isFlush);
318 }
319 
IsBundleIdle(const std::string & bundleName,const int32_t userId)320 int32_t BundleActiveGroupController::IsBundleIdle(const std::string& bundleName, const int32_t userId)
321 {
322     std::lock_guard<std::mutex> lock(mutex_);
323     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
324     if (IsBundleInstalled(bundleName, userId) == false) {
325         return -1;
326     }
327     int64_t bootBasedTimeStamp = timer->GetBootTimeMs();
328     auto oneBundleHistory = bundleUserHistory_->GetUsageHistoryForBundle(
329         bundleName, userId, bootBasedTimeStamp, false);
330     if (oneBundleHistory == nullptr) {
331         return 1;
332     } else if (oneBundleHistory->currentGroup_ >= ACTIVE_GROUP_RARE) {
333         BUNDLE_ACTIVE_LOGI("IsBundleIdle, bundle group is %{public}d", oneBundleHistory->currentGroup_);
334         return 1;
335     } else {
336         BUNDLE_ACTIVE_LOGI("IsBundleIdle, bundle group is %{public}d", oneBundleHistory->currentGroup_);
337         return 0;
338     }
339 }
340 
QueryAppGroup(int32_t & appGroup,const std::string & bundleName,const int32_t userId)341 ErrCode BundleActiveGroupController::QueryAppGroup(int32_t& appGroup,
342     const std::string& bundleName, const int32_t userId)
343 {
344     std::lock_guard<std::mutex> lock(mutex_);
345     if (bundleName.empty()) {
346         BUNDLE_ACTIVE_LOGE("bundleName can not get by userId");
347         return ERR_NO_APP_GROUP_INFO_IN_DATABASE;
348     }
349     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
350     if (!IsBundleInstalled(bundleName, userId)) {
351         BUNDLE_ACTIVE_LOGI("QueryAppGroup is not bundleInstalled");
352         return ERR_APPLICATION_IS_NOT_INSTALLED;
353     }
354     int64_t bootBasedTimeStamp = timer->GetBootTimeMs();
355     auto oneBundleHistory = bundleUserHistory_->GetUsageHistoryForBundle(
356         bundleName, userId, bootBasedTimeStamp, false);
357     if (!oneBundleHistory) {
358         return ERR_NO_APP_GROUP_INFO_IN_DATABASE;
359     }
360     BUNDLE_ACTIVE_LOGI("QueryAppGroup group is %{public}d", oneBundleHistory->currentGroup_);
361     appGroup = oneBundleHistory->currentGroup_;
362     return ERR_OK;
363 }
364 
IsBundleInstalled(const std::string & bundleName,const int32_t userId)365 bool BundleActiveGroupController::IsBundleInstalled(const std::string& bundleName, const int32_t userId)
366 {
367     ApplicationInfo bundleInfo;
368     if (!sptrBundleMgr_) {
369         return false;
370     }
371     bool getInfoIsSuccess = sptrBundleMgr_->GetApplicationInfo(bundleName, ApplicationFlag::GET_BASIC_APPLICATION_INFO,
372         userId, bundleInfo);
373     if (getInfoIsSuccess == false) {
374         BUNDLE_ACTIVE_LOGE("IsBundleInstalled bundle is not installed!");
375         return false;
376     }
377     return true;
378 }
379 
ShutDown(const int64_t bootBasedTimeStamp,const int32_t userId)380 void BundleActiveGroupController::ShutDown(const int64_t bootBasedTimeStamp, const int32_t userId)
381 {
382     BUNDLE_ACTIVE_LOGI("ShutDown called");
383     CheckEachBundleState(userId);
384     bundleUserHistory_->UpdateBootBasedAndScreenTime(false, bootBasedTimeStamp, true);
385 }
386 
IsScreenOn()387 bool BundleActiveGroupController::IsScreenOn()
388 {
389     bool result = PowerMgrClient::GetInstance().IsScreenOn();
390     BUNDLE_ACTIVE_LOGI("IsScreenOn() is %{public}d", result);
391     return result;
392 }
393 }  // namespace DeviceUsageStats
394 }  // namespace OHOS
395 
396