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