• 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 "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