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 "bundle_active_user_service.h"
17 #include "bundle_active_core.h"
18 #include "bundle_active_log.h"
19 #include "bundle_active_util.h"
20 #include "bundle_active_bundle_mgr_helper.h"
21
22 namespace OHOS {
23 namespace DeviceUsageStats {
24 const int32_t MAIN_APP_INDEX = 0;
Init(const int64_t timeStamp)25 void BundleActiveUserService::Init(const int64_t timeStamp)
26 {
27 database_.InitDatabaseTableInfo(timeStamp);
28 database_.InitUsageGroupDatabase(APP_GROUP_DATABASE_INDEX, true);
29 BUNDLE_ACTIVE_LOGI("Init called");
30 LoadActiveStats(timeStamp, false, false);
31 LoadModuleAndFormStats();
32 PrintInMemFormStats(debugUserService_, true);
33 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
34 PrintInMemPackageStats(0, debugUserService_);
35 std::shared_ptr<BundleActivePeriodStats> currentDailyStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
36 if (currentDailyStats != nullptr) {
37 BundleActiveEvent startupEvent(BundleActiveEvent::STARTUP, timeStamp - ONE_SECOND_MILLISECONDS);
38 startupEvent.bundleName_ = BundleActiveEvent::DEVICE_EVENT_PACKAGE_NAME;
39 currentDailyStats->AddEvent(startupEvent);
40 for (auto it : currentDailyStats->events_.events_) {
41 BUNDLE_ACTIVE_LOGI("Init event id is %{public}d, time stamp is %{public}lld",
42 it.eventId_, (long long)it.timeStamp_);
43 }
44 BUNDLE_ACTIVE_LOGI("Init currentDailyStats begintime is %{public}lld, "
45 "expire time is %{public}lld", (long long)currentDailyStats->beginTime_,
46 (long long)dailyExpiryDate_.GetMilliseconds());
47 }
48 }
49
OnUserRemoved()50 void BundleActiveUserService::OnUserRemoved()
51 {
52 database_.OnPackageUninstalled(userId_, "", 0, 0);
53 }
54
DeleteUninstalledBundleStats(const std::string & bundleName,const int32_t uid,const int32_t appIndex)55 void BundleActiveUserService::DeleteUninstalledBundleStats(const std::string& bundleName, const int32_t uid,
56 const int32_t appIndex)
57 {
58 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
59 for (auto it : currentStats_) {
60 if (it != nullptr) {
61 DeleteMemUsageStats(it, bundleName, uid, appIndex);
62 DeleteMemEvent(it, bundleName, uid, appIndex);
63 DeleteMemRecords(it, bundleName, uid, appIndex);
64 DeleteMemPackageUidSet(it, bundleName, uid, appIndex);
65 }
66 }
67 database_.OnPackageUninstalled(userId_, bundleName, uid, appIndex);
68 }
69
DeleteMemUsageStats(const std::shared_ptr<BundleActivePeriodStats> & currentStats,const std::string & bundleName,const int32_t deletedUid,const int32_t appIndex)70 void BundleActiveUserService::DeleteMemUsageStats(const std::shared_ptr<BundleActivePeriodStats>& currentStats,
71 const std::string& bundleName, const int32_t deletedUid, const int32_t appIndex)
72 {
73 std::string bundleStatsKey = BundleActiveUtil::GetBundleUsageKey(bundleName, deletedUid);
74 if (appIndex != MAIN_APP_INDEX) {
75 if (currentStats->bundleStats_.find(bundleStatsKey) != currentStats->bundleStats_.end()) {
76 currentStats->bundleStats_.erase(bundleStatsKey);
77 }
78 return;
79 }
80 auto uidSet = BundleActiveBundleMgrHelper::GetInstance()->GetPackageUidSet(bundleName);
81 for (auto it: uidSet) {
82 bundleStatsKey = BundleActiveUtil::GetBundleUsageKey(bundleName, it);
83 currentStats->bundleStats_.erase(bundleStatsKey);
84 }
85 }
86
DeleteMemEvent(const std::shared_ptr<BundleActivePeriodStats> & currentStats,const std::string & bundleName,const int32_t deletedUid,const int32_t appIndex)87 void BundleActiveUserService::DeleteMemEvent(const std::shared_ptr<BundleActivePeriodStats>& currentStats,
88 const std::string& bundleName, const int32_t deletedUid, const int32_t appIndex)
89 {
90 if (appIndex != MAIN_APP_INDEX) {
91 for (auto eventIter = currentStats->events_.events_.begin();
92 eventIter != currentStats->events_.events_.end();) {
93 if (eventIter->bundleName_ == bundleName && eventIter->uid_ == deletedUid) {
94 eventIter = currentStats->events_.events_.erase(eventIter);
95 } else {
96 eventIter++;
97 }
98 }
99 return;
100 }
101 auto uidSet = BundleActiveBundleMgrHelper::GetInstance()->GetPackageUidSet(bundleName);
102 for (auto eventIter = currentStats->events_.events_.begin();
103 eventIter != currentStats->events_.events_.end();) {
104 if (eventIter->bundleName_ == bundleName && uidSet.find(eventIter->uid_) != uidSet.end()) {
105 eventIter = currentStats->events_.events_.erase(eventIter);
106 } else {
107 eventIter++;
108 }
109 }
110 }
111
DeleteMemRecords(const std::shared_ptr<BundleActivePeriodStats> & currentStats,const std::string & bundleName,const int32_t deletedUid,const int32_t appIndex)112 void BundleActiveUserService::DeleteMemRecords(const std::shared_ptr<BundleActivePeriodStats>& currentStats,
113 const std::string& bundleName, const int32_t deletedUid, const int32_t appIndex)
114 {
115 if (appIndex != MAIN_APP_INDEX) {
116 for (auto it = moduleRecords_.begin(); it != moduleRecords_.end();) {
117 std::string moduleKey = bundleName + " " + std::to_string(deletedUid);
118 if (it->first.find(moduleKey) != std::string::npos) {
119 it = moduleRecords_.erase(it);
120 } else {
121 it++;
122 }
123 }
124 return;
125 }
126 for (auto it = moduleRecords_.begin(); it != moduleRecords_.end();) {
127 if (it->first.find(bundleName) != std::string::npos) {
128 it = moduleRecords_.erase(it);
129 } else {
130 it++;
131 }
132 }
133 }
134
DeleteMemPackageUidSet(const std::shared_ptr<BundleActivePeriodStats> & currentStats,const std::string & bundleName,const int32_t deletedUid,const int32_t appIndex)135 void BundleActiveUserService::DeleteMemPackageUidSet(const std::shared_ptr<BundleActivePeriodStats>& currentStats,
136 const std::string& bundleName, const int32_t deletedUid, const int32_t appIndex)
137 {
138 if (appIndex != MAIN_APP_INDEX) {
139 BundleActiveBundleMgrHelper::GetInstance()->DeletePackageUid(bundleName, deletedUid);
140 return;
141 }
142 BundleActiveBundleMgrHelper::GetInstance()->DeleteMemPackage(bundleName);
143 }
144
RenewTableTime(int64_t oldTime,int64_t newTime)145 void BundleActiveUserService::RenewTableTime(int64_t oldTime, int64_t newTime)
146 {
147 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
148 BUNDLE_ACTIVE_LOGI("RenewTableTime called current event size is %{public}d", currentStats_[0]->events_.Size());
149 database_.RenewTableTime(newTime - oldTime);
150 }
151
NotifyStatsChanged()152 void BundleActiveUserService::NotifyStatsChanged()
153 {
154 BUNDLE_ACTIVE_LOGD("NotifyStatsChanged stat change is %{public}d, user is %{public}d", statsChanged_, userId_);
155 if (!statsChanged_) {
156 BUNDLE_ACTIVE_LOGD("NotifyStatsChanged() set stats changed to true");
157 statsChanged_ = true;
158 listener_.OnStatsChanged(userId_);
159 }
160 }
161
NotifyNewUpdate()162 void BundleActiveUserService::NotifyNewUpdate()
163 {
164 listener_.OnSystemUpdate(userId_);
165 }
166
ReportEvent(const BundleActiveEvent & event)167 void BundleActiveUserService::ReportEvent(const BundleActiveEvent& event)
168 {
169 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
170 BUNDLE_ACTIVE_LOGD("ReportEvent, B time is %{public}lld, E time is %{public}lld, userId is %{public}d,",
171 (long long)currentStats_[0]->beginTime_, (long long)dailyExpiryDate_.GetMilliseconds(), userId_);
172 event.PrintEvent(debugUserService_);
173 if (event.timeStamp_ >= dailyExpiryDate_.GetMilliseconds()) {
174 BUNDLE_ACTIVE_LOGI("ReportEvent later than daily expire, renew data in memory");
175 RenewStatsInMemory(event.timeStamp_);
176 }
177 std::shared_ptr<BundleActivePeriodStats> currentDailyStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
178 if (!currentDailyStats) {
179 return;
180 }
181 bool incrementBundleLaunch = false;
182 if (event.eventId_ != BundleActiveEvent::SYSTEM_INTERACTIVE && event.eventId_ != BundleActiveEvent::FLUSH) {
183 currentDailyStats->AddEvent(event);
184 }
185 if (event.eventId_ == BundleActiveEvent::ABILITY_FOREGROUND) {
186 if (!event.bundleName_.empty() && event.bundleName_ != lastForegroundBundle_) {
187 incrementBundleLaunch = true;
188 lastForegroundBundle_ = event.bundleName_;
189 }
190 }
191 UpdatePeriodStats(event, incrementBundleLaunch);
192 }
193
UpdatePeriodStats(const BundleActiveEvent & event,const bool & incrementBundleLaunch)194 void BundleActiveUserService::UpdatePeriodStats(const BundleActiveEvent& event, const bool& incrementBundleLaunch)
195 {
196 for (auto it : currentStats_) {
197 switch (event.eventId_) {
198 case BundleActiveEvent::SCREEN_INTERACTIVE:
199 it->UpdateScreenInteractive(event.timeStamp_);
200 break;
201 case BundleActiveEvent::SCREEN_NON_INTERACTIVE:
202 it->UpdateScreenNonInteractive(event.timeStamp_);
203 break;
204 case BundleActiveEvent::KEYGUARD_SHOWN:
205 it->UpdateKeyguardShown(event.timeStamp_);
206 break;
207 case BundleActiveEvent::KEYGUARD_HIDDEN:
208 it->UpdateKeyguardHidden(event.timeStamp_);
209 break;
210 default:
211 it->Update(event.bundleName_, event.continuousTaskAbilityName_, event.timeStamp_, event.eventId_,
212 event.abilityId_, event.uid_);
213 if (incrementBundleLaunch) {
214 std::string bundleStatsKey = event.bundleName_ + std::to_string(event.uid_);
215 it->bundleStats_[bundleStatsKey]->IncrementBundleLaunchedCount();
216 }
217 break;
218 }
219 }
220 if (event.eventId_ != BundleActiveEvent::FLUSH) {
221 NotifyStatsChanged();
222 }
223 }
224
ReportForShutdown(const BundleActiveEvent & event)225 void BundleActiveUserService::ReportForShutdown(const BundleActiveEvent& event)
226 {
227 BUNDLE_ACTIVE_LOGI("ReportForShutdown() called");
228 if (event.eventId_ != BundleActiveEvent::SHUTDOWN) {
229 return;
230 }
231 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
232 currentStats_[BundleActivePeriodStats::PERIOD_DAILY]->AddEvent(event);
233 if (event.timeStamp_ >= dailyExpiryDate_.GetMilliseconds()) {
234 BUNDLE_ACTIVE_LOGI(" BundleActiveUserService::ReportEvent later than daily expire");
235 RenewStatsInMemory(event.timeStamp_);
236 }
237 for (auto it : currentStats_) {
238 it->Update(event.bundleName_, event.continuousTaskAbilityName_, event.timeStamp_, event.eventId_,
239 event.abilityId_, event.uid_);
240 }
241 BUNDLE_ACTIVE_LOGI("ReportForShutdown called notify");
242 NotifyStatsChanged();
243 }
244
RestoreStats(bool forced)245 void BundleActiveUserService::RestoreStats(bool forced)
246 {
247 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
248 BUNDLE_ACTIVE_LOGI("RestoreStats() called, userId is %{public}d", userId_);
249 if (statsChanged_ || forced) {
250 BUNDLE_ACTIVE_LOGI("RestoreStats() stat changed is true");
251 for (uint32_t i = 0; i < currentStats_.size(); i++) {
252 if (!currentStats_[i]) {
253 continue;
254 }
255 if (!currentStats_[i]->bundleStats_.empty()) {
256 database_.UpdateBundleUsageData(i, *(currentStats_[i]));
257 }
258 if (!currentStats_[i]->events_.events_.empty() && i == BundleActivePeriodStats::PERIOD_DAILY) {
259 database_.UpdateEventData(i, *(currentStats_[i]));
260 }
261 }
262 if (!moduleRecords_.empty()) {
263 database_.UpdateModuleData(userId_, moduleRecords_,
264 currentStats_[BundleActivePeriodStats::PERIOD_DAILY]->beginTime_);
265 }
266 currentStats_[BundleActivePeriodStats::PERIOD_DAILY]->events_.Clear();
267 statsChanged_ = false;
268 BUNDLE_ACTIVE_LOGI("change statsChanged_ to %{public}d user is %{public}d", statsChanged_, userId_);
269 }
270 }
271
LoadActiveStats(const int64_t timeStamp,const bool & force,const bool & timeChanged)272 void BundleActiveUserService::LoadActiveStats(const int64_t timeStamp, const bool& force, const bool& timeChanged)
273 {
274 BUNDLE_ACTIVE_LOGI("LoadActiveStats called");
275 BundleActiveCalendar tmpCalendar(0);
276 if (debugUserService_ == true) {
277 tmpCalendar.ChangeToDebug();
278 }
279 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
280 for (uint32_t intervalType = 0; intervalType < periodLength_.size(); intervalType++) {
281 tmpCalendar.SetMilliseconds(timeStamp);
282 tmpCalendar.TruncateTo(static_cast<int32_t>(intervalType));
283 if (!force && currentStats_[intervalType] != nullptr &&
284 currentStats_[intervalType]->beginTime_ == tmpCalendar.GetMilliseconds()) {
285 continue;
286 }
287 std::shared_ptr<BundleActivePeriodStats> stats = database_.GetCurrentUsageData(intervalType, userId_);
288 currentStats_[intervalType].reset(); // 当前interval stat置空
289 if (stats != nullptr) { // 找出最近的stats
290 BUNDLE_ACTIVE_LOGI("LoadActiveStats inter type is %{public}d, "
291 "bundle size is %{public}zu", intervalType, stats->bundleStats_.size());
292 // 如果当前时间在stats的统计时间范围内,则可以从数据库加载数据
293 BUNDLE_ACTIVE_LOGI("interval type is %{public}d, database stat BEGIN time is %{public}lld, "
294 "timestamp is %{public}lld, expect end is %{public}lld",
295 intervalType, (long long)stats->beginTime_, (long long)timeStamp,
296 (long long)stats->beginTime_ + periodLength_[intervalType]);
297 if (timeStamp > stats->beginTime_ && timeStamp < stats->beginTime_ + periodLength_[intervalType]) {
298 currentStats_[intervalType] = stats;
299 }
300 }
301 if (currentStats_[intervalType] != nullptr) {
302 currentStats_[intervalType]->beginTime_ = tmpCalendar.GetMilliseconds();
303 currentStats_[intervalType]->endTime_ = timeStamp;
304 continue;
305 }
306 BUNDLE_ACTIVE_LOGI("LoadActiveStats [Server]create new interval stats!");
307 currentStats_[intervalType] = std::make_shared<BundleActivePeriodStats>();
308 currentStats_[intervalType]->userId_ = userId_;
309 currentStats_[intervalType]->beginTime_ = tmpCalendar.GetMilliseconds();
310 currentStats_[intervalType]->endTime_ = timeStamp;
311 }
312 statsChanged_ = false;
313 UpdateExpiryDate(timeChanged, tmpCalendar, timeStamp);
314 listener_.OnStatsReload();
315 BUNDLE_ACTIVE_LOGI("LoadActiveStats current expire time is %{public}lld, "
316 "begin time is %{public}lld", (long long)dailyExpiryDate_.GetMilliseconds(),
317 (long long)tmpCalendar.GetMilliseconds());
318 }
319
UpdateExpiryDate(const bool timeChanged,BundleActiveCalendar & tmpCalendar,const int64_t timeStamp)320 void BundleActiveUserService::UpdateExpiryDate(const bool timeChanged,
321 BundleActiveCalendar& tmpCalendar, const int64_t timeStamp)
322 {
323 // 延长统计时间到第二天0点
324 if (timeChanged) {
325 dailyExpiryDate_.SetMilliseconds(currentStats_[BundleActivePeriodStats::PERIOD_DAILY]->beginTime_);
326 } else {
327 dailyExpiryDate_.SetMilliseconds(timeStamp);
328 }
329 dailyExpiryDate_.IncreaseDays(1);
330 if (!timeChanged) {
331 dailyExpiryDate_.TruncateToDay();
332 }
333 }
334
LoadModuleAndFormStats()335 void BundleActiveUserService::LoadModuleAndFormStats()
336 {
337 database_.LoadModuleData(userId_, moduleRecords_);
338 database_.LoadFormData(userId_, moduleRecords_);
339 }
340
FlushDataInMem(std::set<std::string> & continueBundles,std::map<std::string,std::map<std::string,int>> & continueAbilities,std::map<std::string,std::map<std::string,int>> & continueServices)341 void BundleActiveUserService::FlushDataInMem(std::set<std::string> &continueBundles,
342 std::map<std::string, std::map<std::string, int>> &continueAbilities,
343 std::map<std::string, std::map<std::string, int>> &continueServices)
344 {
345 for (std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator it = currentStats_.begin();
346 it != currentStats_.end(); ++it) {
347 if (*it == nullptr) {
348 continue;
349 }
350 for (auto bundleUsageStatsPair : (*it)->bundleStats_) {
351 if (bundleUsageStatsPair.second == nullptr) {
352 continue;
353 }
354 BundleActivePackageStats bundleUsageStats(*(bundleUsageStatsPair.second));
355 std::string bundleStatsKey = bundleUsageStats.bundleName_ + std::to_string(bundleUsageStats.uid_);
356 if (!bundleUsageStats.abilities_.empty()) {
357 continueAbilities[bundleStatsKey] = bundleUsageStats.abilities_;
358 }
359 if (!bundleUsageStats.longTimeTasks_.empty()) {
360 continueServices[bundleStatsKey] = bundleUsageStats.longTimeTasks_;
361 }
362 (*it)->Update(bundleUsageStats.bundleName_, "", dailyExpiryDate_.GetMilliseconds() - 1,
363 BundleActiveEvent::END_OF_THE_DAY, "", bundleUsageStats.uid_);
364
365 continueBundles.insert(bundleUsageStats.bundleName_);
366 NotifyStatsChanged();
367 }
368 (*it)->CommitTime(dailyExpiryDate_.GetMilliseconds() - 1);
369 }
370 }
371
UpdateContinueAbilitiesMemory(const int64_t & beginTime,const std::map<std::string,std::map<std::string,int>> & continueAbilities,const std::string & continueBundleName,const std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator & itInterval)372 void BundleActiveUserService::UpdateContinueAbilitiesMemory(const int64_t& beginTime,
373 const std::map<std::string, std::map<std::string, int>>& continueAbilities, const std::string& continueBundleName,
374 const std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator& itInterval)
375 {
376 auto uidSet = BundleActiveBundleMgrHelper::GetInstance()->GetPackageUidSet(continueBundleName);
377 for (auto uid: uidSet) {
378 std::string continueAbilitiesKey = BundleActiveUtil::GetBundleUsageKey(continueBundleName, uid);
379 auto ability = continueAbilities.find(continueAbilitiesKey);
380 if (ability == continueAbilities.end()) {
381 return;
382 }
383 for (auto it = ability->second.begin(); it != ability->second.end(); ++it) {
384 if (it->second == BundleActiveEvent::ABILITY_BACKGROUND) {
385 continue;
386 }
387 (*itInterval)->Update(continueBundleName, "", beginTime, it->second, it->first, uid);
388 }
389 }
390 }
391
UpdateContinueServicesMemory(const int64_t & beginTime,const std::map<std::string,std::map<std::string,int>> & continueServices,const std::string & continueBundleName,const std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator & itInterval)392 void BundleActiveUserService::UpdateContinueServicesMemory(const int64_t& beginTime,
393 const std::map<std::string, std::map<std::string, int>>& continueServices, const std::string& continueBundleName,
394 const std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator& itInterval)
395 {
396 auto uidSet = BundleActiveBundleMgrHelper::GetInstance()->GetPackageUidSet(continueBundleName);
397
398 for (auto uid: uidSet) {
399 std::string continueServicesKey = BundleActiveUtil::GetBundleUsageKey(continueBundleName, uid);
400 auto service = continueServices.find(continueServicesKey);
401 if (service == continueServices.end()) {
402 return;
403 }
404 for (auto it = service->second.begin(); it != service->second.end(); ++it) {
405 (*itInterval)->Update(continueBundleName, it->first, beginTime, it->second, "", uid);
406 }
407 }
408 }
409
RenewStatsInMemory(const int64_t timeStamp)410 void BundleActiveUserService::RenewStatsInMemory(const int64_t timeStamp)
411 {
412 std::set<std::string> continueBundles;
413 std::map<std::string, std::map<std::string, int>> continueAbilities;
414 std::map<std::string, std::map<std::string, int>> continueServices;
415 // update stat in memory.
416 FlushDataInMem(continueBundles, continueAbilities, continueServices);
417 RestoreStats(true);
418 database_.RemoveOldData(timeStamp);
419 // create new stats
420 LoadActiveStats(timeStamp, false, false);
421 // update timestamps of events in memory
422 for (std::string continueBundleName : continueBundles) {
423 int64_t beginTime = currentStats_[BundleActivePeriodStats::PERIOD_DAILY]->beginTime_;
424 for (std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator itInterval = currentStats_.begin();
425 itInterval != currentStats_.end(); ++itInterval) {
426 UpdateContinueAbilitiesMemory(beginTime, continueAbilities, continueBundleName, itInterval);
427 UpdateContinueServicesMemory(beginTime, continueServices, continueBundleName, itInterval);
428 }
429 }
430 RestoreStats(true);
431 }
432
QueryBundleStatsInfos(std::vector<BundleActivePackageStats> & PackageStats,int32_t intervalType,const int64_t beginTime,const int64_t endTime,const int32_t userId,const std::string & bundleName)433 ErrCode BundleActiveUserService::QueryBundleStatsInfos(std::vector<BundleActivePackageStats>& PackageStats,
434 int32_t intervalType, const int64_t beginTime, const int64_t endTime, const int32_t userId,
435 const std::string& bundleName)
436 {
437 if (intervalType == BundleActivePeriodStats::PERIOD_BEST) {
438 intervalType = database_.GetOptimalIntervalType(beginTime, endTime);
439 if (intervalType < 0) {
440 intervalType = BundleActivePeriodStats::PERIOD_DAILY;
441 }
442 }
443 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
444 if (intervalType < 0 || intervalType >= static_cast<int32_t>(currentStats_.size())) {
445 return ERR_USAGE_STATS_INTERVAL_NUMBER;
446 }
447 auto currentStats = currentStats_[intervalType];
448 if (currentStats == nullptr) {
449 BUNDLE_ACTIVE_LOGE("current interval stat is null!");
450 return ERR_MEMORY_OPERATION_FAILED;
451 }
452 if (currentStats->endTime_ == 0) {
453 if (beginTime > currentStats->beginTime_ + periodLength_[intervalType]) {
454 return ERR_QUERY_TIME_OUT_OF_RANGE;
455 } else {
456 PackageStats = database_.QueryDatabaseUsageStats(intervalType, beginTime, endTime, userId, bundleName);
457 return ERR_OK;
458 }
459 } else if (beginTime >= currentStats->endTime_) {
460 return ERR_QUERY_TIME_OUT_OF_RANGE;
461 }
462 int64_t truncatedEndTime = std::min(currentStats->beginTime_, endTime);
463 PackageStats = database_.QueryDatabaseUsageStats(intervalType, beginTime, truncatedEndTime, userId, bundleName);
464 BUNDLE_ACTIVE_LOGI("Query package data in db PackageStats size is %{public}zu", PackageStats.size());
465 PrintInMemPackageStats(intervalType, debugUserService_);
466 // if we need a in-memory stats, combine current stats with PackageStats from database.
467 if (endTime > currentStats->beginTime_) {
468 BUNDLE_ACTIVE_LOGI("QueryBundleStatsInfos need in memory stats");
469 for (auto it : currentStats->bundleStats_) {
470 bool isTimeLegal = (it.second->totalInFrontTime_ != 0 || it.second->totalContiniousTaskUsedTime_ != 0) &&
471 it.second->lastTimeUsed_ >= beginTime && it.second->lastTimeUsed_ <= endTime;
472 bool isBundleNameEqual = !bundleName.empty() && it.second->bundleName_ == bundleName;
473 it.second->userId_ = userId;
474 if (bundleName.empty() && isTimeLegal) {
475 PackageStats.push_back(*(it.second));
476 } else if (isBundleNameEqual && isTimeLegal) {
477 PackageStats.push_back(*(it.second));
478 }
479 }
480 }
481 return ERR_OK;
482 }
483
QueryBundleEvents(std::vector<BundleActiveEvent> & bundleActiveEvent,const int64_t beginTime,const int64_t endTime,const int32_t userId,const std::string & bundleName)484 ErrCode BundleActiveUserService::QueryBundleEvents(std::vector<BundleActiveEvent>& bundleActiveEvent,
485 const int64_t beginTime, const int64_t endTime, const int32_t userId, const std::string& bundleName)
486 {
487 BUNDLE_ACTIVE_LOGI("QueryBundleEvents called");
488 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
489 auto currentStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
490 if (currentStats == nullptr) {
491 BUNDLE_ACTIVE_LOGE("current interval stat is null!");
492 return ERR_MEMORY_OPERATION_FAILED;
493 }
494 if (beginTime >= currentStats->endTime_) {
495 return ERR_QUERY_TIME_OUT_OF_RANGE;
496 }
497 BUNDLE_ACTIVE_LOGI("Query event bundle name is %{public}s", bundleName.c_str());
498 bundleActiveEvent = database_.QueryDatabaseEvents(beginTime, endTime, userId, bundleName);
499 PrintInMemEventStats(debugUserService_);
500 if (currentStats->endTime_ == 0) {
501 BUNDLE_ACTIVE_LOGI("QueryBundleEvents result in db is %{public}zu", bundleActiveEvent.size());
502 return ERR_OK;
503 }
504 // if we need a in-memory stats, combine current stats with bundleActiveEvent from database.
505 if (endTime > currentStats->beginTime_) {
506 BUNDLE_ACTIVE_LOGI("QueryBundleEvents need in memory stats");
507 int32_t eventBeginIdx = currentStats->events_.FindBestIndex(beginTime);
508 int32_t eventSize = currentStats->events_.Size();
509 for (int32_t i = eventBeginIdx; i < eventSize; i++) {
510 if (currentStats->events_.events_[i].timeStamp_ > endTime) {
511 continue;
512 }
513 if (bundleName.empty() || currentStats->events_.events_[i].bundleName_ == bundleName) {
514 bundleActiveEvent.push_back(currentStats->events_.events_[i]);
515 }
516 }
517 }
518 BUNDLE_ACTIVE_LOGI("QueryBundleEvents result in db and memory is %{public}zu", bundleActiveEvent.size());
519 return ERR_OK;
520 }
521
QueryModuleUsageRecords(int32_t maxNum,std::vector<BundleActiveModuleRecord> & results)522 int32_t BundleActiveUserService::QueryModuleUsageRecords(int32_t maxNum, std::vector<BundleActiveModuleRecord>& results)
523 {
524 BUNDLE_ACTIVE_LOGI("QueryModuleUsageRecords called, MAX IS %{public}d", maxNum);
525 for (auto oneModuleRecord = moduleRecords_.begin(); oneModuleRecord != moduleRecords_.end(); oneModuleRecord++) {
526 if (!oneModuleRecord->second) {
527 continue;
528 }
529 results.emplace_back(*(oneModuleRecord->second));
530 }
531 std::sort(results.begin(), results.end(), BundleActiveModuleRecord::cmp);
532 if (static_cast<int32_t>(results.size()) > maxNum) {
533 results.resize(maxNum);
534 }
535 for (auto& result : results) {
536 std::sort(result.formRecords_.begin(), result.formRecords_.end(), BundleActiveFormRecord::cmp);
537 }
538 return 0;
539 }
540
QueryDeviceEventStats(int64_t beginTime,int64_t endTime,std::vector<BundleActiveEventStats> & eventStats,int32_t userId)541 int32_t BundleActiveUserService::QueryDeviceEventStats(int64_t beginTime, int64_t endTime,
542 std::vector<BundleActiveEventStats>& eventStats, int32_t userId)
543 {
544 BUNDLE_ACTIVE_LOGI("QueryDeviceEventStats called");
545 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
546 auto currentStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
547 if (currentStats == nullptr) {
548 BUNDLE_ACTIVE_LOGE("current interval stat is null!");
549 return ERR_MEMORY_OPERATION_FAILED;
550 }
551 if (beginTime >= currentStats->endTime_) {
552 return ERR_TIME_OPERATION_FAILED;
553 }
554 std::map<std::string, BundleActiveEventStats> systemEventStats;
555 database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_LOCK, beginTime, endTime, systemEventStats, userId);
556 database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_UNLOCK, beginTime, endTime, systemEventStats, userId);
557 database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_SLEEP, beginTime, endTime, systemEventStats, userId);
558 database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_WAKEUP, beginTime, endTime, systemEventStats, userId);
559 BUNDLE_ACTIVE_LOGI("Query eventStats data in db result size is %{public}zu", systemEventStats.size());
560 PrintInMemEventStats(debugUserService_);
561 // if we need a in-memory stats, combine current stats with result from database.
562 if (currentStats->endTime_ != 0 && endTime > currentStats->beginTime_) {
563 BUNDLE_ACTIVE_LOGI("QueryDeviceEventStats need in memory stats");
564 GetCachedSystemEvents(currentStats, beginTime, endTime, systemEventStats);
565 }
566 std::map<std::string, BundleActiveEventStats>::iterator iter;
567 for (iter = systemEventStats.begin(); iter != systemEventStats.end(); ++iter) {
568 eventStats.push_back(iter->second);
569 }
570 return ERR_OK;
571 }
572
GetCachedSystemEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & systemEventStats)573 void BundleActiveUserService::GetCachedSystemEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,
574 int64_t beginTime, int64_t endTime, std::map<std::string, BundleActiveEventStats>& systemEventStats)
575 {
576 int32_t eventBeginIdx = currentStats->events_.FindBestIndex(beginTime);
577 int32_t eventSize = currentStats->events_.Size();
578 BundleActiveEventStats singleEventStats;
579 std::map<std::string, BundleActiveEventStats>::iterator iter;
580 for (int32_t i = eventBeginIdx; i < eventSize; i++) {
581 if ((currentStats->events_.events_[i].timeStamp_ <= endTime)
582 && ((currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_LOCK)
583 || (currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_UNLOCK)
584 || (currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_SLEEP)
585 || (currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_WAKEUP))) {
586 singleEventStats.name_ = currentStats->events_.events_[i].bundleName_;
587 iter = systemEventStats.find(singleEventStats.name_);
588 if (iter != systemEventStats.end()) {
589 iter->second.count_++;
590 } else {
591 singleEventStats.eventId_ = currentStats->events_.events_[i].eventId_;
592 singleEventStats.count_ = 1;
593 systemEventStats.insert(std::pair<std::string, BundleActiveEventStats>(
594 singleEventStats.name_, singleEventStats));
595 }
596 }
597 }
598 }
599
QueryNotificationEventStats(int64_t beginTime,int64_t endTime,std::vector<BundleActiveEventStats> & eventStats,int32_t userId)600 int32_t BundleActiveUserService::QueryNotificationEventStats(int64_t beginTime, int64_t endTime,
601 std::vector<BundleActiveEventStats>& eventStats, int32_t userId)
602 {
603 BUNDLE_ACTIVE_LOGI("QueryNotificationEventStats called");
604 std::lock_guard<ffrt::recursive_mutex> lock(statsMutex_);
605 auto currentStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
606 if (currentStats == nullptr) {
607 BUNDLE_ACTIVE_LOGE("current interval stat is null!");
608 return ERR_MEMORY_OPERATION_FAILED;
609 }
610 if (beginTime >= currentStats->endTime_) {
611 return ERR_TIME_OPERATION_FAILED;
612 }
613 std::map<std::string, BundleActiveEventStats> notificationEventStats;
614 database_.QueryNotificationEventStats(BundleActiveEvent::NOTIFICATION_SEEN,
615 beginTime, endTime, notificationEventStats, userId);
616 BUNDLE_ACTIVE_LOGI("Query eventStats data in db result size is %{public}zu", notificationEventStats.size());
617 PrintInMemEventStats(debugUserService_);
618 // if we need a in-memory stats, combine current stats with result from database.
619 if (currentStats->endTime_ != 0 && endTime > currentStats->beginTime_) {
620 BUNDLE_ACTIVE_LOGI("QueryNotificationEventStats need in memory stats");
621 GetCachedNotificationEvents(currentStats, beginTime, endTime, notificationEventStats);
622 }
623 std::map<std::string, BundleActiveEventStats>::iterator iter;
624 for (iter = notificationEventStats.begin(); iter != notificationEventStats.end(); ++iter) {
625 eventStats.push_back(iter->second);
626 }
627 return ERR_OK;
628 }
629
GetCachedNotificationEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & notificationEventStats)630 void BundleActiveUserService::GetCachedNotificationEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,
631 int64_t beginTime, int64_t endTime, std::map<std::string, BundleActiveEventStats>& notificationEventStats)
632 {
633 int32_t eventBeginIdx = currentStats->events_.FindBestIndex(beginTime);
634 int32_t eventSize = currentStats->events_.Size();
635 std::map<std::string, BundleActiveEventStats>::iterator iter;
636 BundleActiveEventStats singleEventStats;
637 for (int32_t i = eventBeginIdx; i < eventSize; i++) {
638 if ((currentStats->events_.events_[i].timeStamp_ <= endTime)
639 && (currentStats->events_.events_[i].eventId_== BundleActiveEvent::NOTIFICATION_SEEN)) {
640 singleEventStats.name_ = currentStats->events_.events_[i].bundleName_;
641 iter = notificationEventStats.find(singleEventStats.name_);
642 if (iter != notificationEventStats.end()) {
643 iter->second.count_++;
644 } else {
645 singleEventStats.eventId_ = BundleActiveEvent::NOTIFICATION_SEEN;
646 singleEventStats.count_ = 1;
647 notificationEventStats.insert(std::pair<std::string, BundleActiveEventStats>(
648 singleEventStats.name_, singleEventStats));
649 }
650 }
651 }
652 }
653
PrintInMemPackageStats(const int32_t idx,const bool debug)654 void BundleActiveUserService::PrintInMemPackageStats(const int32_t idx, const bool debug)
655 {
656 if (!debug) {
657 return;
658 }
659 BUNDLE_ACTIVE_LOGI("PrintInMemPackageStats called");
660 for (auto it : currentStats_[idx]->bundleStats_) {
661 BUNDLE_ACTIVE_LOGI("In mem, bundle name is %{public}s", it.first.c_str());
662 int64_t lastTimeUsed = it.second->lastTimeUsed_;
663 int64_t totalUsedTime = it.second->totalInFrontTime_;
664 int64_t lastTimeContinuousTaskUsed = it.second->lastContiniousTaskUsed_;
665 int64_t totalTimeContinuousTaskUsed = it.second->totalContiniousTaskUsedTime_;
666 int32_t uid = it.second->uid_;
667 BUNDLE_ACTIVE_LOGI("bundle stat is, totaltime is %{public}lld, lastTimeUsed is %{public}lld"
668 "total continuous task is %{public}lld, lastTimeContinuousTaskUsed is %{public}lld uid is %{public}d",
669 (long long)totalUsedTime, (long long)lastTimeUsed,
670 (long long)totalTimeContinuousTaskUsed, (long long)lastTimeContinuousTaskUsed, uid);
671 }
672 }
673
PrintInMemEventStats(const bool debug)674 void BundleActiveUserService::PrintInMemEventStats(const bool debug)
675 {
676 if (!debug) {
677 return;
678 }
679 BUNDLE_ACTIVE_LOGI("PrintInMemEventStats called");
680 int32_t idx = 0;
681 int32_t size = static_cast<int32_t>(currentStats_[idx]->events_.events_.size());
682 for (int32_t i = 0; i < size; i++) {
683 std::string abilityId = currentStats_[idx]->events_.events_[i].abilityId_;
684 std::string abilityname = currentStats_[idx]->events_.events_[i].abilityName_;
685 std::string bundlename = currentStats_[idx]->events_.events_[i].bundleName_;
686 int32_t eventid = currentStats_[idx]->events_.events_[i].eventId_;
687 int64_t timestamp = currentStats_[idx]->events_.events_[i].timeStamp_;
688 int32_t uid = currentStats_[idx]->events_.events_[i].uid_;
689 BUNDLE_ACTIVE_LOGI("In mem, event stat is, abilityid is %{public}s, abilityname is %{public}s, "
690 "bundlename is %{public}s, eventid is %{public}d, timestamp is %{public}lld, uid is %{public}d",
691 abilityId.c_str(), abilityname.c_str(), bundlename.c_str(), eventid, (long long)timestamp, uid);
692 }
693 }
694
PrintInMemFormStats(const bool debug,const bool printform)695 void BundleActiveUserService::PrintInMemFormStats(const bool debug, const bool printform)
696 {
697 if (!debug) {
698 return;
699 }
700 for (const auto& oneModule : moduleRecords_) {
701 if (oneModule.second) {
702 BUNDLE_ACTIVE_LOGI("bundle name is %{public}s, module name is %{public}s, "
703 "lastusedtime is %{public}lld, launchcount is %{public}d, uid is %{public}d",
704 oneModule.second->bundleName_.c_str(), oneModule.second->moduleName_.c_str(),
705 (long long)oneModule.second->lastModuleUsedTime_, oneModule.second->launchedCount_, oneModule.second->uid_);
706 BUNDLE_ACTIVE_LOGI("combined info is %{public}s", oneModule.first.c_str());
707 if (printform) {
708 for (const auto& oneForm : oneModule.second->formRecords_) {
709 BUNDLE_ACTIVE_LOGI("form name is %{public}s, form dimension is %{public}d, "
710 "form id is %{public}lld, "
711 "lasttouchtime is %{public}lld, touchcount is %{public}d", oneForm.formName_.c_str(),
712 oneForm.formDimension_, (long long)oneForm.formId_,
713 (long long)oneForm.formLastUsedTime_, oneForm.count_);
714 }
715 }
716 }
717 }
718 }
719
ReportModuleEvent(const BundleActiveEvent & event)720 void BundleActiveUserService::ReportModuleEvent(const BundleActiveEvent& event)
721 {
722 BUNDLE_ACTIVE_LOGD("ReportModuleEvent called");
723 if (event.eventId_ != BundleActiveEvent::ABILITY_FOREGROUND) {
724 return;
725 }
726 auto moduleRecord = GetOrCreateModuleRecord(event);
727 moduleRecord->UpdateModuleRecord(event.timeStamp_);
728 NotifyStatsChanged();
729 PrintInMemFormStats(debugUserService_, false);
730 }
731
ReportFormEvent(const BundleActiveEvent & event)732 void BundleActiveUserService::ReportFormEvent(const BundleActiveEvent& event)
733 {
734 BUNDLE_ACTIVE_LOGD("ReportFormEvent called");
735 auto moduleRecord = GetOrCreateModuleRecord(event);
736 if (event.eventId_ == BundleActiveEvent::FORM_IS_CLICKED && moduleRecord) {
737 moduleRecord->AddOrUpdateOneFormRecord(event.formName_, event.formDimension_, event.formId_,
738 event.timeStamp_, event.uid_);
739 NotifyStatsChanged();
740 } else if (event.eventId_ == BundleActiveEvent::FORM_IS_REMOVED && moduleRecord) {
741 moduleRecord->RemoveOneFormRecord(event.formName_, event.formDimension_, event.formId_);
742 database_.RemoveFormData(userId_, event.bundleName_, event.moduleName_, event.formName_, event.formDimension_,
743 event.formId_, event.uid_);
744 }
745 PrintInMemFormStats(debugUserService_, true);
746 }
747
GetOrCreateModuleRecord(const BundleActiveEvent & event)748 std::shared_ptr<BundleActiveModuleRecord> BundleActiveUserService::GetOrCreateModuleRecord(
749 const BundleActiveEvent& event)
750 {
751 BUNDLE_ACTIVE_LOGD("GetOrCreateModuleRecord called");
752 std::string combinedInfo = event.bundleName_ + " " + std::to_string(event.uid_) + " " + event.moduleName_;
753 auto it = moduleRecords_.find(combinedInfo);
754 if (it == moduleRecords_.end()) {
755 auto moduleRecordInserted = std::make_shared<BundleActiveModuleRecord>();
756 moduleRecordInserted->bundleName_ = event.bundleName_;
757 moduleRecordInserted->moduleName_ = event.moduleName_;
758 moduleRecordInserted->userId_ = userId_;
759 moduleRecordInserted->uid_ = event.uid_;
760 moduleRecords_[combinedInfo] = moduleRecordInserted;
761 }
762 return moduleRecords_[combinedInfo];
763 }
764
DeleteExcessiveEventTableData(int32_t deleteDays)765 void BundleActiveUserService::DeleteExcessiveEventTableData(int32_t deleteDays)
766 {
767 if (deleteDays < 0) {
768 return;
769 }
770 database_.DeleteExcessiveEventTableData(deleteDays);
771 }
772 } // namespace DeviceUsageStats
773 } // namespace OHOS