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