1020a203aSopenharmony_ci/*
2020a203aSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4020a203aSopenharmony_ci * you may not use this file except in compliance with the License.
5020a203aSopenharmony_ci * You may obtain a copy of the License at
6020a203aSopenharmony_ci *
7020a203aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8020a203aSopenharmony_ci *
9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12020a203aSopenharmony_ci * See the License for the specific language governing permissions and
13020a203aSopenharmony_ci * limitations under the License.
14020a203aSopenharmony_ci */
15020a203aSopenharmony_ci
16020a203aSopenharmony_ci#include "resolver.h"
17020a203aSopenharmony_ci
18020a203aSopenharmony_ci#include <sys/time.h>
19020a203aSopenharmony_ci
20020a203aSopenharmony_ci#include "file_util.h"
21020a203aSopenharmony_ci#include "hiview_event_report.h"
22020a203aSopenharmony_ci#include "hiview_logger.h"
23020a203aSopenharmony_ci#include "string_util.h"
24020a203aSopenharmony_ci#include "sys_event.h"
25020a203aSopenharmony_ci#include "sys_event_dao.h"
26020a203aSopenharmony_ci
27020a203aSopenharmony_cinamespace OHOS {
28020a203aSopenharmony_cinamespace HiviewDFX {
29020a203aSopenharmony_cinamespace {
30020a203aSopenharmony_ci    static const int DEFAULT_TIME_WINDOW = 30;
31020a203aSopenharmony_ci    static const int MINUTES_IN_HOUR = 60;
32020a203aSopenharmony_ci    static const int MIN_MATCH_NUM = 2;
33020a203aSopenharmony_ci    static const int DEFAULT_HOURS = 10;
34020a203aSopenharmony_ci}
35020a203aSopenharmony_ci
36020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "FreezeDetector");
37020a203aSopenharmony_cibool FreezeResolver::Init()
38020a203aSopenharmony_ci{
39020a203aSopenharmony_ci    if (freezeCommon_ == nullptr) {
40020a203aSopenharmony_ci        return false;
41020a203aSopenharmony_ci    }
42020a203aSopenharmony_ci    freezeRuleCluster_ = freezeCommon_->GetFreezeRuleCluster();
43020a203aSopenharmony_ci    if (freezeRuleCluster_ == nullptr) {
44020a203aSopenharmony_ci        return false;
45020a203aSopenharmony_ci    }
46020a203aSopenharmony_ci    dBHelper_ = std::make_unique<DBHelper>(freezeCommon_);
47020a203aSopenharmony_ci    vendor_ = std::make_unique<Vendor>(freezeCommon_);
48020a203aSopenharmony_ci    return vendor_->Init();
49020a203aSopenharmony_ci}
50020a203aSopenharmony_ci
51020a203aSopenharmony_cibool FreezeResolver::ResolveEvent(const WatchPoint& watchPoint,
52020a203aSopenharmony_ci    std::vector<WatchPoint>& list, std::vector<FreezeResult>& result) const
53020a203aSopenharmony_ci{
54020a203aSopenharmony_ci    if (freezeRuleCluster_ == nullptr || !freezeRuleCluster_->GetResult(watchPoint, result)) {
55020a203aSopenharmony_ci        return false;
56020a203aSopenharmony_ci    }
57020a203aSopenharmony_ci    unsigned long long timestamp = watchPoint.GetTimestamp();
58020a203aSopenharmony_ci    long pid = watchPoint.GetPid();
59020a203aSopenharmony_ci    std::string packageName = watchPoint.GetPackageName().empty() ?
60020a203aSopenharmony_ci        watchPoint.GetProcessName() : watchPoint.GetPackageName();
61020a203aSopenharmony_ci    DBHelper::WatchParams params = {pid, packageName};
62020a203aSopenharmony_ci    for (auto& i : result) {
63020a203aSopenharmony_ci        long window = i.GetWindow();
64020a203aSopenharmony_ci        if (window == 0) {
65020a203aSopenharmony_ci            list.push_back(watchPoint);
66020a203aSopenharmony_ci        } else if (dBHelper_ != nullptr) {
67020a203aSopenharmony_ci            unsigned long long timeInterval = static_cast<unsigned long long>(std::abs(window) * MILLISECOND);
68020a203aSopenharmony_ci            unsigned long long start = window > 0 ? timestamp : timestamp - timeInterval;
69020a203aSopenharmony_ci            unsigned long long end = window > 0 ? timestamp + timeInterval : timestamp;
70020a203aSopenharmony_ci            dBHelper_->SelectEventFromDB(start, end, list, params, i);
71020a203aSopenharmony_ci        }
72020a203aSopenharmony_ci    }
73020a203aSopenharmony_ci
74020a203aSopenharmony_ci    HIVIEW_LOGI("list size %{public}zu", list.size());
75020a203aSopenharmony_ci    return true;
76020a203aSopenharmony_ci}
77020a203aSopenharmony_ci
78020a203aSopenharmony_cibool FreezeResolver::JudgmentResult(const WatchPoint& watchPoint,
79020a203aSopenharmony_ci    const std::vector<WatchPoint>& list, const std::vector<FreezeResult>& result) const
80020a203aSopenharmony_ci{
81020a203aSopenharmony_ci    if (watchPoint.GetDomain() == "ACE" && watchPoint.GetStringId() == "UI_BLOCK_6S") {
82020a203aSopenharmony_ci        if (list.size() == result.size()) {
83020a203aSopenharmony_ci            HIVIEW_LOGI("ACE UI_BLOCK has UI_BLOCK_3S UI_BLOCK_6S UI_BLOCK_RECOVERED as UI_JANK");
84020a203aSopenharmony_ci            return false;
85020a203aSopenharmony_ci        }
86020a203aSopenharmony_ci
87020a203aSopenharmony_ci        if (list.size() != (result.size() - 1)) {
88020a203aSopenharmony_ci            return false;
89020a203aSopenharmony_ci        }
90020a203aSopenharmony_ci
91020a203aSopenharmony_ci        for (auto& i : list) {
92020a203aSopenharmony_ci            if (i.GetStringId() == "UI_BLOCK_RECOVERED") {
93020a203aSopenharmony_ci                return false;
94020a203aSopenharmony_ci            }
95020a203aSopenharmony_ci        }
96020a203aSopenharmony_ci        return true;
97020a203aSopenharmony_ci    }
98020a203aSopenharmony_ci
99020a203aSopenharmony_ci    if (std::any_of(result.begin(), result.end(), [&list](auto& res) {
100020a203aSopenharmony_ci        return res.GetAction() == "or";
101020a203aSopenharmony_ci    })) {
102020a203aSopenharmony_ci        return list.size() >= MIN_MATCH_NUM;
103020a203aSopenharmony_ci    }
104020a203aSopenharmony_ci
105020a203aSopenharmony_ci    if (list.size() == result.size()) {
106020a203aSopenharmony_ci        return true;
107020a203aSopenharmony_ci    }
108020a203aSopenharmony_ci    return false;
109020a203aSopenharmony_ci}
110020a203aSopenharmony_ci
111020a203aSopenharmony_ciint FreezeResolver::ProcessEvent(const WatchPoint &watchPoint) const
112020a203aSopenharmony_ci{
113020a203aSopenharmony_ci    HIVIEW_LOGI("process event [%{public}s, %{public}s]",
114020a203aSopenharmony_ci        watchPoint.GetDomain().c_str(), watchPoint.GetStringId().c_str());
115020a203aSopenharmony_ci    if (vendor_ == nullptr) {
116020a203aSopenharmony_ci        return -1;
117020a203aSopenharmony_ci    }
118020a203aSopenharmony_ci    std::vector<WatchPoint> list;
119020a203aSopenharmony_ci    std::vector<FreezeResult> result;
120020a203aSopenharmony_ci    if (!ResolveEvent(watchPoint, list, result)) {
121020a203aSopenharmony_ci        HIVIEW_LOGW("no rule for event [%{public}s, %{public}s]",
122020a203aSopenharmony_ci            watchPoint.GetDomain().c_str(), watchPoint.GetStringId().c_str());
123020a203aSopenharmony_ci        return -1;
124020a203aSopenharmony_ci    }
125020a203aSopenharmony_ci
126020a203aSopenharmony_ci    if (!JudgmentResult(watchPoint, list, result)) {
127020a203aSopenharmony_ci        HIVIEW_LOGW("no match event for event [%{public}s, %{public}s]",
128020a203aSopenharmony_ci            watchPoint.GetDomain().c_str(), watchPoint.GetStringId().c_str());
129020a203aSopenharmony_ci        return -1;
130020a203aSopenharmony_ci    }
131020a203aSopenharmony_ci
132020a203aSopenharmony_ci    vendor_->MergeEventLog(watchPoint, list, result);
133020a203aSopenharmony_ci    return 0;
134020a203aSopenharmony_ci}
135020a203aSopenharmony_ci
136020a203aSopenharmony_cistd::string FreezeResolver::GetTimeZone() const
137020a203aSopenharmony_ci{
138020a203aSopenharmony_ci    std::string timeZone = "";
139020a203aSopenharmony_ci    struct timeval tv;
140020a203aSopenharmony_ci    struct timezone tz;
141020a203aSopenharmony_ci    if (gettimeofday(&tv, &tz) != 0) {
142020a203aSopenharmony_ci        HIVIEW_LOGE("failed to gettimeofday");
143020a203aSopenharmony_ci        return timeZone;
144020a203aSopenharmony_ci    }
145020a203aSopenharmony_ci
146020a203aSopenharmony_ci    int hour = (-tz.tz_minuteswest) / MINUTES_IN_HOUR;
147020a203aSopenharmony_ci    timeZone = (hour >= 0) ? "+" : "-";
148020a203aSopenharmony_ci
149020a203aSopenharmony_ci    int absHour = std::abs(hour);
150020a203aSopenharmony_ci    if (absHour < DEFAULT_HOURS) {
151020a203aSopenharmony_ci        timeZone.append("0");
152020a203aSopenharmony_ci    }
153020a203aSopenharmony_ci    timeZone.append(std::to_string(absHour));
154020a203aSopenharmony_ci
155020a203aSopenharmony_ci    int minute = (-tz.tz_minuteswest) % MINUTES_IN_HOUR;
156020a203aSopenharmony_ci    int absMinute = std::abs(minute);
157020a203aSopenharmony_ci    if (absMinute < DEFAULT_HOURS) {
158020a203aSopenharmony_ci        timeZone.append("0");
159020a203aSopenharmony_ci    }
160020a203aSopenharmony_ci    timeZone.append(std::to_string(absMinute));
161020a203aSopenharmony_ci
162020a203aSopenharmony_ci    return timeZone;
163020a203aSopenharmony_ci}
164020a203aSopenharmony_ci} // namespace HiviewDFX
165020a203aSopenharmony_ci} // namespace OHOS
166