/* * Copyright (c) 2021-2023 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_service.h" #include "file_ex.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" #include "securec.h" #include "system_ability_definition.h" #include #include #include #include #include #include "config_policy_utils.h" #include "constants.h" #include "ffrt_utils.h" #include "permission.h" #include "sysparam.h" #include "thermal_common.h" #include "thermal_mgr_dumper.h" #include "xcollie/watchdog.h" namespace OHOS { namespace PowerMgr { sptr ThermalService::instance_ = nullptr; std::mutex ThermalService::singletonMutex_; namespace { const std::string THERMAL_SERVICE_CONFIG_PATH = "etc/thermal_config/thermal_service_config.xml"; const std::string VENDOR_THERMAL_SERVICE_CONFIG_PATH = "/vendor/etc/thermal_config/thermal_service_config.xml"; const std::string SYSTEM_THERMAL_SERVICE_CONFIG_PATH = "/system/etc/thermal_config/thermal_service_config.xml"; constexpr const char* THMERMAL_SERVICE_NAME = "ThermalService"; constexpr const char* HDI_SERVICE_NAME = "thermal_interface_service"; FFRTQueue g_queue("thermal_service"); constexpr uint32_t RETRY_TIME = 1000; auto g_service = ThermalService::GetInstance(); const bool G_REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(g_service.GetRefPtr()); SysParam::BootCompletedCallback g_bootCompletedCallback; } // namespace std::atomic_bool ThermalService::isBootCompleted_ = false; std::string ThermalService::scene_; ThermalService::ThermalService() : SystemAbility(POWER_MANAGER_THERMAL_SERVICE_ID, true) {} ThermalService::~ThermalService() {} sptr ThermalService::GetInstance() { if (instance_ == nullptr) { std::lock_guard lock(singletonMutex_); if (instance_ == nullptr) { instance_ = new ThermalService(); } } return instance_; } void ThermalService::OnStart() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (ready_) { THERMAL_HILOGE(COMP_SVC, "OnStart is ready, nothing to do"); return; } if (!(Init())) { THERMAL_HILOGE(COMP_SVC, "OnStart call init fail"); return; } AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); if (!Publish(ThermalService::GetInstance())) { THERMAL_HILOGE(COMP_SVC, "OnStart register to system ability manager failed."); return; } RegisterBootCompletedCallback(); ready_ = true; THERMAL_HILOGD(COMP_SVC, "OnStart and add system ability success"); } void ThermalService::RegisterBootCompletedCallback() { g_bootCompletedCallback = []() { isBootCompleted_ = true; }; SysParam::RegisterBootCompletedCallback(g_bootCompletedCallback); } void ThermalService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) { THERMAL_HILOGI(COMP_SVC, "systemAbilityId=%{public}d, deviceId=%{private}s", systemAbilityId, deviceId.c_str()); if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { InitStateMachine(); } } bool ThermalService::Init() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!CreateConfigModule()) { return false; } if (!InitModules()) { return false; } RegisterHdiStatusListener(); THERMAL_HILOGD(COMP_SVC, "Init success"); return true; } bool ThermalService::CreateConfigModule() { if (!baseInfo_) { baseInfo_ = std::make_shared(); if (baseInfo_ == nullptr) { THERMAL_HILOGE(COMP_SVC, "failed to create base info"); return false; } } if (!state_) { state_ = std::make_shared(); if (state_ == nullptr) { THERMAL_HILOGE(COMP_SVC, "failed to create state machine"); return false; } } if (!actionMgr_) { actionMgr_ = std::make_shared(); if (actionMgr_ == nullptr) { THERMAL_HILOGE(COMP_SVC, "failed to create action manager"); return false; } } if (!policy_) { policy_ = std::make_shared(); if (policy_ == nullptr) { THERMAL_HILOGE(COMP_SVC, "failed to create thermal policy"); return false; } } if (!fanFaultDetect_) { fanFaultDetect_ = std::make_shared(); if (fanFaultDetect_ == nullptr) { THERMAL_HILOGE(COMP_SVC, "failed to create fan fault detect"); return false; } } return true; } bool ThermalService::InitConfigFile() { if (serviceConfigParsed) { THERMAL_HILOGI(COMP_SVC, "system config file has parsed."); return true; } char buf[MAX_PATH_LEN]; char* path = GetOneCfgFile(THERMAL_SERVICE_CONFIG_PATH.c_str(), buf, MAX_PATH_LEN); if (path != nullptr && *path != '\0') { if (configParser_.ThermalSrvConfigInit(path)) { THERMAL_HILOGD(COMP_SVC, "match pliocy config file"); return true; } THERMAL_HILOGE(COMP_SVC, "pliocy config file config init err"); return false; } if (configParser_.ThermalSrvConfigInit(VENDOR_THERMAL_SERVICE_CONFIG_PATH)) { THERMAL_HILOGD(COMP_SVC, "thermal service config init suc:VENDOR_CONFIG"); return true; } if (configParser_.ThermalSrvConfigInit(SYSTEM_THERMAL_SERVICE_CONFIG_PATH)) { THERMAL_HILOGD(COMP_SVC, "thermal service config init suc:SYSTEM_CONFIG"); return true; } return false; } bool ThermalService::InitConfigModule() { THERMAL_HILOGD(COMP_SVC, "InitVendor Enter"); if (!CreateConfigModule()) { THERMAL_HILOGD(COMP_SVC, "CreateConfigModule fail"); } if (!configParser_.ThermalSrvConfigInit(SYSTEM_THERMAL_SERVICE_CONFIG_PATH)) { THERMAL_HILOGE(COMP_SVC, "system thermal service config init failed."); return false; } serviceConfigParsed = true; THERMAL_HILOGE(COMP_SVC, "system thermal service config init suc."); return true; } bool ThermalService::InitModules() { if (!InitConfigFile()) { return false; } if (popup_ == nullptr) { popup_ = std::make_shared(POPUP_ACTION_NAME); } if (!InitThermalObserver()) { THERMAL_HILOGE(COMP_SVC, "thermal observer start fail"); return false; } if (!InitActionManager()) { THERMAL_HILOGE(COMP_SVC, "action manager init fail"); return false; } if (!InitThermalPolicy()) { THERMAL_HILOGE(COMP_SVC, "thermal policy start fail"); return false; } if (!InitThermalSubscriber()) { THERMAL_HILOGE(COMP_SVC, "thermal subscriber init fail"); return false; } return true; } bool ThermalService::InitThermalObserver() { if (!InitBaseInfo()) { return false; } THERMAL_HILOGD(COMP_SVC, "Enter"); if (observer_ == nullptr) { observer_ = std::make_shared(); if (!(observer_->Init())) { THERMAL_HILOGE(COMP_SVC, "InitThermalObserver: thermal observer start fail"); return false; } } if (info_ == nullptr) { info_ = std::make_shared(); } THERMAL_HILOGI(COMP_SVC, "InitThermalObserver: Init Success"); return true; } bool ThermalService::InitBaseInfo() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!baseInfo_->Init()) { THERMAL_HILOGE(COMP_SVC, "InitBaseInfo: base info init failed"); return false; } return true; } bool ThermalService::InitStateMachine() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!state_->Init()) { THERMAL_HILOGE(COMP_SVC, "InitStateMachine: state machine init failed"); return false; } return true; } bool ThermalService::InitActionManager() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!actionMgr_->Init()) { THERMAL_HILOGE(COMP_SVC, "InitActionManager: action manager init failed"); return false; } return true; } bool ThermalService::InitThermalPolicy() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!policy_->Init()) { THERMAL_HILOGE(COMP_SVC, "InitThermalPolicy: policy init failed"); return false; } return true; } bool ThermalService::InitThermalSubscriber() { if (serviceSubscriber_ == nullptr) { serviceSubscriber_ = std::make_shared(); if (!(serviceSubscriber_->Init())) { THERMAL_HILOGE(COMP_SVC, "InitThermalSubscriber: thermal subscriber init failed"); return false; } } return true; } void ThermalService::OnStop() { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!ready_) { return; } ready_ = false; isBootCompleted_ = false; RemoveSystemAbilityListener(COMMON_EVENT_SERVICE_ID); if (thermalInterface_) { thermalInterface_->Unregister(); thermalInterface_->UnregisterFanCallback(); thermalInterface_ = nullptr; } if (hdiServiceMgr_) { hdiServiceMgr_->UnregisterServiceStatusListener(hdiServStatListener_); hdiServiceMgr_ = nullptr; } } bool ThermalService::SubscribeThermalTempCallback( const std::vector& typeList, const sptr& callback) { if (!Permission::IsSystem()) { return false; } auto uid = IPCSkeleton::GetCallingUid(); THERMAL_HILOGI(COMP_SVC, "%{public}s is called by uid=%{public}d", __func__, uid); observer_->SubscribeThermalTempCallback(typeList, callback); return true; } bool ThermalService::UnSubscribeThermalTempCallback(const sptr& callback) { if (!Permission::IsSystem()) { return false; } auto uid = IPCSkeleton::GetCallingUid(); THERMAL_HILOGI(COMP_SVC, "%{public}s is called by uid=%{public}d", __func__, uid); observer_->UnSubscribeThermalTempCallback(callback); return true; } bool ThermalService::GetThermalSrvSensorInfo(const SensorType& type, ThermalSrvSensorInfo& sensorInfo) { THERMAL_HILOGD(COMP_SVC, "Enter"); if (!(observer_->GetThermalSrvSensorInfo(type, sensorInfo))) { THERMAL_HILOGW(COMP_SVC, "failed to get sensor temp, type enum: %{public}u", static_cast(type)); return false; } return true; } bool ThermalService::SubscribeThermalLevelCallback(const sptr& callback) { auto uid = IPCSkeleton::GetCallingUid(); THERMAL_HILOGI(COMP_SVC, "%{public}s is called by uid=%{public}d", __func__, uid); actionMgr_->SubscribeThermalLevelCallback(callback); return true; } bool ThermalService::UnSubscribeThermalLevelCallback(const sptr& callback) { auto uid = IPCSkeleton::GetCallingUid(); THERMAL_HILOGI(COMP_SVC, "%{public}s is called by uid=%{public}d", __func__, uid); actionMgr_->UnSubscribeThermalLevelCallback(callback); return true; } bool ThermalService::SubscribeThermalActionCallback( const std::vector& actionList, const std::string& desc, const sptr& callback) { if (!Permission::IsSystem()) { return false; } auto pid = IPCSkeleton::GetCallingPid(); auto uid = IPCSkeleton::GetCallingUid(); THERMAL_HILOGI(COMP_SVC, "%{public}s is called by pid=%{public}d, uid=%{public}d", __func__, pid, uid); observer_->SubscribeThermalActionCallback(actionList, desc, callback); return true; } bool ThermalService::UnSubscribeThermalActionCallback(const sptr& callback) { if (!Permission::IsSystem()) { return false; } auto pid = IPCSkeleton::GetCallingPid(); auto uid = IPCSkeleton::GetCallingUid(); THERMAL_HILOGI(COMP_SVC, "%{public}s is called by pid=%{public}d, uid=%{public}d", __func__, pid, uid); observer_->UnSubscribeThermalActionCallback(callback); return true; } bool ThermalService::GetThermalLevel(ThermalLevel& level) { uint32_t levelValue = actionMgr_->GetThermalLevel(); level = static_cast(levelValue); return true; } bool ThermalService::GetThermalInfo() { THERMAL_HILOGD(COMP_SVC, "Enter"); HdfThermalCallbackInfo thermalInfo; bool ret = false; if (thermalInterface_ == nullptr) { thermalInterface_ = IThermalInterface::Get(); if (thermalInterface_ == nullptr) { THERMAL_HILOGD(COMP_SVC, "thermalInterface_ is nullptr"); return ret; } } if (thermalInterface_ != nullptr) { int32_t res = thermalInterface_->GetThermalZoneInfo(thermalInfo); HandleThermalCallbackEvent(thermalInfo); if (!res) { ret = true; } } return ret; } bool ThermalService::SetScene(const std::string& scene) { if (!Permission::IsSystem()) { return false; } scene_ = scene; return true; } bool ThermalService::UpdateThermalState(const std::string& tag, const std::string& val, bool isImmed) { if (!Permission::IsSystem()) { return false; } THERMAL_HILOGI(COMP_SVC, "tag %{public}s, val %{public}s, isImmed %{public}d", tag.c_str(), val.c_str(), isImmed); std::lock_guard lock(mutex_); state_->UpdateState(tag, val); if (isImmed) { policy_->ExecutePolicy(); } return true; } void ThermalService::RegisterHdiStatusListener() { THERMAL_HILOGD(COMP_SVC, "Enter"); hdiServiceMgr_ = IServiceManager::Get(); if (hdiServiceMgr_ == nullptr) { FFRTTask retryTask = [this] { return RegisterHdiStatusListener(); }; FFRTUtils::SubmitDelayTask(retryTask, RETRY_TIME, g_queue); THERMAL_HILOGW(COMP_SVC, "hdi service manager is nullptr, try again after %{public}u ms", RETRY_TIME); return; } hdiServStatListener_ = new HdiServiceStatusListener( HdiServiceStatusListener::StatusCallback([&](const OHOS::HDI::ServiceManager::V1_0::ServiceStatus& status) { THERMAL_RETURN_IF(status.serviceName != HDI_SERVICE_NAME || status.deviceClass != DEVICE_CLASS_DEFAULT) if (status.status == SERVIE_STATUS_START) { FFRTTask task = [this] { RegisterThermalHdiCallback(); RegisterFanHdiCallback(); }; FFRTUtils::SubmitTask(task); THERMAL_HILOGD(COMP_SVC, "thermal interface service start"); } else if (status.status == SERVIE_STATUS_STOP && thermalInterface_) { thermalInterface_->Unregister(); thermalInterface_->UnregisterFanCallback(); thermalInterface_ = nullptr; THERMAL_HILOGW(COMP_SVC, "thermal interface service, unregister interface"); } })); int32_t status = hdiServiceMgr_->RegisterServiceStatusListener(hdiServStatListener_, DEVICE_CLASS_DEFAULT); if (status != ERR_OK) { THERMAL_HILOGW(COMP_SVC, "Register hdi failed, try again after %{public}u ms", RETRY_TIME); FFRTTask retryTask = [this] { return RegisterHdiStatusListener(); }; FFRTUtils::SubmitDelayTask(retryTask, RETRY_TIME, g_queue); } } void ThermalService::RegisterThermalHdiCallback() { THERMAL_HILOGD(COMP_SVC, "register thermal hdi callback"); if (thermalInterface_ == nullptr) { thermalInterface_ = IThermalInterface::Get(); THERMAL_RETURN_IF_WITH_LOG(thermalInterface_ == nullptr, "failed to get thermal hdi interface"); } sptr callback = new ThermalCallback(); ThermalCallback::ThermalEventCallback eventCb = [this](const HdfThermalCallbackInfo& event) -> int32_t { return this->HandleThermalCallbackEvent(event); }; ThermalCallback::RegisterThermalEvent(eventCb); int32_t ret = thermalInterface_->Register(callback); THERMAL_HILOGI(COMP_SVC, "register thermal hdi callback end, ret: %{public}d", ret); } void ThermalService::UnRegisterThermalHdiCallback() { if (thermalInterface_ == nullptr) { FFRTTask retryTask = [this] { return UnRegisterThermalHdiCallback(); }; FFRTUtils::SubmitDelayTask(retryTask, RETRY_TIME, g_queue); THERMAL_HILOGW(COMP_SVC, "thermalInterface_ is nullptr, try again after %{public}u ms", RETRY_TIME); return; } int32_t ret = thermalInterface_->Unregister(); THERMAL_HILOGI(COMP_SVC, "unregister thermal hdi callback end, ret: %{public}d", ret); } int32_t ThermalService::HandleThermalCallbackEvent(const HdfThermalCallbackInfo& event) { #ifndef THERMAL_USER_VERSION if (!isTempReport_) { return ERR_OK; } #endif TypeTempMap typeTempMap; if (!event.info.empty()) { for (auto iter = event.info.begin(); iter != event.info.end(); iter++) { typeTempMap.insert(std::make_pair(iter->type, iter->temp)); } } std::lock_guard lock(mutex_); serviceSubscriber_->OnTemperatureChanged(typeTempMap); return ERR_OK; } bool ThermalService::HandleTempEmulation(const TypeTempMap& typeTempMap) { if (isTempReport_) { return false; } std::lock_guard lock(mutex_); serviceSubscriber_->OnTemperatureChanged(typeTempMap); return true; } void ThermalService::RegisterFanHdiCallback() { if (!fanFaultDetect_->HasFanConfig()) { return; } if (thermalInterface_ == nullptr) { thermalInterface_ = IThermalInterface::Get(); THERMAL_RETURN_IF_WITH_LOG(thermalInterface_ == nullptr, "failed to get thermal hdi interface"); } sptr callback = new FanCallback(); FanCallback::FanEventCallback eventCb = [this](const HdfThermalCallbackInfo& event) -> int32_t { return this->HandleFanCallbackEvent(event); }; FanCallback::RegisterFanEvent(eventCb); int32_t ret = thermalInterface_->RegisterFanCallback(callback); THERMAL_HILOGI(COMP_SVC, "register fan hdi callback end, ret: %{public}d", ret); return; } int32_t ThermalService::HandleFanCallbackEvent(const HdfThermalCallbackInfo& event) { FanSensorInfo report; if (!event.info.empty()) { for (auto iter = event.info.begin(); iter != event.info.end(); iter++) { report.insert(std::make_pair(iter->type, iter->temp)); } } fanFaultDetect_->OnFanSensorInfoChanged(report); return ERR_OK; } std::string ThermalService::ShellDump(const std::vector& args, uint32_t argc) { if (!Permission::IsSystem() || !isBootCompleted_) { return ""; } std::lock_guard lock(mutex_); pid_t pid = IPCSkeleton::GetCallingPid(); THERMAL_HILOGI(COMP_SVC, "PID: %{public}d", pid); std::string result; bool ret = ThermalMgrDumper::Dump(args, result); THERMAL_HILOGI(COMP_SVC, "ThermalMgrDumper :%{public}d", ret); return result; } int32_t ThermalService::Dump(int fd, const std::vector& args) { if (!isBootCompleted_) { return ERR_NO_INIT; } if (!Permission::IsSystem()) { return ERR_PERMISSION_DENIED; } std::vector argsInStr; std::transform(args.begin(), args.end(), std::back_inserter(argsInStr), [](const std::u16string& arg) { std::string ret = Str16ToStr8(arg); THERMAL_HILOGI(COMP_SVC, "arg: %{public}s", ret.c_str()); return ret; }); std::string result; ThermalMgrDumper::Dump(argsInStr, result); if (!SaveStringToFd(fd, result)) { THERMAL_HILOGE(COMP_SVC, "ThermalService::Dump failed, save to fd failed."); THERMAL_HILOGE(COMP_SVC, "Dump Info:\n"); THERMAL_HILOGE(COMP_SVC, "%{public}s", result.c_str()); return ERR_OK; } return ERR_OK; } void ThermalService::EnableMock(const std::string& actionName, void* mockObject) { std::lock_guard lock(mutex_); actionMgr_->EnableMock(actionName, mockObject); } void ThermalService::DestroyInstance() { std::lock_guard lock(singletonMutex_); if (instance_) { instance_.clear(); instance_ = nullptr; } } } // namespace PowerMgr } // namespace OHOS