* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "thermal_interface_impl.h"
#include <thread>
#include <memory>
#include <hdf_base.h>
#include "thermal_hdf_config.h"
#include "thermal_hdf_timer.h"
#include "thermal_simulation_node.h"
#include "thermal_device_mitigation.h"
#include "thermal_zone_manager.h"
#include "thermal_log.h"
#ifdef HAS_THERMAL_CONFIG_POLICY_PART
#include "config_policy_utils.h"
#endif
namespace OHOS {
namespace HDI {
namespace Thermal {
namespace V1_1 {
namespace {
const std::string HDI_XML_PATH = "etc/thermal_config/thermal_hdi_config.xml";
const std::string VENDOR_HDI_XML_PATH = "/vendor/etc/thermal_config/thermal_hdi_config.xml";
bool g_isHdiStart = false;
}
static sptr<IThermalCallback> theramalCb_ = nullptr;
static std::shared_ptr<HdfThermalCallbackInfo> callbackInfo_ = nullptr;
static std::shared_ptr<ThermalHdfTimer> hdfTimer_ = nullptr;
static std::shared_ptr<ThermalSimulationNode> simulation_ = nullptr;
static std::shared_ptr<ThermalDeviceMitigation> mitigation_ = nullptr;
static std::shared_ptr<ThermalZoneManager> thermalZoneMgr_ = nullptr;
extern "C" IThermalInterface *ThermalInterfaceImplGetInstance(void)
{
return new (std::nothrow) ThermalInterfaceImpl();
}
ThermalInterfaceImpl::ThermalInterfaceImpl()
{
Init();
}
int32_t ThermalInterfaceImpl::Init()
{
bool parseConfigSuc = false;
int32_t ret;
#ifdef HAS_THERMAL_CONFIG_POLICY_PART
char buf[MAX_PATH_LEN];
char* path = GetOneCfgFile(HDI_XML_PATH.c_str(), buf, MAX_PATH_LEN);
if (path != nullptr && *path != '\0') {
ret = ThermalHdfConfig::GetInstance().ThermalHDIConfigInit(path);
if (ret != HDF_SUCCESS) {
THERMAL_HILOGE(COMP_HDI, "parse err pliocy thermal hdi XML");
return HDF_FAILURE;
}
parseConfigSuc = true;
}
#endif
if (!parseConfigSuc) {
ret = ThermalHdfConfig::GetInstance().ThermalHDIConfigInit(VENDOR_HDI_XML_PATH);
if (ret != HDF_SUCCESS) {
THERMAL_HILOGE(COMP_HDI, "failed to init XML, ret: %{public}d", ret);
return HDF_FAILURE;
}
}
if (simulation_ == nullptr) {
simulation_ = std::make_shared<ThermalSimulationNode>();
}
if (thermalZoneMgr_ == nullptr) {
thermalZoneMgr_ = std::make_shared<ThermalZoneManager>();
}
if (mitigation_ == nullptr) {
mitigation_ = std::make_shared<ThermalDeviceMitigation>();
}
if (hdfTimer_ == nullptr) {
hdfTimer_ = std::make_shared<ThermalHdfTimer>(simulation_, thermalZoneMgr_);
hdfTimer_->SetSimluationFlag();
}
ret = simulation_->NodeInit();
if (ret != HDF_SUCCESS) {
return HDF_FAILURE;
}
thermalZoneMgr_->Init();
thermalZoneMgr_->CalculateMaxCd();
ret = thermalZoneMgr_->UpdateThermalZoneData();
if (ret != HDF_SUCCESS) {
return ret;
}
thermalZoneMgr_->DumpPollingInfo();
mitigation_->SetFlag(static_cast<bool>(hdfTimer_->GetSimluationFlag()));
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::SetCpuFreq(int32_t freq)
{
if (freq <= 0) {
THERMAL_HILOGE(COMP_HDI, "invalid freq %{public}d", freq);
return HDF_FAILURE;
}
if (mitigation_ != nullptr) {
int32_t ret = mitigation_->CpuRequest(freq);
if (ret != HDF_SUCCESS) {
THERMAL_HILOGE(COMP_HDI, "failed to set freq %{public}d", ret);
return ret;
}
}
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::SetGpuFreq(int32_t freq)
{
if (freq <= 0) {
THERMAL_HILOGE(COMP_HDI, "invalid freq %{public}d", freq);
return HDF_FAILURE;
}
if (mitigation_ != nullptr) {
int32_t ret = mitigation_->GpuRequest(freq);
if (ret != HDF_SUCCESS) {
THERMAL_HILOGE(COMP_HDI, "failed to set freq %{public}d", ret);
return ret;
}
}
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::SetBatteryCurrent(int32_t current)
{
if (current <= 0) {
THERMAL_HILOGE(COMP_HDI, "invalid current %{public}d", current);
return HDF_FAILURE;
}
if (mitigation_ != nullptr) {
int32_t ret = mitigation_->ChargerRequest(current);
if (ret != HDF_SUCCESS) {
THERMAL_HILOGE(COMP_HDI, "failed to set current %{public}d", ret);
return ret;
}
}
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::GetThermalZoneInfo(HdfThermalCallbackInfo& event)
{
if (thermalZoneMgr_ != nullptr) {
thermalZoneMgr_->UpdateThermalZoneData();
event.info = thermalZoneMgr_->GetCallbackInfo().info;
}
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::IsolateCpu(int32_t num)
{
if (num <= 0) {
THERMAL_HILOGE(COMP_HDI, "invalid num %{public}d", num);
return HDF_FAILURE;
}
if (mitigation_ != nullptr) {
int32_t ret = mitigation_->IsolateCpu(num);
if (ret != HDF_SUCCESS) {
THERMAL_HILOGE(COMP_HDI, "failed to set isolate cpu num %{public}d", ret);
return ret;
}
}
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::Register(const sptr<IThermalCallback>& callbackObj)
{
if (thermalZoneMgr_ == nullptr || callbackObj == nullptr) {
return HDF_FAILURE;
}
thermalZoneMgr_->SetThermalEventCb(callbackObj);
StartTimerThread();
return g_isHdiStart ? HDF_SUCCESS : HDF_FAILURE;
}
int32_t ThermalInterfaceImpl::Unregister()
{
if (thermalZoneMgr_ == nullptr || thermalZoneMgr_->GetThermalEventCb() == nullptr) {
return HDF_FAILURE;
}
thermalZoneMgr_->DelThermalEventCb();
return HDF_SUCCESS;
}
int32_t ThermalInterfaceImpl::RegisterFanCallback(const sptr<IFanCallback>& callbackObj)
{
if (thermalZoneMgr_ == nullptr || callbackObj == nullptr) {
return HDF_FAILURE;
}
thermalZoneMgr_->SetFanEventCb(callbackObj);
StartTimerThread();
return g_isHdiStart ? HDF_SUCCESS : HDF_FAILURE;
}
int32_t ThermalInterfaceImpl::UnregisterFanCallback()
{
if (thermalZoneMgr_ == nullptr || thermalZoneMgr_->GetFanEventCb() == nullptr) {
return HDF_FAILURE;
}
thermalZoneMgr_->DelFanEventCb();
return HDF_SUCCESS;
}
void ThermalInterfaceImpl::StartTimerThread()
{
if (hdfTimer_ == nullptr) {
return;
}
std::lock_guard<std::mutex> lock(mutex_);
if (!g_isHdiStart) {
int32_t ret = hdfTimer_->Init();
if (ret != HDF_SUCCESS) {
return;
}
g_isHdiStart = true;
}
return;
}
}
}
}
}