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