1 /*
2 * Copyright (C) 2022-2024 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 "usage_event_report_service.h"
16
17 #include <algorithm>
18 #include <getopt.h>
19
20 #include "app_usage_event_factory.h"
21 #include "fold_app_usage_event_factory.h"
22 #include "hiview_logger.h"
23 #include "sys_usage_event_factory.h"
24 #include "time_util.h"
25 #include "usage_event_common.h"
26
27 namespace OHOS {
28 namespace HiviewDFX {
29 DEFINE_LOG_TAG("HiView-UsageEventReportService");
30 using namespace SysUsageEventSpace;
31 using namespace SysUsageDbSpace;
32 namespace {
33 constexpr char ARG_SELECTION[] = "p:t:T:sSA";
34 const std::string DEFAULT_WORK_PATH = "/data/log/hiview";
35 const std::string SYS_USAGE_KEYS[] = { KEY_OF_POWER, KEY_OF_RUNNING };
36 }
37
UsageEventReportService()38 UsageEventReportService::UsageEventReportService() : workPath_(DEFAULT_WORK_PATH), lastReportTime_(0),
39 lastSysReportTime_(0)
40 {}
41
InitWorkPath(const char * path)42 void UsageEventReportService::InitWorkPath(const char* path)
43 {
44 if (path == nullptr) {
45 HIVIEW_LOGE("invalid path, path is nullptr");
46 return;
47 }
48 char realPath[PATH_MAX] = { 0x00 };
49 if (strlen(path) >= PATH_MAX || realpath(path, realPath) == nullptr) {
50 HIVIEW_LOGE("invalid path, path does not exist");
51 return;
52 }
53 if (std::string realPathStr = realPath; realPathStr.rfind(DEFAULT_WORK_PATH, 0) != 0) {
54 HIVIEW_LOGE("invalid path, path should be in the hiview dir");
55 return;
56 }
57 workPath_ = realPath;
58 }
59
ReportAppUsage()60 void UsageEventReportService::ReportAppUsage()
61 {
62 HIVIEW_LOGI("start to report app usage event");
63 auto factory = std::make_unique<AppUsageEventFactory>();
64 std::vector<std::unique_ptr<LoggerEvent>> events;
65 factory->Create(events);
66 HIVIEW_LOGI("report app usage event num: %{public}zu", events.size());
67 for (size_t i = 0; i < events.size(); ++i) {
68 events[i]->Report();
69 }
70 }
71
ReportSysUsage()72 void UsageEventReportService::ReportSysUsage()
73 {
74 HIVIEW_LOGI("start to report sys usage event");
75 UsageEventCacher cacher(workPath_);
76 auto cacheUsage = cacher.GetSysUsageEvent();
77 if (cacheUsage == nullptr) {
78 HIVIEW_LOGE("failed to report sys usage event, cache is null");
79 return;
80 }
81 cacheUsage->Report();
82
83 // after reporting, update cache_usage event to the db
84 cacheUsage->Update(KEY_OF_START, cacheUsage->GetValue(KEY_OF_END).GetUint64());
85 for (auto key : SYS_USAGE_KEYS) {
86 cacheUsage->Update(key, DEFAULT_UINT64);
87 }
88 cacher.SaveSysUsageEventToDb(cacheUsage);
89 }
90
UpdateCacheSysUsage(std::shared_ptr<LoggerEvent> & cacheUsage,const UsageEventCacher & cacher)91 void UsageEventReportService::UpdateCacheSysUsage(std::shared_ptr<LoggerEvent>& cacheUsage,
92 const UsageEventCacher& cacher)
93 {
94 std::shared_ptr<LoggerEvent> nowUsage = std::make_unique<SysUsageEventFactory>()->Create();
95 auto lastUsage = cacher.GetSysUsageEvent(LAST_SYS_USAGE_TABLE);
96 for (auto key : SYS_USAGE_KEYS) {
97 uint64_t nowUsageTime = nowUsage->GetValue(key).GetUint64();
98 uint64_t lastUsageTime = lastUsage == nullptr ? 0 : lastUsage->GetValue(key).GetUint64();
99 uint64_t curUsageTime = nowUsageTime > lastUsageTime ? (nowUsageTime - lastUsageTime) : nowUsageTime;
100 cacheUsage->Update(key, curUsageTime + cacheUsage->GetValue(key).GetUint64());
101 }
102 cacheUsage->Update(KEY_OF_END, nowUsage->GetValue(KEY_OF_END).GetUint64());
103 UpdateLastSysUsage(nowUsage, cacher);
104 }
105
UpdateLastSysUsage(std::shared_ptr<LoggerEvent> & nowUsage,const UsageEventCacher & cacher)106 void UsageEventReportService::UpdateLastSysUsage(std::shared_ptr<LoggerEvent>& nowUsage,
107 const UsageEventCacher& cacher)
108 {
109 nowUsage->Update(KEY_OF_START, lastReportTime_); // save the last report time for app_usage
110 cacher.SaveSysUsageEventToDb(nowUsage, LAST_SYS_USAGE_TABLE);
111 }
112
SaveSysUsage()113 void UsageEventReportService::SaveSysUsage()
114 {
115 HIVIEW_LOGI("start to save sys usage event to db");
116 UsageEventCacher cacher(workPath_);
117 auto cacheUsage = cacher.GetSysUsageEvent();
118 if (cacheUsage == nullptr) {
119 // if it is the first save, set the current usage to the cache_usage
120 cacheUsage = std::make_unique<SysUsageEventFactory>()->Create();
121 UpdateLastSysUsage(cacheUsage, cacher);
122 cacheUsage->Update(KEY_OF_START, lastSysReportTime_);
123 } else {
124 // add the current usage to the cache_usage since the last save
125 UpdateCacheSysUsage(cacheUsage, cacher);
126 }
127 cacher.SaveSysUsageEventToDb(cacheUsage);
128 }
129
ProcessArgsRequest(int argc,char * argv[])130 bool UsageEventReportService::ProcessArgsRequest(int argc, char* argv[])
131 {
132 if (argv == nullptr) {
133 return false;
134 }
135 int opt = 0;
136 while ((opt = getopt(argc, argv, ARG_SELECTION)) != -1) {
137 switch (opt) {
138 case 'p':
139 InitWorkPath(optarg);
140 break;
141 case 's':
142 SaveSysUsage();
143 break;
144 case 'A':
145 ReportAppUsage();
146 break;
147 case 'S':
148 ReportSysUsage();
149 break;
150 case 't':
151 lastReportTime_ = strtoull(optarg, nullptr, 0);
152 break;
153 case 'T':
154 lastSysReportTime_ = strtoull(optarg, nullptr, 0);
155 break;
156 default:
157 break;
158 }
159 }
160 return true;
161 }
162 } // namespace HiviewDFX
163 } // namespace OHOS
164