• 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 
RenewStatsInMemory(const int64_t timeStamp)252 void BundleActiveUserService::RenewStatsInMemory(const int64_t timeStamp)
253 {
254     std::set<std::string> continueBundles;
255     std::map<std::string, std::map<std::string, int>> continueAbilities;
256     std::map<std::string, std::map<std::string, int>> continueServices;
257     for (std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator it = currentStats_.begin(); // 更新使用时长
258         it != currentStats_.end(); ++it) {
259         if (*it == nullptr) {
260             continue;
261         }
262         for (auto bundleUsageStatsPair : (*it)->bundleStats_) {
263             if (bundleUsageStatsPair.second == nullptr) {
264                 continue;
265             }
266             BundleActivePackageStats bundleUsageStats(*(bundleUsageStatsPair.second));
267             if (!bundleUsageStats.abilities_.empty()) {
268                 continueAbilities[bundleUsageStats.bundleName_] = bundleUsageStats.abilities_;
269             }
270             if (!bundleUsageStats.longTimeTasks_.empty()) {
271                 continueServices[bundleUsageStats.bundleName_] = bundleUsageStats.longTimeTasks_;
272             }
273             (*it)->Update(bundleUsageStats.bundleName_, "", dailyExpiryDate_.GetMilliseconds() - 1,
274                 BundleActiveEvent::END_OF_THE_DAY, "");
275 
276             continueBundles.insert(bundleUsageStats.bundleName_);
277             NotifyStatsChanged();
278         }
279         (*it)->CommitTime(dailyExpiryDate_.GetMilliseconds() - 1);
280     }
281     RestoreStats(true);
282     database_.RemoveOldData(timeStamp);
283     LoadActiveStats(timeStamp, false, false); // 新建intervalstat或加载当前数据库数据
284     for (std::string continueBundleName : continueBundles) { // 更新所有事件的时间戳到新的begintime
285         int64_t beginTime = currentStats_[BundleActivePeriodStats::PERIOD_DAILY]->beginTime_;
286         for (std::vector<std::shared_ptr<BundleActivePeriodStats>>::iterator itInterval = currentStats_.begin();
287             itInterval != currentStats_.end(); ++itInterval) {
288             if (continueAbilities.find(continueBundleName) != continueAbilities.end()) {
289                 for (std::map<std::string, int>::iterator it = continueAbilities[continueBundleName].begin();
290                     it != continueAbilities[continueBundleName].end(); ++it) {
291                     if (it->second == BundleActiveEvent::ABILITY_BACKGROUND) {
292                         continue;
293                     }
294                     (*itInterval)->Update(continueBundleName, "", beginTime, it->second, it->first);
295                 }
296             }
297             if (continueServices.find(continueBundleName) != continueServices.end()) {
298                 for (std::map<std::string, int>::iterator it = continueServices[continueBundleName].begin();
299                     it != continueServices[continueBundleName].end(); ++it) {
300                     (*itInterval)->Update(continueBundleName, it->first, beginTime, it->second, "");
301                 }
302             }
303         }
304     }
305     RestoreStats(true);
306 }
307 
QueryBundleStatsInfos(std::vector<BundleActivePackageStats> & PackageStats,int32_t intervalType,const int64_t beginTime,const int64_t endTime,const int32_t userId,const std::string & bundleName)308 ErrCode BundleActiveUserService::QueryBundleStatsInfos(std::vector<BundleActivePackageStats>& PackageStats,
309     int32_t intervalType, const int64_t beginTime, const int64_t endTime, const int32_t userId,
310     const std::string& bundleName)
311 {
312     if (intervalType == BundleActivePeriodStats::PERIOD_BEST) {
313         intervalType = database_.GetOptimalIntervalType(beginTime, endTime);
314         if (intervalType < 0) {
315             intervalType = BundleActivePeriodStats::PERIOD_DAILY;
316         }
317     }
318     if (intervalType < 0 || intervalType >= static_cast<int32_t>(currentStats_.size())) {
319         return ERR_USAGE_STATS_INTERVAL_NUMBER;
320     }
321     auto currentStats = currentStats_[intervalType];
322     if (currentStats == nullptr) {
323         BUNDLE_ACTIVE_LOGE("current interval stat is null!");
324         return ERR_MEMORY_OPERATION_FAILED;
325     }
326     if (currentStats->endTime_ == 0) {
327         if (beginTime > currentStats->beginTime_ + periodLength_[intervalType]) {
328             return ERR_QUERY_TIME_OUT_OF_RANGE;
329         } else {
330             PackageStats = database_.QueryDatabaseUsageStats(intervalType, beginTime, endTime, userId);
331             return ERR_OK;
332         }
333     } else if (beginTime >= currentStats->endTime_) {
334         return ERR_QUERY_TIME_OUT_OF_RANGE;
335     }
336     int64_t truncatedEndTime = std::min(currentStats->beginTime_, endTime);
337     PackageStats = database_.QueryDatabaseUsageStats(intervalType, beginTime, truncatedEndTime, userId);
338     BUNDLE_ACTIVE_LOGI("Query package data in db PackageStats size is %{public}zu", PackageStats.size());
339     PrintInMemPackageStats(intervalType, debugUserService_);
340     // if we need a in-memory stats, combine current stats with PackageStats from database.
341     if (endTime > currentStats->beginTime_) {
342         BUNDLE_ACTIVE_LOGI("QueryBundleStatsInfos need in memory stats");
343         for (auto it : currentStats->bundleStats_) {
344             if (bundleName.empty()) {
345                 if ((it.second->totalInFrontTime_ != 0 || it.second->totalContiniousTaskUsedTime_ != 0) &&
346                     it.second->lastTimeUsed_ >= beginTime && it.second->lastTimeUsed_ <= endTime) {
347                     PackageStats.push_back(*(it.second));
348                 }
349             } else {
350                 if ((it.second->totalInFrontTime_ != 0 || it.second->totalContiniousTaskUsedTime_ != 0) &&
351                     it.second->bundleName_ == bundleName && it.second->lastTimeUsed_ >= beginTime &&
352                     it.second->lastTimeUsed_ <= endTime) {
353                     PackageStats.push_back(*(it.second));
354                 }
355             }
356         }
357     }
358     return ERR_OK;
359 }
360 
QueryBundleEvents(std::vector<BundleActiveEvent> & bundleActiveEvent,const int64_t beginTime,const int64_t endTime,const int32_t userId,const std::string & bundleName)361 ErrCode BundleActiveUserService::QueryBundleEvents(std::vector<BundleActiveEvent>& bundleActiveEvent,
362     const int64_t beginTime, const int64_t endTime, const int32_t userId, const std::string& bundleName)
363 {
364     BUNDLE_ACTIVE_LOGI("QueryBundleEvents called");
365     auto currentStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
366     if (currentStats == nullptr) {
367         BUNDLE_ACTIVE_LOGE("current interval stat is null!");
368         return ERR_MEMORY_OPERATION_FAILED;
369     }
370     if (beginTime >= currentStats->endTime_) {
371         return ERR_QUERY_TIME_OUT_OF_RANGE;
372     }
373     BUNDLE_ACTIVE_LOGI("Query event bundle name is %{public}s", bundleName.c_str());
374     bundleActiveEvent = database_.QueryDatabaseEvents(beginTime, endTime, userId, bundleName);
375     PrintInMemEventStats(debugUserService_);
376     if (currentStats->endTime_ == 0) {
377         BUNDLE_ACTIVE_LOGI("QueryBundleEvents result in db is %{public}zu", bundleActiveEvent.size());
378         return ERR_OK;
379     }
380     // if we need a in-memory stats, combine current stats with bundleActiveEvent from database.
381     if (endTime > currentStats->beginTime_) {
382         BUNDLE_ACTIVE_LOGI("QueryBundleEvents need in memory stats");
383         int32_t eventBeginIdx = currentStats->events_.FindBestIndex(beginTime);
384         int32_t eventSize = currentStats->events_.Size();
385         for (int32_t i = eventBeginIdx; i < eventSize; i++) {
386             if (currentStats->events_.events_[i].timeStamp_ <= endTime) {
387                 if (bundleName.empty() || currentStats->events_.events_[i].bundleName_ == bundleName) {
388                     bundleActiveEvent.push_back(currentStats->events_.events_[i]);
389                 }
390             }
391         }
392     }
393     BUNDLE_ACTIVE_LOGI("QueryBundleEvents result in db and memory is %{public}zu", bundleActiveEvent.size());
394     return ERR_OK;
395 }
396 
QueryModuleUsageRecords(int32_t maxNum,std::vector<BundleActiveModuleRecord> & results)397 int32_t BundleActiveUserService::QueryModuleUsageRecords(int32_t maxNum, std::vector<BundleActiveModuleRecord>& results)
398 {
399     BUNDLE_ACTIVE_LOGI("QueryModuleUsageRecords called, MAX IS %{public}d", maxNum);
400     for (auto oneModuleRecord = moduleRecords_.begin(); oneModuleRecord != moduleRecords_.end(); oneModuleRecord++) {
401         if (!oneModuleRecord->second) {
402             continue;
403         }
404         results.emplace_back(*(oneModuleRecord->second));
405     }
406     std::sort(results.begin(), results.end(), BundleActiveModuleRecord::cmp);
407     if (static_cast<int32_t>(results.size()) > maxNum) {
408         results.resize(maxNum);
409     }
410     for (auto& result : results) {
411         std::sort(result.formRecords_.begin(), result.formRecords_.end(), BundleActiveFormRecord::cmp);
412     }
413     return 0;
414 }
415 
QueryDeviceEventStats(int64_t beginTime,int64_t endTime,std::vector<BundleActiveEventStats> & eventStats,int32_t userId)416 int32_t BundleActiveUserService::QueryDeviceEventStats(int64_t beginTime, int64_t endTime,
417     std::vector<BundleActiveEventStats>& eventStats, int32_t userId)
418 {
419     BUNDLE_ACTIVE_LOGI("QueryDeviceEventStats called");
420     auto currentStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
421     if (currentStats == nullptr) {
422         BUNDLE_ACTIVE_LOGE("current interval stat is null!");
423         return ERR_MEMORY_OPERATION_FAILED;
424     }
425     if (beginTime >= currentStats->endTime_) {
426         return ERR_TIME_OPERATION_FAILED;
427     }
428     std::map<std::string, BundleActiveEventStats> systemEventStats;
429     database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_LOCK, beginTime, endTime, systemEventStats, userId);
430     database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_UNLOCK, beginTime, endTime, systemEventStats, userId);
431     database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_SLEEP, beginTime, endTime, systemEventStats, userId);
432     database_.QueryDeviceEventStats(BundleActiveEvent::SYSTEM_WAKEUP, beginTime, endTime, systemEventStats, userId);
433     BUNDLE_ACTIVE_LOGI("Query eventStats data in db result size is %{public}zu", systemEventStats.size());
434     PrintInMemEventStats(debugUserService_);
435     // if we need a in-memory stats, combine current stats with result from database.
436     if (currentStats->endTime_ != 0 && endTime > currentStats->beginTime_) {
437         BUNDLE_ACTIVE_LOGI("QueryDeviceEventStats need in memory stats");
438         GetCachedSystemEvents(currentStats, beginTime, endTime, systemEventStats);
439     }
440     std::map<std::string, BundleActiveEventStats>::iterator iter;
441     for (iter = systemEventStats.begin(); iter != systemEventStats.end(); ++iter) {
442         eventStats.push_back(iter->second);
443     }
444     return ERR_OK;
445 }
446 
GetCachedSystemEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & systemEventStats)447 void BundleActiveUserService::GetCachedSystemEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,
448     int64_t beginTime, int64_t endTime, std::map<std::string, BundleActiveEventStats>& systemEventStats)
449 {
450     int32_t eventBeginIdx = currentStats->events_.FindBestIndex(beginTime);
451     int32_t eventSize = currentStats->events_.Size();
452     BundleActiveEventStats singleEventStats;
453     std::map<std::string, BundleActiveEventStats>::iterator iter;
454     for (int32_t i = eventBeginIdx; i < eventSize; i++) {
455         if ((currentStats->events_.events_[i].timeStamp_ <= endTime)
456             && ((currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_LOCK)
457             || (currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_UNLOCK)
458             || (currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_SLEEP)
459             || (currentStats->events_.events_[i].eventId_== BundleActiveEvent::SYSTEM_WAKEUP))) {
460             singleEventStats.name_ = currentStats->events_.events_[i].bundleName_;
461             iter = systemEventStats.find(singleEventStats.name_);
462             if (iter != systemEventStats.end()) {
463                 iter->second.count_++;
464             } else {
465                 singleEventStats.eventId_ = currentStats->events_.events_[i].eventId_;
466                 singleEventStats.count_ = 1;
467                 systemEventStats.insert(std::pair<std::string, BundleActiveEventStats>(
468                     singleEventStats.name_, singleEventStats));
469             }
470         }
471     }
472 }
473 
QueryNotificationEventStats(int64_t beginTime,int64_t endTime,std::vector<BundleActiveEventStats> & eventStats,int32_t userId)474 int32_t BundleActiveUserService::QueryNotificationEventStats(int64_t beginTime, int64_t endTime,
475     std::vector<BundleActiveEventStats>& eventStats, int32_t userId)
476 {
477     BUNDLE_ACTIVE_LOGI("QueryNotificationEventStats called");
478     auto currentStats = currentStats_[BundleActivePeriodStats::PERIOD_DAILY];
479     if (currentStats == nullptr) {
480         BUNDLE_ACTIVE_LOGE("current interval stat is null!");
481         return ERR_MEMORY_OPERATION_FAILED;
482     }
483     if (beginTime >= currentStats->endTime_) {
484         return ERR_TIME_OPERATION_FAILED;
485     }
486     std::map<std::string, BundleActiveEventStats> notificationEventStats;
487     database_.QueryNotificationEventStats(BundleActiveEvent::NOTIFICATION_SEEN,
488         beginTime, endTime, notificationEventStats, userId);
489     BUNDLE_ACTIVE_LOGI("Query eventStats data in db result size is %{public}zu", notificationEventStats.size());
490     PrintInMemEventStats(debugUserService_);
491     // if we need a in-memory stats, combine current stats with result from database.
492     if (currentStats->endTime_ != 0 && endTime > currentStats->beginTime_) {
493         BUNDLE_ACTIVE_LOGI("QueryNotificationEventStats need in memory stats");
494         GetCachedNotificationEvents(currentStats, beginTime, endTime, notificationEventStats);
495     }
496     std::map<std::string, BundleActiveEventStats>::iterator iter;
497     for (iter = notificationEventStats.begin(); iter != notificationEventStats.end(); ++iter) {
498         eventStats.push_back(iter->second);
499     }
500     return ERR_OK;
501 }
502 
GetCachedNotificationEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,int64_t beginTime,int64_t endTime,std::map<std::string,BundleActiveEventStats> & notificationEventStats)503 void BundleActiveUserService::GetCachedNotificationEvents(std::shared_ptr<BundleActivePeriodStats> currentStats,
504     int64_t beginTime, int64_t endTime, std::map<std::string, BundleActiveEventStats>& notificationEventStats)
505 {
506     int32_t eventBeginIdx = currentStats->events_.FindBestIndex(beginTime);
507     int32_t eventSize = currentStats->events_.Size();
508     std::map<std::string, BundleActiveEventStats>::iterator iter;
509     BundleActiveEventStats singleEventStats;
510     for (int32_t i = eventBeginIdx; i < eventSize; i++) {
511         if ((currentStats->events_.events_[i].timeStamp_ <= endTime)
512             && (currentStats->events_.events_[i].eventId_== BundleActiveEvent::NOTIFICATION_SEEN)) {
513             singleEventStats.name_ = currentStats->events_.events_[i].bundleName_;
514             iter = notificationEventStats.find(singleEventStats.name_);
515             if (iter != notificationEventStats.end()) {
516                 iter->second.count_++;
517             } else {
518                 singleEventStats.eventId_ = BundleActiveEvent::NOTIFICATION_SEEN;
519                 singleEventStats.count_ = 1;
520                 notificationEventStats.insert(std::pair<std::string, BundleActiveEventStats>(
521                     singleEventStats.name_, singleEventStats));
522             }
523         }
524     }
525 }
526 
PrintInMemPackageStats(const int32_t idx,const bool debug)527 void BundleActiveUserService::PrintInMemPackageStats(const int32_t idx, const bool debug)
528 {
529     if (!debug) {
530         return;
531     }
532     BUNDLE_ACTIVE_LOGI("PrintInMemPackageStats called");
533     for (auto it : currentStats_[idx]->bundleStats_) {
534         BUNDLE_ACTIVE_LOGI("In mem, bundle name is %{public}s", it.first.c_str());
535         int64_t lastTimeUsed = it.second->lastTimeUsed_;
536         int64_t totalUsedTime = it.second->totalInFrontTime_;
537         int64_t lastTimeContinuousTaskUsed = it.second->lastContiniousTaskUsed_;
538         int64_t totalTimeContinuousTaskUsed = it.second->totalContiniousTaskUsedTime_;
539         BUNDLE_ACTIVE_LOGI("bundle stat is, totaltime is %{public}lld, lastTimeUsed is %{public}lld"
540             "total continuous task is %{public}lld, lastTimeContinuousTaskUsed is %{public}lld",
541             (long long)totalUsedTime, (long long)lastTimeUsed,
542             (long long)totalTimeContinuousTaskUsed, (long long)lastTimeContinuousTaskUsed);
543     }
544 }
545 
PrintInMemEventStats(const bool debug)546 void BundleActiveUserService::PrintInMemEventStats(const bool debug)
547 {
548     if (!debug) {
549         return;
550     }
551     BUNDLE_ACTIVE_LOGI("PrintInMemEventStats called");
552     int32_t idx = 0;
553     int32_t size = static_cast<int32_t>(currentStats_[idx]->events_.events_.size());
554     for (int32_t i = 0; i < size; i++) {
555         std::string abilityId = currentStats_[idx]->events_.events_[i].abilityId_;
556         std::string abilityname = currentStats_[idx]->events_.events_[i].abilityName_;
557         std::string bundlename = currentStats_[idx]->events_.events_[i].bundleName_;
558         int32_t eventid = currentStats_[idx]->events_.events_[i].eventId_;
559         int64_t timestamp = currentStats_[idx]->events_.events_[i].timeStamp_;
560         BUNDLE_ACTIVE_LOGI("In mem, event stat is, abilityid is %{public}s, abilityname is %{public}s, "
561             "bundlename is %{public}s, eventid is %{public}d, timestamp is %{public}lld",
562             abilityId.c_str(), abilityname.c_str(), bundlename.c_str(), eventid, (long long)timestamp);
563     }
564 }
565 
PrintInMemFormStats(const bool debug,const bool printform)566 void BundleActiveUserService::PrintInMemFormStats(const bool debug, const bool printform)
567 {
568     if (!debug) {
569         return;
570     }
571     for (const auto& oneModule : moduleRecords_) {
572         if (oneModule.second) {
573         BUNDLE_ACTIVE_LOGI("bundle name is %{public}s, module name is %{public}s, "
574             "lastusedtime is %{public}lld, launchcount is %{public}d", oneModule.second->bundleName_.c_str(),
575             oneModule.second->moduleName_.c_str(),
576             (long long)oneModule.second->lastModuleUsedTime_, oneModule.second->launchedCount_);
577         BUNDLE_ACTIVE_LOGI("combined info is %{public}s", oneModule.first.c_str());
578             if (printform) {
579                 for (const auto& oneForm : oneModule.second->formRecords_) {
580                     BUNDLE_ACTIVE_LOGI("form name is %{public}s, form dimension is %{public}d, "
581                         "form id is %{public}lld, "
582                         "lasttouchtime is %{public}lld, touchcount is %{public}d", oneForm.formName_.c_str(),
583                         oneForm.formDimension_, (long long)oneForm.formId_,
584                         (long long)oneForm.formLastUsedTime_, oneForm.count_);
585                 }
586             }
587         }
588     }
589 }
590 
ReportModuleEvent(const BundleActiveEvent & event)591 void BundleActiveUserService::ReportModuleEvent(const BundleActiveEvent& event)
592 {
593     BUNDLE_ACTIVE_LOGI("ReportModuleEvent called");
594     if (event.eventId_ != BundleActiveEvent::ABILITY_FOREGROUND) {
595         return;
596     }
597     auto moduleRecord = GetOrCreateModuleRecord(event);
598     moduleRecord->UpdateModuleRecord(event.timeStamp_);
599     NotifyStatsChanged();
600     PrintInMemFormStats(debugUserService_, false);
601 }
602 
ReportFormEvent(const BundleActiveEvent & event)603 void BundleActiveUserService::ReportFormEvent(const BundleActiveEvent& event)
604 {
605     BUNDLE_ACTIVE_LOGI("ReportFormEvent called");
606     auto moduleRecord = GetOrCreateModuleRecord(event);
607     if (event.eventId_ == BundleActiveEvent::FORM_IS_CLICKED && moduleRecord) {
608         moduleRecord->AddOrUpdateOneFormRecord(event.formName_, event.formDimension_, event.formId_, event.timeStamp_);
609         NotifyStatsChanged();
610     } else if (event.eventId_ == BundleActiveEvent::FORM_IS_REMOVED && moduleRecord) {
611         moduleRecord->RemoveOneFormRecord(event.formName_, event.formDimension_, event.formId_);
612         database_.RemoveFormData(userId_, event.bundleName_, event.moduleName_, event.formName_, event.formDimension_,
613             event.formId_);
614     }
615     PrintInMemFormStats(debugUserService_, true);
616 }
617 
GetOrCreateModuleRecord(const BundleActiveEvent & event)618 std::shared_ptr<BundleActiveModuleRecord> BundleActiveUserService::GetOrCreateModuleRecord(
619     const BundleActiveEvent& event)
620 {
621     BUNDLE_ACTIVE_LOGI("GetOrCreateModuleRecord called");
622     std::string combinedInfo = event.bundleName_ + " " + event.moduleName_;
623     auto it = moduleRecords_.find(combinedInfo);
624     if (it == moduleRecords_.end()) {
625         auto moduleRecordInserted = std::make_shared<BundleActiveModuleRecord>();
626         moduleRecordInserted->bundleName_ = event.bundleName_;
627         moduleRecordInserted->moduleName_ = event.moduleName_;
628         moduleRecordInserted->userId_ = userId_;
629         moduleRecords_[combinedInfo] = moduleRecordInserted;
630     }
631     return moduleRecords_[combinedInfo];
632 }
633 }  // namespace DeviceUsageStats
634 }  // namespace OHOS