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