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