1 /*
2 * Copyright (c) 2022-2025 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 #include "app_usage_event_factory.h"
16
17 #include <algorithm>
18 #include <cinttypes>
19 #include <vector>
20
21 #include "app_usage_event.h"
22 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
23 #include "bundle_active_client.h"
24 #endif
25 #include "bundle_mgr_client.h"
26 #include "hiview_logger.h"
27 #include "os_account_manager.h"
28 #include "time_util.h"
29 #include "usage_event_common.h"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33 DEFINE_LOG_TAG("HiView-AppUsageEventFactory");
34 namespace {
35 constexpr int32_t DEFAULT_USER_ID = 100;
36 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
37 constexpr int32_t INTERVAL_TYPE = 1;
38 constexpr int64_t MILLISEC_TO_SEC = 1000;
39 constexpr char DATE_FORMAT[] = "%Y-%m-%d";
40 #endif
41 }
42 using namespace AppUsageEventSpace;
43 using namespace OHOS::AccountSA;
44 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
45 using namespace OHOS::DeviceUsageStats;
46 #endif
47
Create()48 std::unique_ptr<LoggerEvent> AppUsageEventFactory::Create()
49 {
50 return std::make_unique<AppUsageEvent>(EVENT_NAME, HiSysEvent::STATISTIC);
51 }
52
Create(std::vector<std::unique_ptr<LoggerEvent>> & events)53 void AppUsageEventFactory::Create(std::vector<std::unique_ptr<LoggerEvent>>& events)
54 {
55 // get user ids
56 std::vector<int32_t> userIds;
57 GetAllCreatedOsAccountIds(userIds);
58 if (userIds.empty()) {
59 HIVIEW_LOGE("the accounts obtained are empty");
60 return;
61 }
62
63 // get app usage info
64 std::vector<AppUsageInfo> appUsageInfos;
65 for (auto userId : userIds) {
66 GetAppUsageInfosByUserId(appUsageInfos, userId);
67 }
68
69 // sort and get top
70 std::sort(appUsageInfos.begin(), appUsageInfos.end(),
71 [](const AppUsageInfo &infoA, const AppUsageInfo &infoB) {
72 return infoA.usage_ > infoB.usage_;
73 }
74 );
75 if (appUsageInfos.size() > MAX_APP_USAGE_SIZE) {
76 HIVIEW_LOGI("AppUsageInfo size=%{public}zu, resize=%{public}zu", appUsageInfos.size(), MAX_APP_USAGE_SIZE);
77 appUsageInfos.resize(MAX_APP_USAGE_SIZE);
78 }
79
80 // create events
81 for (auto info : appUsageInfos) {
82 std::unique_ptr<LoggerEvent> event = Create();
83 event->Update(KEY_OF_PACKAGE, info.package_);
84 event->Update(KEY_OF_VERSION, info.version_);
85 event->Update(KEY_OF_USAGE, info.usage_);
86 event->Update(KEY_OF_DATE, info.date_);
87 event->Update(KEY_OF_START_NUM, info.startNum_);
88 events.push_back(std::move(event));
89 }
90 }
91
GetAllCreatedOsAccountIds(std::vector<int32_t> & ids)92 void AppUsageEventFactory::GetAllCreatedOsAccountIds(std::vector<int32_t>& ids)
93 {
94 if (auto res = OsAccountManager::QueryActiveOsAccountIds(ids); res != ERR_OK) {
95 HIVIEW_LOGE("failed to get userId, err=%{public}d", res);
96 ids.push_back(DEFAULT_USER_ID);
97 }
98 }
99
GetAppUsageInfosByUserId(std::vector<AppUsageInfo> & appUsageInfos,int32_t userId)100 void AppUsageEventFactory::GetAppUsageInfosByUserId(std::vector<AppUsageInfo>& appUsageInfos, int32_t userId)
101 {
102 #ifdef DEVICE_USAGE_STATISTICS_ENABLE
103 HIVIEW_LOGI("get app usage info by userId=%{public}d", userId);
104 int64_t today0Time = TimeUtil::Get0ClockStampMs();
105 int64_t gapTime = static_cast<int64_t>(TimeUtil::MILLISECS_PER_DAY);
106 int64_t startTime = today0Time > gapTime ? (today0Time - gapTime) : 0;
107 int64_t endTime = today0Time > MILLISEC_TO_SEC ? (today0Time - MILLISEC_TO_SEC) : 0;
108 std::vector<BundleActivePackageStats> pkgStats;
109 int32_t errCode = BundleActiveClient::GetInstance().QueryBundleStatsInfoByInterval(pkgStats, INTERVAL_TYPE,
110 startTime, endTime, userId);
111 if (errCode != ERR_OK) {
112 HIVIEW_LOGE("failed to get package stats, errCode=%{public}d", errCode);
113 return;
114 }
115
116 HIVIEW_LOGI("startTime=%{public}" PRId64 ", endTime=%{public}" PRId64 ", size=%{public}zu",
117 startTime, endTime, pkgStats.size());
118 std::string dateStr = TimeUtil::TimestampFormatToDate(startTime / MILLISEC_TO_SEC, DATE_FORMAT);
119 for (auto stat : pkgStats) {
120 std::string package = stat.bundleName_;
121 auto it = std::find_if(appUsageInfos.begin(), appUsageInfos.end(), [package](auto info) {
122 return info.package_ == package;
123 });
124 uint64_t usage = stat.totalInFrontTime_ > 0 ? static_cast<uint64_t>(stat.totalInFrontTime_) : 0;
125 uint32_t startNum = stat.startCount_ > 0 ? static_cast<uint32_t>(stat.startCount_) : 0;
126 if (it != appUsageInfos.end()) {
127 it->usage_ += usage;
128 it->startNum_ += startNum;
129 } else {
130 std::string version = GetAppVersion(stat.bundleName_);
131 appUsageInfos.push_back(AppUsageInfo(stat.bundleName_, version, usage, dateStr, startNum));
132 }
133 }
134 #endif
135 }
136
GetAppVersion(const std::string & bundleName)137 std::string AppUsageEventFactory::GetAppVersion(const std::string& bundleName)
138 {
139 AppExecFwk::BundleInfo info;
140 AppExecFwk::BundleMgrClient client;
141 if (!client.GetBundleInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, info,
142 AppExecFwk::Constants::ALL_USERID)) {
143 HIVIEW_LOGE("Failed to get the version of the bundle");
144 return "";
145 }
146 return info.versionName;
147 }
148 } // namespace HiviewDFX
149 } // namespace OHOS
150