1/*
2 * Copyright (c) 2022-2023 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 "thermal_hdf_timer.h"
17
18#include <cerrno>
19#include <fcntl.h>
20#include <linux/netlink.h>
21#include <sys/epoll.h>
22#include <sys/socket.h>
23#include <sys/timerfd.h>
24#include <thread>
25#include <unistd.h>
26
27#include "hdf_base.h"
28#include "string_ex.h"
29#include "thermal_dfx.h"
30#include "thermal_log.h"
31#include "thermal_hdf_utils.h"
32
33namespace OHOS {
34namespace HDI {
35namespace Thermal {
36namespace V1_1 {
37namespace {
38const std::string THERMAL_SIMULATION_TAG = "sim_tz";
39}
40ThermalHdfTimer::ThermalHdfTimer(const std::shared_ptr<ThermalSimulationNode> &node,
41    const std::shared_ptr<ThermalZoneManager> &thermalZoneMgr)
42{
43    node_ = node;
44    thermalZoneMgr_ = thermalZoneMgr;
45    reportTime_ = 0;
46}
47
48ThermalHdfTimer::~ThermalHdfTimer()
49{
50    isRunning_ = false;
51    if (callbackThread_ != nullptr && callbackThread_->joinable()) {
52        callbackThread_->join();
53    }
54    ThermalDfx::DestroyInstance();
55}
56
57void ThermalHdfTimer::SetSimluationFlag()
58{
59    auto baseConfigList = ThermalHdfConfig::GetInstance().GetBaseConfig()->GetBaseItem();
60    if (baseConfigList.empty()) {
61        THERMAL_HILOGE(COMP_HDI, "baseConfigList is empty");
62        return;
63    }
64    auto baseIter = std::find(baseConfigList.begin(), baseConfigList.end(), THERMAL_SIMULATION_TAG);
65    if (baseIter != baseConfigList.end()) {
66        StrToInt(TrimStr(baseIter->value), isSim_);
67        THERMAL_HILOGI(COMP_HDI, "isSim value:%{public}d", isSim_);
68    } else {
69        THERMAL_HILOGI(COMP_HDI, "not found");
70    }
71}
72
73void ThermalHdfTimer::SetSimFlag(int32_t flag)
74{
75    isSim_ = flag;
76}
77
78int32_t ThermalHdfTimer::GetSimluationFlag()
79{
80    return isSim_;
81}
82
83void ThermalHdfTimer::TimerProviderCallback()
84{
85    reportTime_ = reportTime_ + 1;
86    ReportThermalData();
87    ResetCount();
88    return;
89}
90
91void ThermalHdfTimer::LoopingThreadEntry()
92{
93    int32_t dfxInterval = static_cast<int32_t>(ThermalDfx::GetInstance().GetInterval());
94    int32_t gcd = ThermalHdfUtils::GetMaxCommonDivisor(thermalZoneMgr_->GetMaxCd(), dfxInterval);
95    if (dfxInterval == 0 || gcd == 0) {
96        THERMAL_HILOGE(COMP_HDI, "LoopingThreadEntry error");
97        return;
98    }
99    int32_t loopingTimes = 0;
100    while (isRunning_) {
101        std::this_thread::sleep_for(std::chrono::milliseconds(gcd));
102        loopingTimes++;
103        int32_t dfxTask = loopingTimes % (dfxInterval / gcd);
104        int32_t reportTask = loopingTimes % (thermalZoneMgr_->GetMaxCd() / gcd);
105        if (dfxTask == 0) {
106            ThermalDfx::GetInstance().DoWork();
107        }
108        if (reportTask == 0) {
109            TimerProviderCallback();
110        }
111        // both dfxTask and reportTask execute, and reset loopingTimes
112        if ((dfxTask == 0) && (reportTask == 0)) {
113            loopingTimes = 0;
114        }
115    }
116}
117
118void ThermalHdfTimer::Run()
119{
120    callbackThread_ = std::make_unique<std::thread>([this] { this->LoopingThreadEntry(); });
121}
122
123void ThermalHdfTimer::StartThread()
124{
125    Run();
126}
127
128int32_t ThermalHdfTimer::Init()
129{
130    ThermalDfx::GetInstance().Init();
131    StartThread();
132    return HDF_SUCCESS;
133}
134
135void ThermalHdfTimer::ReportThermalData()
136{
137    thermalZoneMgr_->ReportThermalZoneData(reportTime_);
138}
139
140void ThermalHdfTimer::ResetCount()
141{
142    if (reportTime_ == thermalZoneMgr_->GetMaxReportTime()) {
143        THERMAL_HILOGD(COMP_HDI, "reportTime:%{public}d", reportTime_);
144        reportTime_ = 0;
145    }
146}
147} // V1_1
148} // Thermal
149} // HDI
150} // OHOS
151