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