/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * 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.
 */
#define ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL)

#include "thermal-helper.h"

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <utils/Trace.h>

#include <iterator>
#include <set>
#include <sstream>
#include <thread>
#include <vector>

namespace aidl {
namespace android {
namespace hardware {
namespace thermal {
namespace implementation {

constexpr std::string_view kThermalSensorsRoot("/sys/devices/virtual/thermal");
constexpr std::string_view kSensorPrefix("thermal_zone");
constexpr std::string_view kCoolingDevicePrefix("cooling_device");
constexpr std::string_view kThermalNameFile("type");
constexpr std::string_view kSensorPolicyFile("policy");
constexpr std::string_view kSensorTempSuffix("temp");
constexpr std::string_view kSensorTripPointTempZeroFile("trip_point_0_temp");
constexpr std::string_view kSensorTripPointHystZeroFile("trip_point_0_hyst");
constexpr std::string_view kUserSpaceSuffix("user_space");
constexpr std::string_view kCoolingDeviceCurStateSuffix("cur_state");
constexpr std::string_view kCoolingDeviceMaxStateSuffix("max_state");
constexpr std::string_view kCoolingDeviceState2powerSuffix("state2power_table");
constexpr std::string_view kConfigProperty("vendor.thermal.config");
constexpr std::string_view kConfigDefaultFileName("thermal_info_config.json");
constexpr std::string_view kThermalGenlProperty("persist.vendor.enable.thermal.genl");
constexpr std::string_view kThermalDisabledProperty("vendor.disable.thermalhal.control");

namespace {
using ::android::base::StringPrintf;

std::unordered_map<std::string, std::string> parseThermalPathMap(std::string_view prefix) {
    std::unordered_map<std::string, std::string> path_map;
    std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(kThermalSensorsRoot.data()), closedir);
    if (!dir) {
        return path_map;
    }

    // std::filesystem is not available for vendor yet
    // see discussion: aosp/894015
    while (struct dirent *dp = readdir(dir.get())) {
        if (dp->d_type != DT_DIR) {
            continue;
        }

        if (!::android::base::StartsWith(dp->d_name, prefix.data())) {
            continue;
        }

        std::string path = ::android::base::StringPrintf("%s/%s/%s", kThermalSensorsRoot.data(),
                                                         dp->d_name, kThermalNameFile.data());
        std::string name;
        if (!::android::base::ReadFileToString(path, &name)) {
            PLOG(ERROR) << "Failed to read from " << path;
            continue;
        }

        path_map.emplace(
                ::android::base::Trim(name),
                ::android::base::StringPrintf("%s/%s", kThermalSensorsRoot.data(), dp->d_name));
    }

    return path_map;
}

}  // namespace

// If the cdev_ceiling is higher than CDEV max_state, cap the cdev_ceiling to max_state.
void ThermalHelperImpl::maxCoolingRequestCheck(
        std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map) {
    for (auto &binded_cdev_info_pair : *binded_cdev_info_map) {
        const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_info_pair.first);
        for (auto &cdev_ceiling : binded_cdev_info_pair.second.cdev_ceiling) {
            if (cdev_ceiling > cdev_info.max_state) {
                if (cdev_ceiling != std::numeric_limits<int>::max()) {
                    LOG(ERROR) << binded_cdev_info_pair.first << " cdev_ceiling:" << cdev_ceiling
                               << " is higher than max state:" << cdev_info.max_state;
                }
                cdev_ceiling = cdev_info.max_state;
            }
        }
    }
}

/*
 * Populate the sensor_name_to_file_map_ map by walking through the file tree,
 * reading the type file and assigning the temp file path to the map.  If we do
 * not succeed, abort.
 */
ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
    : thermal_watcher_(new ThermalWatcher(std::bind(&ThermalHelperImpl::thermalWatcherCallbackFunc,
                                                    this, std::placeholders::_1))),
      cb_(cb) {
    const std::string config_path =
            "/vendor/etc/" +
            ::android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data());
    bool thermal_throttling_disabled =
            ::android::base::GetBoolProperty(kThermalDisabledProperty.data(), false);
    bool ret = true;
    Json::Value config;
    if (!ParseThermalConfig(config_path, &config)) {
        LOG(ERROR) << "Failed to read JSON config";
        ret = false;
    }

    if (!ParseCoolingDevice(config, &cooling_device_info_map_)) {
        LOG(ERROR) << "Failed to parse cooling device info config";
        ret = false;
    }

    if (!ParseSensorInfo(config, &sensor_info_map_)) {
        LOG(ERROR) << "Failed to parse sensor info config";
        ret = false;
    }

    auto tz_map = parseThermalPathMap(kSensorPrefix.data());
    if (!initializeSensorMap(tz_map)) {
        LOG(ERROR) << "Failed to initialize sensor map";
        ret = false;
    }

    auto cdev_map = parseThermalPathMap(kCoolingDevicePrefix.data());
    if (!initializeCoolingDevices(cdev_map)) {
        LOG(ERROR) << "Failed to initialize cooling device map";
        ret = false;
    }

    if (!power_files_.registerPowerRailsToWatch(config)) {
        LOG(ERROR) << "Failed to register power rails";
        ret = false;
    }

    if (ret) {
        if (!thermal_stats_helper_.initializeStats(config, sensor_info_map_,
                                                   cooling_device_info_map_)) {
            LOG(FATAL) << "Failed to initialize thermal stats";
        }
    }

    for (auto &name_status_pair : sensor_info_map_) {
        sensor_status_map_[name_status_pair.first] = {
                .severity = ThrottlingSeverity::NONE,
                .prev_hot_severity = ThrottlingSeverity::NONE,
                .prev_cold_severity = ThrottlingSeverity::NONE,
                .last_update_time = boot_clock::time_point::min(),
                .thermal_cached = {NAN, boot_clock::time_point::min()},
                .override_status = {nullptr, false, false},
        };

        if (name_status_pair.second.throttling_info != nullptr) {
            if (!thermal_throttling_.registerThermalThrottling(
                        name_status_pair.first, name_status_pair.second.throttling_info,
                        cooling_device_info_map_)) {
                LOG(ERROR) << name_status_pair.first << " failed to register thermal throttling";
                ret = false;
                break;
            }

            // Update cooling device max state for default mode
            maxCoolingRequestCheck(&name_status_pair.second.throttling_info->binded_cdev_info_map);

            // Update cooling device max state for each profile mode
            for (auto &cdev_throttling_profile_pair :
                 name_status_pair.second.throttling_info->profile_map) {
                maxCoolingRequestCheck(&cdev_throttling_profile_pair.second);
            }
        }
        // Check the virtual sensor settings are valid
        if (name_status_pair.second.virtual_sensor_info != nullptr) {
            // Check if sub sensor setting is valid
            for (size_t i = 0;
                 i < name_status_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
                if (!isSubSensorValid(
                            name_status_pair.second.virtual_sensor_info->linked_sensors[i],
                            name_status_pair.second.virtual_sensor_info->linked_sensors_type[i])) {
                    LOG(ERROR) << name_status_pair.first << "'s link sensor "
                               << name_status_pair.second.virtual_sensor_info->linked_sensors[i]
                               << " is invalid";
                    ret = false;
                    break;
                }
            }

            // Check if the trigger sensor is valid
            if (!name_status_pair.second.virtual_sensor_info->trigger_sensors.empty() &&
                name_status_pair.second.is_watch) {
                for (size_t i = 0;
                     i < name_status_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) {
                    if (sensor_info_map_.count(
                                name_status_pair.second.virtual_sensor_info->trigger_sensors[i])) {
                        sensor_info_map_[name_status_pair.second.virtual_sensor_info
                                                 ->trigger_sensors[i]]
                                .is_watch = true;
                    } else {
                        LOG(ERROR)
                                << name_status_pair.first << "'s trigger sensor: "
                                << name_status_pair.second.virtual_sensor_info->trigger_sensors[i]
                                << " is invalid";
                        ret = false;
                        break;
                    }
                }
            }
        }
    }

    if (!power_hal_service_.connect()) {
        LOG(ERROR) << "Fail to connect to Power Hal";
    } else {
        power_hal_service_.updateSupportedPowerHints(sensor_info_map_);
    }

    if (thermal_throttling_disabled) {
        if (ret) {
            clearAllThrottling();
            is_initialized_ = ret;
            return;
        } else {
            sensor_info_map_.clear();
            cooling_device_info_map_.clear();
            return;
        }
    } else if (!ret) {
        LOG(FATAL) << "ThermalHAL could not be initialized properly.";
    }
    is_initialized_ = ret;

    const bool thermal_genl_enabled =
            ::android::base::GetBoolProperty(kThermalGenlProperty.data(), false);

    std::set<std::string> monitored_sensors;
    initializeTrip(tz_map, &monitored_sensors, thermal_genl_enabled);

    if (thermal_genl_enabled) {
        thermal_watcher_->registerFilesToWatchNl(monitored_sensors);
    } else {
        thermal_watcher_->registerFilesToWatch(monitored_sensors);
    }

    // Need start watching after status map initialized
    is_initialized_ = thermal_watcher_->startWatchingDeviceFiles();
    if (!is_initialized_) {
        LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
    }
}

bool getThermalZoneTypeById(int tz_id, std::string *type) {
    std::string tz_type;
    std::string path =
            ::android::base::StringPrintf("%s/%s%d/%s", kThermalSensorsRoot.data(),
                                          kSensorPrefix.data(), tz_id, kThermalNameFile.data());
    LOG(INFO) << "TZ Path: " << path;
    if (!::android::base::ReadFileToString(path, &tz_type)) {
        LOG(ERROR) << "Failed to read sensor: " << tz_type;
        return false;
    }

    // Strip the newline.
    *type = ::android::base::Trim(tz_type);
    LOG(INFO) << "TZ type: " << *type;
    return true;
}

void ThermalHelperImpl::checkUpdateSensorForEmul(std::string_view target_sensor,
                                                 const bool max_throttling) {
    // Force update all the sensors which are related to the target emul sensor
    for (auto &[sensor_name, sensor_info] : sensor_info_map_) {
        if (sensor_info.virtual_sensor_info == nullptr || !sensor_info.is_watch) {
            continue;
        }

        const auto &linked_sensors = sensor_info.virtual_sensor_info->linked_sensors;
        if (std::find(linked_sensors.begin(), linked_sensors.end(), target_sensor) ==
            linked_sensors.end()) {
            continue;
        }

        auto &sensor_status = sensor_status_map_.at(sensor_name.data());
        sensor_status.override_status.max_throttling = max_throttling;
        sensor_status.override_status.pending_update = true;

        checkUpdateSensorForEmul(sensor_name, max_throttling);
    }
}

bool ThermalHelperImpl::emulTemp(std::string_view target_sensor, const float temp,
                                 const bool max_throttling) {
    LOG(INFO) << "Set " << target_sensor.data() << " emul_temp: " << temp
              << " max_throttling: " << max_throttling;

    std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);

    // Check the target sensor is valid
    if (!sensor_status_map_.count(target_sensor.data())) {
        LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
        return false;
    }

    auto &sensor_status = sensor_status_map_.at(target_sensor.data());

    sensor_status.override_status.emul_temp.reset(new EmulTemp{temp, -1});
    sensor_status.override_status.max_throttling = max_throttling;
    sensor_status.override_status.pending_update = true;

    checkUpdateSensorForEmul(target_sensor.data(), max_throttling);

    thermal_watcher_->wake();
    return true;
}

bool ThermalHelperImpl::emulSeverity(std::string_view target_sensor, const int severity,
                                     const bool max_throttling) {
    LOG(INFO) << "Set " << target_sensor.data() << " emul_severity: " << severity
              << " max_throttling: " << max_throttling;

    std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
    // Check the target sensor is valid
    if (!sensor_status_map_.count(target_sensor.data()) ||
        !sensor_info_map_.count(target_sensor.data())) {
        LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
        return false;
    }
    const auto &sensor_info = sensor_info_map_.at(target_sensor.data());

    // Check the emul severity is valid
    if (severity > static_cast<int>(kThrottlingSeverityCount)) {
        LOG(ERROR) << "Invalid emul severity value " << severity;
        return false;
    }

    const auto temp = sensor_info.hot_thresholds[severity] / sensor_info.multiplier;

    auto &sensor_status = sensor_status_map_.at(target_sensor.data());

    sensor_status.override_status.emul_temp.reset(new EmulTemp{temp, severity});
    sensor_status.override_status.max_throttling = max_throttling;
    sensor_status.override_status.pending_update = true;

    checkUpdateSensorForEmul(target_sensor.data(), max_throttling);

    thermal_watcher_->wake();
    return true;
}

bool ThermalHelperImpl::emulClear(std::string_view target_sensor) {
    LOG(INFO) << "Clear " << target_sensor.data() << " emulation settings";

    std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
    if (target_sensor == "all") {
        for (auto &[sensor_name, sensor_status] : sensor_status_map_) {
            sensor_status.override_status = {
                    .emul_temp = nullptr, .max_throttling = false, .pending_update = true};
            checkUpdateSensorForEmul(sensor_name, false);
        }
    } else if (sensor_status_map_.count(target_sensor.data())) {
        auto &sensor_status = sensor_status_map_.at(target_sensor.data());
        sensor_status.override_status = {
                .emul_temp = nullptr, .max_throttling = false, .pending_update = true};
        checkUpdateSensorForEmul(target_sensor.data(), false);
    } else {
        LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
        return false;
    }

    thermal_watcher_->wake();
    return true;
}

bool ThermalHelperImpl::readCoolingDevice(std::string_view cooling_device,
                                          CoolingDevice *out) const {
    // Read the file.  If the file can't be read temp will be empty string.
    std::string data;

    if (!cooling_devices_.readThermalFile(cooling_device, &data)) {
        LOG(ERROR) << "readCoolingDevice: failed to read cooling_device: " << cooling_device;
        return false;
    }

    const CdevInfo &cdev_info = cooling_device_info_map_.at(cooling_device.data());
    const CoolingType &type = cdev_info.type;

    out->type = type;
    out->name = cooling_device.data();
    out->value = std::stoi(data);

    return true;
}

bool ThermalHelperImpl::readTemperature(
        std::string_view sensor_name, Temperature *out,
        std::pair<ThrottlingSeverity, ThrottlingSeverity> *throttling_status,
        const bool force_no_cache) {
    // Return fail if the thermal sensor cannot be read.
    float temp;
    std::map<std::string, float> sensor_log_map;
    auto &sensor_status = sensor_status_map_.at(sensor_name.data());

    if (!readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log_map)) {
        LOG(ERROR) << "Failed to read thermal sensor " << sensor_name.data();
        thermal_stats_helper_.reportThermalAbnormality(
                ThermalSensorAbnormalityDetected::TEMP_READ_FAIL, sensor_name, std::nullopt);
        return false;
    }

    if (std::isnan(temp)) {
        LOG(INFO) << "Sensor " << sensor_name.data() << " temperature is nan.";
        return false;
    }

    const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
    out->type = sensor_info.type;
    out->name = sensor_name.data();
    out->value = temp * sensor_info.multiplier;

    std::pair<ThrottlingSeverity, ThrottlingSeverity> status =
            std::make_pair(ThrottlingSeverity::NONE, ThrottlingSeverity::NONE);
    // Only update status if the thermal sensor is being monitored
    if (sensor_info.is_watch) {
        ThrottlingSeverity prev_hot_severity, prev_cold_severity;
        {
            // reader lock, readTemperature will be called in Binder call and the watcher thread.
            std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
            prev_hot_severity = sensor_status.prev_hot_severity;
            prev_cold_severity = sensor_status.prev_cold_severity;
        }
        status = getSeverityFromThresholds(sensor_info.hot_thresholds, sensor_info.cold_thresholds,
                                           sensor_info.hot_hysteresis, sensor_info.cold_hysteresis,
                                           prev_hot_severity, prev_cold_severity, out->value);
    }

    if (throttling_status) {
        *throttling_status = status;
    }

    if (sensor_status.override_status.emul_temp != nullptr &&
        sensor_status.override_status.emul_temp->severity >= 0) {
        std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
        out->throttlingStatus =
                static_cast<ThrottlingSeverity>(sensor_status.override_status.emul_temp->severity);
    } else {
        out->throttlingStatus =
                static_cast<size_t>(status.first) > static_cast<size_t>(status.second)
                        ? status.first
                        : status.second;
    }
    if (sensor_info.is_watch) {
        std::ostringstream sensor_log;
        for (const auto &sensor_log_pair : sensor_log_map) {
            sensor_log << sensor_log_pair.first << ":" << sensor_log_pair.second << " ";
        }
        // Update sensor temperature time in state
        thermal_stats_helper_.updateSensorTempStatsBySeverity(sensor_name, out->throttlingStatus);
        LOG(INFO) << sensor_name.data() << ":" << out->value << " raw data: " << sensor_log.str();
    }

    return true;
}

bool ThermalHelperImpl::readTemperatureThreshold(std::string_view sensor_name,
                                                 TemperatureThreshold *out) const {
    // Read the file.  If the file can't be read temp will be empty string.
    std::string temp;
    std::string path;

    if (!sensor_info_map_.count(sensor_name.data())) {
        LOG(ERROR) << __func__ << ": sensor not found: " << sensor_name;
        return false;
    }

    const auto &sensor_info = sensor_info_map_.at(sensor_name.data());

    out->type = sensor_info.type;
    out->name = sensor_name.data();
    out->hotThrottlingThresholds =
            std::vector(sensor_info.hot_thresholds.begin(), sensor_info.hot_thresholds.end());
    out->coldThrottlingThresholds =
            std::vector(sensor_info.cold_thresholds.begin(), sensor_info.cold_thresholds.end());
    return true;
}

void ThermalHelperImpl::updateCoolingDevices(const std::vector<std::string> &updated_cdev) {
    int max_state;

    for (const auto &target_cdev : updated_cdev) {
        if (thermal_throttling_.getCdevMaxRequest(target_cdev, &max_state)) {
            if (cooling_devices_.writeCdevFile(target_cdev, std::to_string(max_state))) {
                ATRACE_INT(target_cdev.c_str(), max_state);
                LOG(INFO) << "Successfully update cdev " << target_cdev << " sysfs to "
                          << max_state;
            } else {
                LOG(ERROR) << "Failed to update cdev " << target_cdev << " sysfs to " << max_state;
            }
        }
    }
}

std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelperImpl::getSeverityFromThresholds(
        const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
        const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
        ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
        float value) const {
    ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE;
    ThrottlingSeverity ret_hot_hysteresis = ThrottlingSeverity::NONE;
    ThrottlingSeverity ret_cold = ThrottlingSeverity::NONE;
    ThrottlingSeverity ret_cold_hysteresis = ThrottlingSeverity::NONE;

    // Here we want to control the iteration from high to low, and ::ndk::enum_range doesn't support
    // a reverse iterator yet.
    for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN);
         i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) {
        if (!std::isnan(hot_thresholds[i]) && hot_thresholds[i] <= value &&
            ret_hot == ThrottlingSeverity::NONE) {
            ret_hot = static_cast<ThrottlingSeverity>(i);
        }
        if (!std::isnan(hot_thresholds[i]) && (hot_thresholds[i] - hot_hysteresis[i]) < value &&
            ret_hot_hysteresis == ThrottlingSeverity::NONE) {
            ret_hot_hysteresis = static_cast<ThrottlingSeverity>(i);
        }
        if (!std::isnan(cold_thresholds[i]) && cold_thresholds[i] >= value &&
            ret_cold == ThrottlingSeverity::NONE) {
            ret_cold = static_cast<ThrottlingSeverity>(i);
        }
        if (!std::isnan(cold_thresholds[i]) && (cold_thresholds[i] + cold_hysteresis[i]) > value &&
            ret_cold_hysteresis == ThrottlingSeverity::NONE) {
            ret_cold_hysteresis = static_cast<ThrottlingSeverity>(i);
        }
    }
    if (static_cast<size_t>(ret_hot) < static_cast<size_t>(prev_hot_severity)) {
        ret_hot = ret_hot_hysteresis;
    }
    if (static_cast<size_t>(ret_cold) < static_cast<size_t>(prev_cold_severity)) {
        ret_cold = ret_cold_hysteresis;
    }

    return std::make_pair(ret_hot, ret_cold);
}

bool ThermalHelperImpl::isSubSensorValid(std::string_view sensor_data,
                                         const SensorFusionType sensor_fusion_type) {
    switch (sensor_fusion_type) {
        case SensorFusionType::SENSOR:
            if (!sensor_info_map_.count(sensor_data.data())) {
                LOG(ERROR) << "Cannot find " << sensor_data.data() << " from sensor info map";
                return false;
            }
            break;
        case SensorFusionType::ODPM:
            if (!GetPowerStatusMap().count(sensor_data.data())) {
                LOG(ERROR) << "Cannot find " << sensor_data.data() << " from power status map";
                return false;
            }
            break;
        default:
            break;
    }
    return true;
}

void ThermalHelperImpl::clearAllThrottling(void) {
    // Clear the CDEV request
    for (const auto &cdev_info_pair : cooling_device_info_map_) {
        cooling_devices_.writeCdevFile(cdev_info_pair.first, "0");
    }

    for (auto &sensor_info_pair : sensor_info_map_) {
        sensor_info_pair.second.is_watch = false;
        sensor_info_pair.second.throttling_info.reset();
        sensor_info_pair.second.hot_thresholds.fill(NAN);
        sensor_info_pair.second.cold_thresholds.fill(NAN);
        Temperature temp = {
                .type = sensor_info_pair.second.type,
                .name = sensor_info_pair.first,
                .value = NAN,
                .throttlingStatus = ThrottlingSeverity::NONE,
        };
        // Send callbacks with NONE severity
        if (sensor_info_pair.second.send_cb && cb_) {
            cb_(temp);
        }
        // Disable thermal power hints
        if (sensor_info_pair.second.send_powerhint) {
            for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
                power_hal_service_.setMode(sensor_info_pair.first, severity, false);
            }
        }
    }
}

bool ThermalHelperImpl::initializeSensorMap(
        const std::unordered_map<std::string, std::string> &path_map) {
    for (const auto &sensor_info_pair : sensor_info_map_) {
        std::string_view sensor_name = sensor_info_pair.first;
        if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
            continue;
        }
        if (!path_map.count(sensor_name.data())) {
            LOG(ERROR) << "Could not find " << sensor_name << " in sysfs";
            return false;
        }

        std::string path;
        if (sensor_info_pair.second.temp_path.empty()) {
            path = ::android::base::StringPrintf("%s/%s", path_map.at(sensor_name.data()).c_str(),
                                                 kSensorTempSuffix.data());
        } else {
            path = sensor_info_pair.second.temp_path;
        }

        if (!thermal_sensors_.addThermalFile(sensor_name, path)) {
            LOG(ERROR) << "Could not add " << sensor_name << "to sensors map";
            return false;
        }
    }
    return true;
}

bool ThermalHelperImpl::initializeCoolingDevices(
        const std::unordered_map<std::string, std::string> &path_map) {
    for (auto &cooling_device_info_pair : cooling_device_info_map_) {
        std::string cooling_device_name = cooling_device_info_pair.first;
        if (!path_map.count(cooling_device_name)) {
            LOG(ERROR) << "Could not find " << cooling_device_name << " in sysfs";
            return false;
        }
        // Add cooling device path for thermalHAL to get current state
        std::string_view path = path_map.at(cooling_device_name);
        std::string read_path;
        if (!cooling_device_info_pair.second.read_path.empty()) {
            read_path = cooling_device_info_pair.second.read_path.data();
        } else {
            read_path = ::android::base::StringPrintf("%s/%s", path.data(),
                                                      kCoolingDeviceCurStateSuffix.data());
        }
        if (!cooling_devices_.addThermalFile(cooling_device_name, read_path)) {
            LOG(ERROR) << "Could not add " << cooling_device_name
                       << " read path to cooling device map";
            return false;
        }

        std::string state2power_path = ::android::base::StringPrintf(
                "%s/%s", path.data(), kCoolingDeviceState2powerSuffix.data());
        std::string state2power_str;
        if (::android::base::ReadFileToString(state2power_path, &state2power_str)) {
            LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
                      << " use state2power read from sysfs";
            cooling_device_info_pair.second.state2power.clear();

            std::stringstream power(state2power_str);
            unsigned int power_number;
            int i = 0;
            while (power >> power_number) {
                cooling_device_info_pair.second.state2power.push_back(
                        static_cast<float>(power_number));
                LOG(INFO) << "Cooling device " << cooling_device_info_pair.first << " state:" << i
                          << " power: " << power_number;
                i++;
            }
        }

        // Get max cooling device request state
        std::string max_state;
        std::string max_state_path = ::android::base::StringPrintf(
                "%s/%s", path.data(), kCoolingDeviceMaxStateSuffix.data());
        if (!::android::base::ReadFileToString(max_state_path, &max_state)) {
            LOG(ERROR) << cooling_device_info_pair.first
                       << " could not open max state file:" << max_state_path;
            cooling_device_info_pair.second.max_state = std::numeric_limits<int>::max();
        } else {
            cooling_device_info_pair.second.max_state = std::stoi(::android::base::Trim(max_state));
            LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
                      << " max state: " << cooling_device_info_pair.second.max_state
                      << " state2power number: "
                      << cooling_device_info_pair.second.state2power.size();
            if (cooling_device_info_pair.second.state2power.size() > 0 &&
                static_cast<int>(cooling_device_info_pair.second.state2power.size()) !=
                        (cooling_device_info_pair.second.max_state + 1)) {
                LOG(ERROR) << "Invalid state2power number: "
                           << cooling_device_info_pair.second.state2power.size()
                           << ", number should be " << cooling_device_info_pair.second.max_state + 1
                           << " (max_state + 1)";
                return false;
            }
        }

        // Add cooling device path for thermalHAL to request state
        cooling_device_name =
                ::android::base::StringPrintf("%s_%s", cooling_device_name.c_str(), "w");
        std::string write_path;
        if (!cooling_device_info_pair.second.write_path.empty()) {
            write_path = cooling_device_info_pair.second.write_path.data();
        } else {
            write_path = ::android::base::StringPrintf("%s/%s", path.data(),
                                                       kCoolingDeviceCurStateSuffix.data());
        }

        if (!cooling_devices_.addThermalFile(cooling_device_name, write_path)) {
            LOG(ERROR) << "Could not add " << cooling_device_name
                       << " write path to cooling device map";
            return false;
        }
    }
    return true;
}

void ThermalHelperImpl::setMinTimeout(SensorInfo *sensor_info) {
    sensor_info->polling_delay = kMinPollIntervalMs;
    sensor_info->passive_delay = kMinPollIntervalMs;
}

void ThermalHelperImpl::initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
                                       std::set<std::string> *monitored_sensors,
                                       bool thermal_genl_enabled) {
    for (auto &sensor_info : sensor_info_map_) {
        if (!sensor_info.second.is_watch || (sensor_info.second.virtual_sensor_info != nullptr)) {
            continue;
        }

        bool trip_update = false;
        std::string_view sensor_name = sensor_info.first;
        std::string_view tz_path = path_map.at(sensor_name.data());
        std::string tz_policy;
        std::string path =
                ::android::base::StringPrintf("%s/%s", (tz_path.data()), kSensorPolicyFile.data());

        if (thermal_genl_enabled) {
            trip_update = true;
        } else {
            // Check if thermal zone support uevent notify
            if (!::android::base::ReadFileToString(path, &tz_policy)) {
                LOG(ERROR) << sensor_name << " could not open tz policy file:" << path;
            } else {
                tz_policy = ::android::base::Trim(tz_policy);
                if (tz_policy != kUserSpaceSuffix) {
                    LOG(ERROR) << sensor_name << " does not support uevent notify";
                } else {
                    trip_update = true;
                }
            }
        }
        if (trip_update) {
            // Update thermal zone trip point
            for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
                if (!std::isnan(sensor_info.second.hot_thresholds[i]) &&
                    !std::isnan(sensor_info.second.hot_hysteresis[i])) {
                    // Update trip_point_0_temp threshold
                    std::string threshold = std::to_string(static_cast<int>(
                            sensor_info.second.hot_thresholds[i] / sensor_info.second.multiplier));
                    path = ::android::base::StringPrintf("%s/%s", (tz_path.data()),
                                                         kSensorTripPointTempZeroFile.data());
                    if (!::android::base::WriteStringToFile(threshold, path)) {
                        LOG(ERROR) << "fail to update " << sensor_name << " trip point: " << path
                                   << " to " << threshold;
                        trip_update = false;
                        break;
                    }
                    // Update trip_point_0_hyst threshold
                    threshold = std::to_string(static_cast<int>(
                            sensor_info.second.hot_hysteresis[i] / sensor_info.second.multiplier));
                    path = ::android::base::StringPrintf("%s/%s", (tz_path.data()),
                                                         kSensorTripPointHystZeroFile.data());
                    if (!::android::base::WriteStringToFile(threshold, path)) {
                        LOG(ERROR) << "fail to update " << sensor_name << "trip hyst" << threshold
                                   << path;
                        trip_update = false;
                        break;
                    }
                    break;
                } else if (i == kThrottlingSeverityCount - 1) {
                    LOG(ERROR) << sensor_name << ":all thresholds are NAN";
                    trip_update = false;
                    break;
                }
            }
            monitored_sensors->insert(sensor_info.first);
        }

        if (!trip_update) {
            LOG(INFO) << "config Sensor: " << sensor_info.first
                      << " to default polling interval: " << kMinPollIntervalMs.count();
            setMinTimeout(&sensor_info.second);
        }
    }
}

bool ThermalHelperImpl::fillCurrentTemperatures(bool filterType, bool filterCallback,
                                                TemperatureType type,
                                                std::vector<Temperature> *temperatures) {
    std::vector<Temperature> ret;
    for (const auto &name_info_pair : sensor_info_map_) {
        Temperature temp;
        if (name_info_pair.second.is_hidden) {
            continue;
        }
        if (filterType && name_info_pair.second.type != type) {
            continue;
        }
        if (filterCallback && !name_info_pair.second.send_cb) {
            continue;
        }
        if (readTemperature(name_info_pair.first, &temp, nullptr, false)) {
            ret.emplace_back(std::move(temp));
        } else {
            LOG(ERROR) << __func__
                       << ": error reading temperature for sensor: " << name_info_pair.first;
        }
    }
    *temperatures = ret;
    return ret.size() > 0;
}

bool ThermalHelperImpl::fillTemperatureThresholds(
        bool filterType, TemperatureType type,
        std::vector<TemperatureThreshold> *thresholds) const {
    std::vector<TemperatureThreshold> ret;
    for (const auto &name_info_pair : sensor_info_map_) {
        TemperatureThreshold temp;
        if (name_info_pair.second.is_hidden) {
            continue;
        }
        if (filterType && name_info_pair.second.type != type) {
            continue;
        }
        if (readTemperatureThreshold(name_info_pair.first, &temp)) {
            ret.emplace_back(std::move(temp));
        } else {
            LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
                       << name_info_pair.first;
            return false;
        }
    }
    *thresholds = ret;
    return ret.size() > 0;
}

bool ThermalHelperImpl::fillCurrentCoolingDevices(
        bool filterType, CoolingType type, std::vector<CoolingDevice> *cooling_devices) const {
    std::vector<CoolingDevice> ret;
    for (const auto &name_info_pair : cooling_device_info_map_) {
        CoolingDevice value;
        if (filterType && name_info_pair.second.type != type) {
            continue;
        }
        if (readCoolingDevice(name_info_pair.first, &value)) {
            ret.emplace_back(std::move(value));
        } else {
            LOG(ERROR) << __func__ << ": error reading cooling device: " << name_info_pair.first;
            return false;
        }
    }
    *cooling_devices = ret;
    return ret.size() > 0;
}

bool ThermalHelperImpl::readDataByType(std::string_view sensor_data, float *reading_value,
                                       const SensorFusionType type, const bool force_no_cache,
                                       std::map<std::string, float> *sensor_log_map) {
    switch (type) {
        case SensorFusionType::SENSOR:
            if (!readThermalSensor(sensor_data.data(), reading_value, force_no_cache,
                                   sensor_log_map)) {
                LOG(ERROR) << "Failed to get " << sensor_data.data() << " data";
                return false;
            }
            break;
        case SensorFusionType::ODPM:
            *reading_value = GetPowerStatusMap().at(sensor_data.data()).last_updated_avg_power;
            if (std::isnan(*reading_value)) {
                LOG(INFO) << "Power data " << sensor_data.data() << " is under collecting";
                return true;
            }
            (*sensor_log_map)[sensor_data.data()] = *reading_value;
            break;
        case SensorFusionType::CONSTANT:
            *reading_value = std::atof(sensor_data.data());
            break;
        default:
            break;
    }
    return true;
}

float ThermalHelperImpl::runVirtualTempEstimator(std::string_view sensor_name,
                                                 std::map<std::string, float> *sensor_log_map) {
    std::vector<float> model_inputs;
    float estimated_vt = NAN;
    constexpr int kCelsius2mC = 1000;

    ATRACE_NAME(StringPrintf("ThermalHelper::runVirtualTempEstimator - %s", sensor_name.data())
                        .c_str());
    if (!(sensor_info_map_.count(sensor_name.data()) &&
          sensor_status_map_.count(sensor_name.data()))) {
        LOG(ERROR) << sensor_name << " not part of sensor_info_map_ or sensor_status_map_";
        return NAN;
    }

    const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
    if (!sensor_info.virtual_sensor_info->vt_estimator) {
        LOG(ERROR) << "vt_estimator not valid for " << sensor_name;
        return NAN;
    }

    model_inputs.reserve(sensor_info.virtual_sensor_info->linked_sensors.size());

    for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
        std::string linked_sensor = sensor_info.virtual_sensor_info->linked_sensors[i];

        if ((*sensor_log_map).count(linked_sensor.data())) {
            float value = (*sensor_log_map)[linked_sensor.data()];
            model_inputs.push_back(value / kCelsius2mC);
        } else {
            LOG(ERROR) << "failed to read sensor: " << linked_sensor;
            return NAN;
        }
    }

    ::thermal::vtestimator::VtEstimatorStatus ret =
            sensor_info.virtual_sensor_info->vt_estimator->Estimate(model_inputs, &estimated_vt);
    if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
        LOG(ERROR) << "Failed to run estimator (ret: " << ret << ") for " << sensor_name;
        return NAN;
    }

    return (estimated_vt * kCelsius2mC);
}

constexpr int kTranTimeoutParam = 2;

bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *temp,
                                          const bool force_no_cache,
                                          std::map<std::string, float> *sensor_log_map) {
    std::string file_reading;
    boot_clock::time_point now = boot_clock::now();

    ATRACE_NAME(StringPrintf("ThermalHelper::readThermalSensor - %s", sensor_name.data()).c_str());
    if (!(sensor_info_map_.count(sensor_name.data()) &&
          sensor_status_map_.count(sensor_name.data()))) {
        return false;
    }

    const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
    auto &sensor_status = sensor_status_map_.at(sensor_name.data());

    {
        std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
        if (sensor_status.override_status.emul_temp != nullptr) {
            *temp = sensor_status.override_status.emul_temp->temp;
            return true;
        }
    }

    const auto since_last_update = std::chrono::duration_cast<std::chrono::milliseconds>(
            now - sensor_status.thermal_cached.timestamp);

    // Check if thermal data need to be read from cache
    if (!force_no_cache &&
        (sensor_status.thermal_cached.timestamp != boot_clock::time_point::min()) &&
        (since_last_update < sensor_info.time_resolution) &&
        !isnan(sensor_status.thermal_cached.temp)) {
        *temp = sensor_status.thermal_cached.temp;
        (*sensor_log_map)[sensor_name.data()] = *temp;
        ATRACE_INT((sensor_name.data() + std::string("-cached")).c_str(), static_cast<int>(*temp));
        return true;
    }

    // Reading thermal sensor according to it's composition
    if (sensor_info.virtual_sensor_info == nullptr) {
        if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading) ||
            file_reading.empty()) {
            LOG(ERROR) << "failed to read sensor: " << sensor_name;
            return false;
        }
        *temp = std::stof(::android::base::Trim(file_reading));
    } else {
        const auto &linked_sensors_size = sensor_info.virtual_sensor_info->linked_sensors.size();
        std::vector<float> sensor_readings(linked_sensors_size, 0.0);

        // Calculate temperature of each of the linked sensor
        for (size_t i = 0; i < linked_sensors_size; i++) {
            if (!readDataByType(sensor_info.virtual_sensor_info->linked_sensors[i],
                                &sensor_readings[i],
                                sensor_info.virtual_sensor_info->linked_sensors_type[i],
                                force_no_cache, sensor_log_map)) {
                LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s linked sensor "
                           << sensor_info.virtual_sensor_info->linked_sensors[i];
                return false;
            }
            if (std::isnan(sensor_readings[i])) {
                LOG(INFO) << sensor_name << " data is under collecting";
                return true;
            }
        }

        if (sensor_info.virtual_sensor_info->formula == FormulaOption::USE_ML_MODEL) {
            *temp = runVirtualTempEstimator(sensor_name, sensor_log_map);

            if (std::isnan(*temp)) {
                LOG(ERROR) << "VirtualEstimator returned NAN for " << sensor_name;
                return false;
            }
        } else {
            float temp_val = 0.0;
            for (size_t i = 0; i < linked_sensors_size; i++) {
                float coefficient = 0.0;
                if (!readDataByType(sensor_info.virtual_sensor_info->coefficients[i], &coefficient,
                                    sensor_info.virtual_sensor_info->coefficients_type[i],
                                    force_no_cache, sensor_log_map)) {
                    LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
                               << sensor_info.virtual_sensor_info->coefficients[i];
                    return false;
                }
                if (std::isnan(coefficient)) {
                    LOG(INFO) << sensor_name << " data is under collecting";
                    return true;
                }
                switch (sensor_info.virtual_sensor_info->formula) {
                    case FormulaOption::COUNT_THRESHOLD:
                        if ((coefficient < 0 && sensor_readings[i] < -coefficient) ||
                            (coefficient >= 0 && sensor_readings[i] >= coefficient))
                            temp_val += 1;
                        break;
                    case FormulaOption::WEIGHTED_AVG:
                        temp_val += sensor_readings[i] * coefficient;
                        break;
                    case FormulaOption::MAXIMUM:
                        if (i == 0)
                            temp_val = std::numeric_limits<float>::lowest();
                        if (sensor_readings[i] * coefficient > temp_val)
                            temp_val = sensor_readings[i] * coefficient;
                        break;
                    case FormulaOption::MINIMUM:
                        if (i == 0)
                            temp_val = std::numeric_limits<float>::max();
                        if (sensor_readings[i] * coefficient < temp_val)
                            temp_val = sensor_readings[i] * coefficient;
                        break;
                    default:
                        LOG(ERROR) << "Unknown formula type for sensor " << sensor_name.data();
                        return false;
                }
            }
            *temp = (temp_val + sensor_info.virtual_sensor_info->offset);
        }
    }

    if (!isnan(sensor_info.step_ratio) && !isnan(sensor_status.thermal_cached.temp) &&
        since_last_update < sensor_info.passive_delay * kTranTimeoutParam) {
        *temp = (sensor_info.step_ratio * *temp +
                 (1 - sensor_info.step_ratio) * sensor_status.thermal_cached.temp);
    }

    (*sensor_log_map)[sensor_name.data()] = *temp;
    ATRACE_INT(sensor_name.data(), static_cast<int>(*temp));

    {
        std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
        sensor_status.thermal_cached.temp = *temp;
        sensor_status.thermal_cached.timestamp = now;
    }
    auto real_temp = (*temp) * sensor_info.multiplier;
    thermal_stats_helper_.updateSensorTempStatsByThreshold(sensor_name, real_temp);
    return true;
}

// This is called in the different thread context and will update sensor_status
// uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
std::chrono::milliseconds ThermalHelperImpl::thermalWatcherCallbackFunc(
        const std::set<std::string> &uevent_sensors) {
    std::vector<Temperature> temps;
    std::vector<std::string> cooling_devices_to_update;
    boot_clock::time_point now = boot_clock::now();
    auto min_sleep_ms = std::chrono::milliseconds::max();
    bool power_data_is_updated = false;

    ATRACE_CALL();
    for (auto &name_status_pair : sensor_status_map_) {
        bool force_update = false;
        bool force_no_cache = false;
        Temperature temp;
        TemperatureThreshold threshold;
        SensorStatus &sensor_status = name_status_pair.second;
        const SensorInfo &sensor_info = sensor_info_map_.at(name_status_pair.first);
        bool max_throttling = false;

        // Only handle the sensors in allow list
        if (!sensor_info.is_watch) {
            continue;
        }

        ATRACE_NAME(StringPrintf("ThermalHelper::thermalWatcherCallbackFunc - %s",
                                 name_status_pair.first.data())
                            .c_str());

        std::chrono::milliseconds time_elapsed_ms = std::chrono::milliseconds::zero();
        auto sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
                                ? sensor_info.passive_delay
                                : sensor_info.polling_delay;

        if (sensor_info.virtual_sensor_info != nullptr &&
            !sensor_info.virtual_sensor_info->trigger_sensors.empty()) {
            for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size(); i++) {
                const auto &trigger_sensor_status =
                        sensor_status_map_.at(sensor_info.virtual_sensor_info->trigger_sensors[i]);
                if (trigger_sensor_status.severity != ThrottlingSeverity::NONE) {
                    sleep_ms = sensor_info.passive_delay;
                    break;
                }
            }
        }
        // Check if the sensor need to be updated
        if (sensor_status.last_update_time == boot_clock::time_point::min()) {
            force_update = true;
        } else {
            time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                    now - sensor_status.last_update_time);
            if (uevent_sensors.size()) {
                if (sensor_info.virtual_sensor_info != nullptr) {
                    for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size();
                         i++) {
                        if (uevent_sensors.find(
                                    sensor_info.virtual_sensor_info->trigger_sensors[i]) !=
                            uevent_sensors.end()) {
                            force_update = true;
                            break;
                        }
                    }
                } else if (uevent_sensors.find(name_status_pair.first) != uevent_sensors.end()) {
                    force_update = true;
                    force_no_cache = true;
                }
            } else if (time_elapsed_ms > sleep_ms) {
                force_update = true;
            }
        }
        {
            std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
            max_throttling = sensor_status.override_status.max_throttling;
            if (sensor_status.override_status.pending_update) {
                force_update = sensor_status.override_status.pending_update;
                sensor_status.override_status.pending_update = false;
            }
        }
        LOG(VERBOSE) << "sensor " << name_status_pair.first
                     << ": time_elapsed=" << time_elapsed_ms.count()
                     << ", sleep_ms=" << sleep_ms.count() << ", force_update = " << force_update
                     << ", force_no_cache = " << force_no_cache;

        if (!force_update) {
            auto timeout_remaining = sleep_ms - time_elapsed_ms;
            if (min_sleep_ms > timeout_remaining) {
                min_sleep_ms = timeout_remaining;
            }
            LOG(VERBOSE) << "sensor " << name_status_pair.first
                         << ": timeout_remaining=" << timeout_remaining.count();
            continue;
        }

        std::pair<ThrottlingSeverity, ThrottlingSeverity> throttling_status;
        if (!readTemperature(name_status_pair.first, &temp, &throttling_status, force_no_cache)) {
            LOG(ERROR) << __func__
                       << ": error reading temperature for sensor: " << name_status_pair.first;
            continue;
        }
        if (!readTemperatureThreshold(name_status_pair.first, &threshold)) {
            LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
                       << name_status_pair.first;
            continue;
        }

        {
            // writer lock
            std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
            if (throttling_status.first != sensor_status.prev_hot_severity) {
                sensor_status.prev_hot_severity = throttling_status.first;
            }
            if (throttling_status.second != sensor_status.prev_cold_severity) {
                sensor_status.prev_cold_severity = throttling_status.second;
            }
            if (temp.throttlingStatus != sensor_status.severity) {
                temps.push_back(temp);
                sensor_status.severity = temp.throttlingStatus;
                sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
                                   ? sensor_info.passive_delay
                                   : sensor_info.polling_delay;
            }
        }

        if (!power_data_is_updated) {
            power_files_.refreshPowerStatus();
            power_data_is_updated = true;
        }

        if (sensor_status.severity == ThrottlingSeverity::NONE) {
            thermal_throttling_.clearThrottlingData(name_status_pair.first, sensor_info);
        } else {
            // update thermal throttling request
            thermal_throttling_.thermalThrottlingUpdate(
                    temp, sensor_info, sensor_status.severity, time_elapsed_ms,
                    power_files_.GetPowerStatusMap(), cooling_device_info_map_, max_throttling);
        }

        thermal_throttling_.computeCoolingDevicesRequest(
                name_status_pair.first, sensor_info, sensor_status.severity,
                &cooling_devices_to_update, &thermal_stats_helper_);
        if (min_sleep_ms > sleep_ms) {
            min_sleep_ms = sleep_ms;
        }

        LOG(VERBOSE) << "Sensor " << name_status_pair.first << ": sleep_ms=" << sleep_ms.count()
                     << ", min_sleep_ms voting result=" << min_sleep_ms.count();
        sensor_status.last_update_time = now;
    }

    if (!cooling_devices_to_update.empty()) {
        updateCoolingDevices(cooling_devices_to_update);
    }

    if (!temps.empty()) {
        for (const auto &t : temps) {
            if (sensor_info_map_.at(t.name).send_cb && cb_) {
                cb_(t);
            }

            if (sensor_info_map_.at(t.name).send_powerhint) {
                power_hal_service_.sendPowerExtHint(t);
            }
        }
    }

    int count_failed_reporting = thermal_stats_helper_.reportStats();
    if (count_failed_reporting != 0) {
        LOG(ERROR) << "Failed to report " << count_failed_reporting << " thermal stats";
    }

    const auto since_last_power_log_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            now - power_files_.GetPrevPowerLogTime());
    if (since_last_power_log_ms >= kPowerLogIntervalMs) {
        power_files_.logPowerStatus(now);
    }

    return min_sleep_ms;
}

}  // namespace implementation
}  // namespace thermal
}  // namespace hardware
}  // namespace android
}  // namespace aidl
