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