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