1 /*
2  * Copyright (c) 2022 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_interface_impl.h"
17 
18 #include <thread>
19 #include <memory>
20 #include <hdf_base.h>
21 #include "thermal_hdf_config.h"
22 #include "thermal_hdf_timer.h"
23 #include "thermal_simulation_node.h"
24 #include "thermal_device_mitigation.h"
25 #include "thermal_zone_manager.h"
26 #include "thermal_log.h"
27 #ifdef HAS_THERMAL_CONFIG_POLICY_PART
28 #include "config_policy_utils.h"
29 #endif
30 
31 namespace OHOS {
32 namespace HDI {
33 namespace Thermal {
34 namespace V1_1 {
35 namespace {
36 
37 const std::string HDI_XML_PATH = "etc/thermal_config/thermal_hdi_config.xml";
38 const std::string VENDOR_HDI_XML_PATH = "/vendor/etc/thermal_config/thermal_hdi_config.xml";
39 bool g_isHdiStart = false;
40 }
41 static sptr<IThermalCallback> theramalCb_ = nullptr;
42 static std::shared_ptr<HdfThermalCallbackInfo> callbackInfo_ = nullptr;
43 static std::shared_ptr<ThermalHdfTimer> hdfTimer_ = nullptr;
44 static std::shared_ptr<ThermalSimulationNode> simulation_ = nullptr;
45 static std::shared_ptr<ThermalDeviceMitigation> mitigation_ = nullptr;
46 static std::shared_ptr<ThermalZoneManager> thermalZoneMgr_ = nullptr;
47 
ThermalInterfaceImplGetInstance(void)48 extern "C" IThermalInterface *ThermalInterfaceImplGetInstance(void)
49 {
50     return new (std::nothrow) ThermalInterfaceImpl();
51 }
52 
ThermalInterfaceImpl()53 ThermalInterfaceImpl::ThermalInterfaceImpl()
54 {
55     Init();
56 }
57 
Init()58 int32_t ThermalInterfaceImpl::Init()
59 {
60     bool parseConfigSuc = false;
61     int32_t ret;
62 #ifdef HAS_THERMAL_CONFIG_POLICY_PART
63     char buf[MAX_PATH_LEN];
64     char* path = GetOneCfgFile(HDI_XML_PATH.c_str(), buf, MAX_PATH_LEN);
65     if (path != nullptr && *path != '\0') {
66         ret = ThermalHdfConfig::GetInstance().ThermalHDIConfigInit(path);
67         if (ret != HDF_SUCCESS) {
68             THERMAL_HILOGE(COMP_HDI, "parse err pliocy thermal hdi XML");
69             return HDF_FAILURE;
70         }
71         parseConfigSuc = true;
72     }
73 #endif
74 
75     if (!parseConfigSuc) {
76         ret = ThermalHdfConfig::GetInstance().ThermalHDIConfigInit(VENDOR_HDI_XML_PATH);
77         if (ret != HDF_SUCCESS) {
78             THERMAL_HILOGE(COMP_HDI, "failed to init XML, ret: %{public}d", ret);
79             return HDF_FAILURE;
80         }
81     }
82 
83     if (simulation_ == nullptr) {
84         simulation_ = std::make_shared<ThermalSimulationNode>();
85     }
86 
87     if (thermalZoneMgr_ == nullptr) {
88         thermalZoneMgr_ = std::make_shared<ThermalZoneManager>();
89     }
90 
91     if (mitigation_ == nullptr) {
92         mitigation_ = std::make_shared<ThermalDeviceMitigation>();
93     }
94 
95     if (hdfTimer_ == nullptr) {
96         hdfTimer_ = std::make_shared<ThermalHdfTimer>(simulation_, thermalZoneMgr_);
97         hdfTimer_->SetSimluationFlag();
98     }
99 
100     ret = simulation_->NodeInit();
101     if (ret != HDF_SUCCESS) {
102         return HDF_FAILURE;
103     }
104 
105     thermalZoneMgr_->Init();
106     thermalZoneMgr_->CalculateMaxCd();
107     ret = thermalZoneMgr_->UpdateThermalZoneData();
108     if (ret != HDF_SUCCESS) {
109         return ret;
110     }
111 
112     thermalZoneMgr_->DumpPollingInfo();
113     mitigation_->SetFlag(static_cast<bool>(hdfTimer_->GetSimluationFlag()));
114     return HDF_SUCCESS;
115 }
116 
SetCpuFreq(int32_t freq)117 int32_t ThermalInterfaceImpl::SetCpuFreq(int32_t freq)
118 {
119     if (freq <= 0) {
120         THERMAL_HILOGE(COMP_HDI, "invalid freq %{public}d", freq);
121         return HDF_FAILURE;
122     }
123     if (mitigation_ != nullptr) {
124         int32_t ret = mitigation_->CpuRequest(freq);
125         if (ret != HDF_SUCCESS) {
126             THERMAL_HILOGE(COMP_HDI, "failed to set freq %{public}d", ret);
127             return ret;
128         }
129     }
130     return HDF_SUCCESS;
131 }
132 
SetGpuFreq(int32_t freq)133 int32_t ThermalInterfaceImpl::SetGpuFreq(int32_t freq)
134 {
135     if (freq <= 0) {
136         THERMAL_HILOGE(COMP_HDI, "invalid freq %{public}d", freq);
137         return HDF_FAILURE;
138     }
139     if (mitigation_ != nullptr) {
140         int32_t ret = mitigation_->GpuRequest(freq);
141         if (ret != HDF_SUCCESS) {
142             THERMAL_HILOGE(COMP_HDI, "failed to set freq %{public}d", ret);
143             return ret;
144         }
145     }
146     return HDF_SUCCESS;
147 }
148 
SetBatteryCurrent(int32_t current)149 int32_t ThermalInterfaceImpl::SetBatteryCurrent(int32_t current)
150 {
151     if (current <= 0) {
152         THERMAL_HILOGE(COMP_HDI, "invalid current %{public}d", current);
153         return HDF_FAILURE;
154     }
155     if (mitigation_ != nullptr) {
156         int32_t ret = mitigation_->ChargerRequest(current);
157         if (ret != HDF_SUCCESS) {
158             THERMAL_HILOGE(COMP_HDI, "failed to set current %{public}d", ret);
159             return ret;
160         }
161     }
162     return HDF_SUCCESS;
163 }
164 
GetThermalZoneInfo(HdfThermalCallbackInfo & event)165 int32_t ThermalInterfaceImpl::GetThermalZoneInfo(HdfThermalCallbackInfo& event)
166 {
167     if (thermalZoneMgr_ != nullptr) {
168         thermalZoneMgr_->UpdateThermalZoneData();
169         event.info = thermalZoneMgr_->GetCallbackInfo().info;
170     }
171     return HDF_SUCCESS;
172 }
173 
IsolateCpu(int32_t num)174 int32_t ThermalInterfaceImpl::IsolateCpu(int32_t num)
175 {
176     if (num <= 0) {
177         THERMAL_HILOGE(COMP_HDI, "invalid num %{public}d", num);
178         return HDF_FAILURE;
179     }
180     if (mitigation_ != nullptr) {
181         int32_t ret = mitigation_->IsolateCpu(num);
182         if (ret != HDF_SUCCESS) {
183             THERMAL_HILOGE(COMP_HDI, "failed to set isolate cpu num %{public}d", ret);
184             return ret;
185         }
186     }
187     return HDF_SUCCESS;
188 }
189 
Register(const sptr<IThermalCallback> & callbackObj)190 int32_t ThermalInterfaceImpl::Register(const sptr<IThermalCallback>& callbackObj)
191 {
192     if (thermalZoneMgr_ == nullptr || callbackObj == nullptr) {
193         return HDF_FAILURE;
194     }
195 
196     thermalZoneMgr_->SetThermalEventCb(callbackObj);
197     StartTimerThread();
198 
199     return g_isHdiStart ? HDF_SUCCESS : HDF_FAILURE;
200 }
201 
Unregister()202 int32_t ThermalInterfaceImpl::Unregister()
203 {
204     if (thermalZoneMgr_ == nullptr || thermalZoneMgr_->GetThermalEventCb() == nullptr) {
205         return HDF_FAILURE;
206     }
207 
208     thermalZoneMgr_->DelThermalEventCb();
209     return HDF_SUCCESS;
210 }
211 
RegisterFanCallback(const sptr<IFanCallback> & callbackObj)212 int32_t ThermalInterfaceImpl::RegisterFanCallback(const sptr<IFanCallback>& callbackObj)
213 {
214     if (thermalZoneMgr_ == nullptr || callbackObj == nullptr) {
215         return HDF_FAILURE;
216     }
217 
218     thermalZoneMgr_->SetFanEventCb(callbackObj);
219     StartTimerThread();
220 
221     return g_isHdiStart ? HDF_SUCCESS : HDF_FAILURE;
222 }
223 
UnregisterFanCallback()224 int32_t ThermalInterfaceImpl::UnregisterFanCallback()
225 {
226     if (thermalZoneMgr_ == nullptr || thermalZoneMgr_->GetFanEventCb() == nullptr) {
227         return HDF_FAILURE;
228     }
229 
230     thermalZoneMgr_->DelFanEventCb();
231     return HDF_SUCCESS;
232 }
233 
StartTimerThread()234 void ThermalInterfaceImpl::StartTimerThread()
235 {
236     if (hdfTimer_ == nullptr) {
237         return;
238     }
239 
240     std::lock_guard<std::mutex> lock(mutex_);
241     if (!g_isHdiStart) {
242         int32_t ret = hdfTimer_->Init();
243         if (ret != HDF_SUCCESS) {
244             return;
245         }
246         g_isHdiStart = true;
247     }
248 
249     return;
250 }
251 
252 } // V1_1
253 } // Thermal
254 } // HDI
255 } // OHOS
256