/*
 * 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

/*
 * 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.
 */
ThermalHelper::ThermalHelper(const NotificationCallback &cb)
    : thermal_watcher_(new ThermalWatcher(
              std::bind(&ThermalHelper::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;
    }

    for (auto const &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,
                .prev_hint_severity = ThrottlingSeverity::NONE,
                .last_update_time = boot_clock::time_point::min(),
                .thermal_cached = {NAN, boot_clock::time_point::min()},
                .emul_setting = nullptr,
        };

        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 (auto &binded_cdev_info_pair :
                 name_status_pair.second.throttling_info->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(WARNING) << "Sensor " << name_status_pair.first << "'s "
                                         << binded_cdev_info_pair.first
                                         << " cdev_ceiling:" << cdev_ceiling
                                         << " is higher than max state:" << cdev_info.max_state;
                        }
                        cdev_ceiling = cdev_info.max_state;
                    }
                }
            }
        }
        // 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 (!connectToPowerHal()) {
        LOG(ERROR) << "Fail to connect to Power Hal";
    } else {
        updateSupportedPowerHints();
    }

    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.";
    }

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

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;
}

bool ThermalHelper::emulTemp(std::string_view target_sensor, const float value) {
    LOG(INFO) << "Set " << target_sensor.data() << " emul_temp "
              << "to " << value;

    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;
    }

    sensor_status_map_.at(target_sensor.data())
            .emul_setting.reset(new EmulSetting{value, -1, true});

    thermal_watcher_->wake();
    return true;
}

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

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

    sensor_status_map_.at(target_sensor.data())
            .emul_setting.reset(new EmulSetting{NAN, severity, true});

    thermal_watcher_->wake();
    return true;
}

bool ThermalHelper::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_status : sensor_status_map_) {
            if (sensor_status.second.emul_setting != nullptr) {
                sensor_status.second.emul_setting.reset(new EmulSetting{NAN, -1, true});
            }
        }
    } else if (sensor_status_map_.count(target_sensor.data()) &&
               sensor_status_map_.at(target_sensor.data()).emul_setting != nullptr) {
        sensor_status_map_.at(target_sensor.data())
                .emul_setting.reset(new EmulSetting{NAN, -1, true});
    } else {
        LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
        return false;
    }
    return true;
}

bool ThermalHelper::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 ThermalHelper::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) << "readTemperature: failed to read sensor: " << 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->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.emul_setting != nullptr && sensor_status.emul_setting->emul_severity >= 0) {
        std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
        out->throttlingStatus =
                static_cast<ThrottlingSeverity>(sensor_status.emul_setting->emul_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
        LOG(INFO) << sensor_name.data() << ":" << out->value << " raw data: " << sensor_log.str();
    }

    return true;
}

bool ThermalHelper::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 ThermalHelper::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> ThermalHelper::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 ThermalHelper::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 ThermalHelper::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 ThermalHelper::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 ThermalHelper::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 ThermalHelper::setMinTimeout(SensorInfo *sensor_info) {
    sensor_info->polling_delay = kMinPollIntervalMs;
    sensor_info->passive_delay = kMinPollIntervalMs;
}

void ThermalHelper::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 ThermalHelper::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 ThermalHelper::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 ThermalHelper::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 ThermalHelper::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 false;
            }
            (*sensor_log_map)[sensor_data.data()] = *reading_value;
            break;
        default:
            break;
    }
    return true;
}

bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
                                      const bool force_no_cache,
                                      std::map<std::string, float> *sensor_log_map) {
    float temp_val = 0.0;
    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.emul_setting != nullptr &&
            !isnan(sensor_status.emul_setting->emul_temp)) {
            *temp = sensor_status.emul_setting->emul_temp;
            return true;
        }
    }

    // Check if thermal data need to be read from cache
    if (!force_no_cache &&
        (sensor_status.thermal_cached.timestamp != boot_clock::time_point::min()) &&
        (std::chrono::duration_cast<std::chrono::milliseconds>(
                 now - sensor_status.thermal_cached.timestamp) < 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)) {
            return false;
        }

        if (file_reading.empty()) {
            LOG(ERROR) << "failed to read sensor: " << sensor_name;
            return false;
        }
        *temp = std::stof(::android::base::Trim(file_reading));
    } else {
        for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
            float sensor_reading = 0.0;
            // Get the sensor reading data
            if (!readDataByType(sensor_info.virtual_sensor_info->linked_sensors[i], &sensor_reading,
                                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];
            }
            if (std::isnan(sensor_info.virtual_sensor_info->coefficients[i])) {
                return false;
            }
            float coefficient = sensor_info.virtual_sensor_info->coefficients[i];
            switch (sensor_info.virtual_sensor_info->formula) {
                case FormulaOption::COUNT_THRESHOLD:
                    if ((coefficient < 0 && sensor_reading < -coefficient) ||
                        (coefficient >= 0 && sensor_reading >= coefficient))
                        temp_val += 1;
                    break;
                case FormulaOption::WEIGHTED_AVG:
                    temp_val += sensor_reading * coefficient;
                    break;
                case FormulaOption::MAXIMUM:
                    if (i == 0)
                        temp_val = std::numeric_limits<float>::lowest();
                    if (sensor_reading * coefficient > temp_val)
                        temp_val = sensor_reading * coefficient;
                    break;
                case FormulaOption::MINIMUM:
                    if (i == 0)
                        temp_val = std::numeric_limits<float>::max();
                    if (sensor_reading * coefficient < temp_val)
                        temp_val = sensor_reading * coefficient;
                    break;
                default:
                    break;
            }
        }
        *temp = (temp_val + sensor_info.virtual_sensor_info->offset);
    }
    (*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;
    }
    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 ThermalHelper::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);

        // 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_);
            if (sensor_status.emul_setting != nullptr &&
                sensor_status.emul_setting->pending_update) {
                force_update = true;
                sensor_status.emul_setting->pending_update = false;
                LOG(INFO) << "Update " << name_status_pair.first.data()
                          << " right away with emul setting";
            }
        }
        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_);
        }

        thermal_throttling_.computeCoolingDevicesRequest(
                name_status_pair.first, sensor_info, sensor_status.severity,
                &cooling_devices_to_update);
        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 && isAidlPowerHalExist()) {
                sendPowerExtHint(t);
            }
        }
    }

    return min_sleep_ms;
}

bool ThermalHelper::connectToPowerHal() {
    return power_hal_service_.connect();
}

void ThermalHelper::updateSupportedPowerHints() {
    for (auto const &name_status_pair : sensor_info_map_) {
        if (!(name_status_pair.second.send_powerhint)) {
            continue;
        }
        ThrottlingSeverity current_severity = ThrottlingSeverity::NONE;
        for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
            if (severity == ThrottlingSeverity::NONE) {
                supported_powerhint_map_[name_status_pair.first][ThrottlingSeverity::NONE] =
                        ThrottlingSeverity::NONE;
                continue;
            }

            bool isSupported = false;
            ndk::ScopedAStatus isSupportedResult;

            if (power_hal_service_.isPowerHalExtConnected()) {
                isSupported = power_hal_service_.isModeSupported(name_status_pair.first, severity);
            }
            if (isSupported)
                current_severity = severity;
            supported_powerhint_map_[name_status_pair.first][severity] = current_severity;
        }
    }
}

void ThermalHelper::sendPowerExtHint(const Temperature &t) {
    ATRACE_CALL();
    std::lock_guard<std::shared_mutex> lock(sensor_status_map_mutex_);
    ThrottlingSeverity prev_hint_severity;
    prev_hint_severity = sensor_status_map_.at(t.name).prev_hint_severity;
    ThrottlingSeverity current_hint_severity = supported_powerhint_map_[t.name][t.throttlingStatus];

    if (prev_hint_severity == current_hint_severity)
        return;

    if (prev_hint_severity != ThrottlingSeverity::NONE) {
        power_hal_service_.setMode(t.name, prev_hint_severity, false);
    }

    if (current_hint_severity != ThrottlingSeverity::NONE) {
        power_hal_service_.setMode(t.name, current_hint_severity, true);
    }

    sensor_status_map_[t.name].prev_hint_severity = current_hint_severity;
}
}  // namespace implementation
}  // namespace thermal
}  // namespace hardware
}  // namespace android
}  // namespace aidl
