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