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

#include "power_files.h"
#include "thermal_info.h"

namespace aidl {
namespace android {
namespace hardware {
namespace thermal {
namespace implementation {
using ::android::base::StringPrintf;

// To find the next PID target state according to the current thermal severity
size_t getTargetStateOfPID(const SensorInfo &sensor_info, const ThrottlingSeverity curr_severity) {
    size_t target_state = 0;

    for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
        size_t state = static_cast<size_t>(severity);
        if (std::isnan(sensor_info.throttling_info->s_power[state])) {
            continue;
        }
        target_state = state;
        if (severity > curr_severity) {
            break;
        }
    }
    LOG(VERBOSE) << "PID target state = " << target_state;
    return target_state;
}

void ThermalThrottling::clearThrottlingData(std::string_view sensor_name,
                                            const SensorInfo &sensor_info) {
    if (!thermal_throttling_status_map_.count(sensor_name.data())) {
        return;
    }
    std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);

    for (auto &pid_power_budget_pair :
         thermal_throttling_status_map_.at(sensor_name.data()).pid_power_budget_map) {
        pid_power_budget_pair.second = std::numeric_limits<int>::max();
    }

    for (auto &pid_cdev_request_pair :
         thermal_throttling_status_map_.at(sensor_name.data()).pid_cdev_request_map) {
        pid_cdev_request_pair.second = 0;
    }

    for (auto &hardlimit_cdev_request_pair :
         thermal_throttling_status_map_.at(sensor_name.data()).hardlimit_cdev_request_map) {
        hardlimit_cdev_request_pair.second = 0;
    }

    for (auto &throttling_release_pair :
         thermal_throttling_status_map_.at(sensor_name.data()).throttling_release_map) {
        throttling_release_pair.second = 0;
    }

    thermal_throttling_status_map_[sensor_name.data()].prev_err = NAN;
    thermal_throttling_status_map_[sensor_name.data()].i_budget =
            sensor_info.throttling_info->i_default;
    thermal_throttling_status_map_[sensor_name.data()].prev_target =
            static_cast<size_t>(ThrottlingSeverity::NONE);
    thermal_throttling_status_map_[sensor_name.data()].prev_power_budget = NAN;
    thermal_throttling_status_map_[sensor_name.data()].tran_cycle = 0;

    return;
}

bool ThermalThrottling::registerThermalThrottling(
        std::string_view sensor_name, const std::shared_ptr<ThrottlingInfo> &throttling_info,
        const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map) {
    if (thermal_throttling_status_map_.count(sensor_name.data())) {
        LOG(ERROR) << "Sensor " << sensor_name.data() << " throttling map has been registered";
        return false;
    }

    if (throttling_info == nullptr) {
        LOG(ERROR) << "Sensor " << sensor_name.data() << " has no throttling info";
        return false;
    }

    thermal_throttling_status_map_[sensor_name.data()].prev_err = NAN;
    thermal_throttling_status_map_[sensor_name.data()].i_budget = throttling_info->i_default;
    thermal_throttling_status_map_[sensor_name.data()].prev_target =
            static_cast<size_t>(ThrottlingSeverity::NONE);
    thermal_throttling_status_map_[sensor_name.data()].prev_power_budget = NAN;
    thermal_throttling_status_map_[sensor_name.data()].tran_cycle = 0;

    for (auto &binded_cdev_pair : throttling_info->binded_cdev_info_map) {
        if (!cooling_device_info_map.count(binded_cdev_pair.first)) {
            LOG(ERROR) << "Could not find " << sensor_name.data() << "'s binded CDEV "
                       << binded_cdev_pair.first;
            return false;
        }
        // Register PID throttling map
        for (const auto &cdev_weight : binded_cdev_pair.second.cdev_weight_for_pid) {
            if (!std::isnan(cdev_weight)) {
                thermal_throttling_status_map_[sensor_name.data()]
                        .pid_power_budget_map[binded_cdev_pair.first] =
                        std::numeric_limits<int>::max();
                thermal_throttling_status_map_[sensor_name.data()]
                        .pid_cdev_request_map[binded_cdev_pair.first] = 0;
                thermal_throttling_status_map_[sensor_name.data()]
                        .cdev_status_map[binded_cdev_pair.first] = 0;
                cdev_all_request_map_[binded_cdev_pair.first].insert(0);
                break;
            }
        }
        // Register hard limit throttling map
        for (const auto &limit_info : binded_cdev_pair.second.limit_info) {
            if (limit_info > 0) {
                thermal_throttling_status_map_[sensor_name.data()]
                        .hardlimit_cdev_request_map[binded_cdev_pair.first] = 0;
                thermal_throttling_status_map_[sensor_name.data()]
                        .cdev_status_map[binded_cdev_pair.first] = 0;
                cdev_all_request_map_[binded_cdev_pair.first].insert(0);
                break;
            }
        }
        // Register throttling release map if power threshold exists
        if (!binded_cdev_pair.second.power_rail.empty()) {
            for (const auto &power_threshold : binded_cdev_pair.second.power_thresholds) {
                if (!std::isnan(power_threshold)) {
                    thermal_throttling_status_map_[sensor_name.data()]
                            .throttling_release_map[binded_cdev_pair.first] = 0;
                    break;
                }
            }
        }
    }
    return true;
}

// return power budget based on PID algo
float ThermalThrottling::updatePowerBudget(const Temperature &temp, const SensorInfo &sensor_info,
                                           std::chrono::milliseconds time_elapsed_ms,
                                           ThrottlingSeverity curr_severity) {
    float p = 0, d = 0;
    float power_budget = std::numeric_limits<float>::max();
    bool target_changed = false;
    float budget_transient = 0.0;
    auto &throttling_status = thermal_throttling_status_map_.at(temp.name);
    std::string sensor_name = temp.name;

    if (curr_severity == ThrottlingSeverity::NONE) {
        return power_budget;
    }

    const auto target_state = getTargetStateOfPID(sensor_info, curr_severity);
    if (throttling_status.prev_target != static_cast<size_t>(ThrottlingSeverity::NONE) &&
        target_state != throttling_status.prev_target &&
        sensor_info.throttling_info->tran_cycle > 0) {
        throttling_status.tran_cycle = sensor_info.throttling_info->tran_cycle - 1;
        target_changed = true;
    }
    throttling_status.prev_target = target_state;

    // Compute PID
    float err = sensor_info.hot_thresholds[target_state] - temp.value;
    p = err * (err < 0 ? sensor_info.throttling_info->k_po[target_state]
                       : sensor_info.throttling_info->k_pu[target_state]);

    if (err < sensor_info.throttling_info->i_cutoff[target_state]) {
        throttling_status.i_budget += err * sensor_info.throttling_info->k_i[target_state];
    }

    if (fabsf(throttling_status.i_budget) > sensor_info.throttling_info->i_max[target_state]) {
        throttling_status.i_budget = sensor_info.throttling_info->i_max[target_state] *
                                     (throttling_status.i_budget > 0 ? 1 : -1);
    }

    if (!std::isnan(throttling_status.prev_err) &&
        time_elapsed_ms != std::chrono::milliseconds::zero()) {
        d = sensor_info.throttling_info->k_d[target_state] * (err - throttling_status.prev_err) /
            time_elapsed_ms.count();
    }

    throttling_status.prev_err = err;
    // Calculate power budget
    power_budget =
            sensor_info.throttling_info->s_power[target_state] + p + throttling_status.i_budget + d;
    if (power_budget < sensor_info.throttling_info->min_alloc_power[target_state]) {
        power_budget = sensor_info.throttling_info->min_alloc_power[target_state];
    }
    if (power_budget > sensor_info.throttling_info->max_alloc_power[target_state]) {
        power_budget = sensor_info.throttling_info->max_alloc_power[target_state];
    }

    if (target_changed) {
        throttling_status.budget_transient = throttling_status.prev_power_budget - power_budget;
    }

    if (throttling_status.tran_cycle) {
        budget_transient = throttling_status.budget_transient *
                           ((static_cast<float>(throttling_status.tran_cycle) /
                             static_cast<float>(sensor_info.throttling_info->tran_cycle)));
        power_budget += budget_transient;
        throttling_status.tran_cycle--;
    }

    LOG(INFO) << temp.name << " power_budget=" << power_budget << " err=" << err
              << " s_power=" << sensor_info.throttling_info->s_power[target_state]
              << " time_elapsed_ms=" << time_elapsed_ms.count() << " p=" << p
              << " i=" << throttling_status.i_budget << " d=" << d
              << " budget transient=" << budget_transient << " control target=" << target_state;

    ATRACE_INT((sensor_name + std::string("-power_budget")).c_str(),
               static_cast<int>(power_budget));
    ATRACE_INT((sensor_name + std::string("-s_power")).c_str(),
               static_cast<int>(sensor_info.throttling_info->s_power[target_state]));
    ATRACE_INT((sensor_name + std::string("-time_elapsed_ms")).c_str(),
               static_cast<int>(time_elapsed_ms.count()));
    ATRACE_INT((sensor_name + std::string("-budget_transient")).c_str(),
               static_cast<int>(budget_transient));
    ATRACE_INT((sensor_name + std::string("-i")).c_str(),
               static_cast<int>(throttling_status.i_budget));
    ATRACE_INT((sensor_name + std::string("-target_state")).c_str(),
               static_cast<int>(target_state));

    ATRACE_INT((sensor_name + std::string("-err")).c_str(), static_cast<int>(err / sensor_info.multiplier));
    ATRACE_INT((sensor_name + std::string("-p")).c_str(), static_cast<int>(p));
    ATRACE_INT((sensor_name + std::string("-d")).c_str(), static_cast<int>(d));
    ATRACE_INT((sensor_name + std::string("-temp")).c_str(), static_cast<int>(temp.value / sensor_info.multiplier));

    throttling_status.prev_power_budget = power_budget;

    return power_budget;
}

float ThermalThrottling::computeExcludedPower(
        const SensorInfo &sensor_info, const ThrottlingSeverity curr_severity,
        const std::unordered_map<std::string, PowerStatus> &power_status_map, std::string *log_buf,
        std::string_view sensor_name) {
    float excluded_power = 0.0;

    for (const auto &excluded_power_info_pair :
         sensor_info.throttling_info->excluded_power_info_map) {
        const auto last_updated_avg_power =
                power_status_map.at(excluded_power_info_pair.first).last_updated_avg_power;
        if (!std::isnan(last_updated_avg_power)) {
            excluded_power += last_updated_avg_power *
                              excluded_power_info_pair.second[static_cast<size_t>(curr_severity)];
            log_buf->append(StringPrintf(
                    "(%s: %0.2f mW, cdev_weight: %f)", excluded_power_info_pair.first.c_str(),
                    last_updated_avg_power,
                    excluded_power_info_pair.second[static_cast<size_t>(curr_severity)]));

            ATRACE_INT((std::string(sensor_name) + std::string("-") +
                        excluded_power_info_pair.first + std::string("-avg_power"))
                               .c_str(),
                       static_cast<int>(last_updated_avg_power));
        }
    }

    ATRACE_INT((std::string(sensor_name) + std::string("-excluded_power")).c_str(),
               static_cast<int>(excluded_power));
    return excluded_power;
}

// Allocate power budget to binded cooling devices base on the real ODPM power data
bool ThermalThrottling::allocatePowerToCdev(
        const Temperature &temp, const SensorInfo &sensor_info,
        const ThrottlingSeverity curr_severity, const std::chrono::milliseconds time_elapsed_ms,
        const std::unordered_map<std::string, PowerStatus> &power_status_map,
        const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map) {
    float total_weight = 0;
    float last_updated_avg_power = NAN;
    float allocated_power = 0;
    float allocated_weight = 0;
    bool low_power_device_check = true;
    bool is_budget_allocated = false;
    bool power_data_invalid = false;
    std::set<std::string> allocated_cdev;
    std::string log_buf;

    std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
    auto total_power_budget = updatePowerBudget(temp, sensor_info, time_elapsed_ms, curr_severity);

    if (sensor_info.throttling_info->excluded_power_info_map.size()) {
        total_power_budget -= computeExcludedPower(sensor_info, curr_severity, power_status_map,
                                                   &log_buf, temp.name);
        total_power_budget = std::max(total_power_budget, 0.0f);
        if (!log_buf.empty()) {
            LOG(INFO) << temp.name << " power budget=" << total_power_budget << " after " << log_buf
                      << " is excluded";
        }
    }

    // Compute total cdev weight
    for (const auto &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
        const auto cdev_weight = binded_cdev_info_pair.second
                                         .cdev_weight_for_pid[static_cast<size_t>(curr_severity)];
        if (std::isnan(cdev_weight) || cdev_weight == 0) {
            allocated_cdev.insert(binded_cdev_info_pair.first);
            continue;
        }
        total_weight += cdev_weight;
    }

    while (!is_budget_allocated) {
        for (const auto &binded_cdev_info_pair :
             sensor_info.throttling_info->binded_cdev_info_map) {
            float cdev_power_adjustment = 0;
            const auto cdev_weight =
                    binded_cdev_info_pair.second
                            .cdev_weight_for_pid[static_cast<size_t>(curr_severity)];

            if (allocated_cdev.count(binded_cdev_info_pair.first)) {
                continue;
            }
            if (std::isnan(cdev_weight) || !cdev_weight) {
                allocated_cdev.insert(binded_cdev_info_pair.first);
                continue;
            }

            // Get the power data
            if (!power_data_invalid) {
                if (!binded_cdev_info_pair.second.power_rail.empty()) {
                    last_updated_avg_power =
                            power_status_map.at(binded_cdev_info_pair.second.power_rail)
                                    .last_updated_avg_power;
                    if (std::isnan(last_updated_avg_power)) {
                        LOG(VERBOSE) << "power data is under collecting";
                        power_data_invalid = true;
                        break;
                    }

                    ATRACE_INT((temp.name + std::string("-") +
                                binded_cdev_info_pair.second.power_rail + std::string("-avg_power"))
                                       .c_str(),
                               static_cast<int>(last_updated_avg_power));
                } else {
                    power_data_invalid = true;
                    break;
                }
                if (binded_cdev_info_pair.second.throttling_with_power_link) {
                    return false;
                }
            }

            auto cdev_power_budget = total_power_budget * (cdev_weight / total_weight);
            cdev_power_adjustment = cdev_power_budget - last_updated_avg_power;

            if (low_power_device_check) {
                // Share the budget for the CDEV which power is lower than target
                if (cdev_power_adjustment > 0 &&
                    thermal_throttling_status_map_[temp.name].pid_cdev_request_map.at(
                            binded_cdev_info_pair.first) == 0) {
                    allocated_power += last_updated_avg_power;
                    allocated_weight += cdev_weight;
                    allocated_cdev.insert(binded_cdev_info_pair.first);
                    if (!binded_cdev_info_pair.second.power_rail.empty()) {
                        log_buf.append(StringPrintf("(%s: %0.2f mW)",
                                                    binded_cdev_info_pair.second.power_rail.c_str(),
                                                    last_updated_avg_power));
                    }
                    LOG(VERBOSE) << temp.name << " binded " << binded_cdev_info_pair.first
                                 << " has been already at min state 0";
                }
            } else {
                const CdevInfo &cdev_info = cooling_device_info_map.at(binded_cdev_info_pair.first);
                if (!binded_cdev_info_pair.second.power_rail.empty()) {
                    log_buf.append(StringPrintf("(%s: %0.2f mW)",
                                                binded_cdev_info_pair.second.power_rail.c_str(),
                                                last_updated_avg_power));
                }
                // Ignore the power distribution if the CDEV has no space to reduce power
                if ((cdev_power_adjustment < 0 &&
                     thermal_throttling_status_map_[temp.name].pid_cdev_request_map.at(
                             binded_cdev_info_pair.first) == cdev_info.max_state)) {
                    LOG(VERBOSE) << temp.name << " binded " << binded_cdev_info_pair.first
                                 << " has been already at max state " << cdev_info.max_state;
                    continue;
                }

                if (!power_data_invalid && binded_cdev_info_pair.second.power_rail != "") {
                    auto cdev_curr_power_budget =
                            thermal_throttling_status_map_[temp.name].pid_power_budget_map.at(
                                    binded_cdev_info_pair.first);

                    if (last_updated_avg_power > cdev_curr_power_budget) {
                        cdev_power_budget = cdev_curr_power_budget +=
                                (cdev_power_adjustment *
                                 (cdev_curr_power_budget / last_updated_avg_power));
                    } else {
                        cdev_power_budget = cdev_curr_power_budget += cdev_power_adjustment;
                    }
                } else {
                    cdev_power_budget = total_power_budget * (cdev_weight / total_weight);
                }

                if (!std::isnan(cdev_info.state2power[0]) &&
                    cdev_power_budget > cdev_info.state2power[0]) {
                    cdev_power_budget = cdev_info.state2power[0];
                } else if (cdev_power_budget < 0) {
                    cdev_power_budget = 0;
                }

                int max_cdev_vote;
                if (!getCdevMaxRequest(binded_cdev_info_pair.first, &max_cdev_vote)) {
                    return false;
                }

                const auto curr_cdev_vote =
                        thermal_throttling_status_map_[temp.name].pid_cdev_request_map.at(
                                binded_cdev_info_pair.first);

                if (binded_cdev_info_pair.second.max_release_step !=
                            std::numeric_limits<int>::max() &&
                    (power_data_invalid || cdev_power_adjustment > 0)) {
                    if (!power_data_invalid && curr_cdev_vote < max_cdev_vote) {
                        cdev_power_budget = cdev_info.state2power[curr_cdev_vote];
                        LOG(VERBOSE) << temp.name << "'s " << binded_cdev_info_pair.first
                                     << " vote: " << curr_cdev_vote
                                     << " is lower than max cdev vote: " << max_cdev_vote;
                    } else {
                        const auto target_state = std::max(
                                curr_cdev_vote - binded_cdev_info_pair.second.max_release_step, 0);
                        cdev_power_budget =
                                std::min(cdev_power_budget, cdev_info.state2power[target_state]);
                    }
                }

                if (binded_cdev_info_pair.second.max_throttle_step !=
                            std::numeric_limits<int>::max() &&
                    (power_data_invalid || cdev_power_adjustment < 0)) {
                    const auto target_state = std::min(
                            curr_cdev_vote + binded_cdev_info_pair.second.max_throttle_step,
                            cdev_info.max_state);
                    cdev_power_budget =
                            std::max(cdev_power_budget, cdev_info.state2power[target_state]);
                }

                thermal_throttling_status_map_[temp.name].pid_power_budget_map.at(
                        binded_cdev_info_pair.first) = cdev_power_budget;
                LOG(VERBOSE) << temp.name << " allocate "
                             << thermal_throttling_status_map_[temp.name].pid_power_budget_map.at(
                                        binded_cdev_info_pair.first)
                             << "mW to " << binded_cdev_info_pair.first
                             << "(cdev_weight=" << cdev_weight << ")";
            }
        }

        if (!power_data_invalid) {
            total_power_budget -= allocated_power;
            total_weight -= allocated_weight;
        }
        allocated_power = 0;
        allocated_weight = 0;

        if (low_power_device_check) {
            low_power_device_check = false;
        } else {
            is_budget_allocated = true;
        }
    }
    if (log_buf.size()) {
        LOG(INFO) << temp.name << " binded power rails: " << log_buf;
    }
    return true;
}

void ThermalThrottling::updateCdevRequestByPower(
        std::string sensor_name,
        const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map) {
    size_t i;

    std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
    for (auto &pid_power_budget_pair :
         thermal_throttling_status_map_[sensor_name.data()].pid_power_budget_map) {
        const CdevInfo &cdev_info = cooling_device_info_map.at(pid_power_budget_pair.first);

        for (i = 0; i < cdev_info.state2power.size() - 1; ++i) {
            if (pid_power_budget_pair.second >= cdev_info.state2power[i]) {
                break;
            }
        }
        thermal_throttling_status_map_[sensor_name.data()].pid_cdev_request_map.at(
                pid_power_budget_pair.first) = static_cast<int>(i);
    }

    return;
}

void ThermalThrottling::updateCdevRequestBySeverity(std::string_view sensor_name,
                                                    const SensorInfo &sensor_info,
                                                    ThrottlingSeverity curr_severity) {
    std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
    for (auto const &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
        thermal_throttling_status_map_[sensor_name.data()].hardlimit_cdev_request_map.at(
                binded_cdev_info_pair.first) =
                binded_cdev_info_pair.second.limit_info[static_cast<size_t>(curr_severity)];
        LOG(VERBOSE) << "Hard Limit: Sensor " << sensor_name.data() << " update cdev "
                     << binded_cdev_info_pair.first << " to "
                     << thermal_throttling_status_map_[sensor_name.data()]
                                .hardlimit_cdev_request_map.at(binded_cdev_info_pair.first);
    }
}

bool ThermalThrottling::throttlingReleaseUpdate(
        std::string_view sensor_name,
        const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map,
        const std::unordered_map<std::string, PowerStatus> &power_status_map,
        const ThrottlingSeverity severity, const SensorInfo &sensor_info) {
    ATRACE_CALL();
    std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
    if (!thermal_throttling_status_map_.count(sensor_name.data())) {
        return false;
    }
    auto &thermal_throttling_status = thermal_throttling_status_map_.at(sensor_name.data());
    for (const auto &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
        float avg_power = -1;

        if (!thermal_throttling_status.throttling_release_map.count(binded_cdev_info_pair.first) ||
            !power_status_map.count(binded_cdev_info_pair.second.power_rail)) {
            return false;
        }

        const auto max_state = cooling_device_info_map.at(binded_cdev_info_pair.first).max_state;

        auto &release_step =
                thermal_throttling_status.throttling_release_map.at(binded_cdev_info_pair.first);
        avg_power =
                power_status_map.at(binded_cdev_info_pair.second.power_rail).last_updated_avg_power;

        if (std::isnan(avg_power) || avg_power < 0) {
            release_step = binded_cdev_info_pair.second.throttling_with_power_link ? max_state : 0;
            continue;
        }

        bool is_over_budget = true;
        if (!binded_cdev_info_pair.second.high_power_check) {
            if (avg_power <
                binded_cdev_info_pair.second.power_thresholds[static_cast<int>(severity)]) {
                is_over_budget = false;
            }
        } else {
            if (avg_power >
                binded_cdev_info_pair.second.power_thresholds[static_cast<int>(severity)]) {
                is_over_budget = false;
            }
        }
        LOG(INFO) << sensor_name.data() << "'s " << binded_cdev_info_pair.first
                  << " binded power rail " << binded_cdev_info_pair.second.power_rail
                  << ": power threshold = "
                  << binded_cdev_info_pair.second.power_thresholds[static_cast<int>(severity)]
                  << ", avg power = " << avg_power;
        std::string atrace_prefix = ::android::base::StringPrintf(
                "%s-%s", sensor_name.data(), binded_cdev_info_pair.second.power_rail.data());
        ATRACE_INT(
                (atrace_prefix + std::string("-power_threshold")).c_str(),
                static_cast<int>(
                        binded_cdev_info_pair.second.power_thresholds[static_cast<int>(severity)]));
        ATRACE_INT((atrace_prefix + std::string("-avg_power")).c_str(), avg_power);

        switch (binded_cdev_info_pair.second.release_logic) {
            case ReleaseLogic::INCREASE:
                if (!is_over_budget) {
                    if (std::abs(release_step) < static_cast<int>(max_state)) {
                        release_step--;
                    }
                } else {
                    release_step = 0;
                }
                break;
            case ReleaseLogic::DECREASE:
                if (!is_over_budget) {
                    if (release_step < static_cast<int>(max_state)) {
                        release_step++;
                    }
                } else {
                    release_step = 0;
                }
                break;
            case ReleaseLogic::STEPWISE:
                if (!is_over_budget) {
                    if (release_step < static_cast<int>(max_state)) {
                        release_step++;
                    }
                } else {
                    if (std::abs(release_step) < static_cast<int>(max_state)) {
                        release_step--;
                    }
                }
                break;
            case ReleaseLogic::RELEASE_TO_FLOOR:
                release_step = is_over_budget ? 0 : max_state;
                break;
            case ReleaseLogic::NONE:
            default:
                break;
        }
    }
    return true;
}

void ThermalThrottling::thermalThrottlingUpdate(
        const Temperature &temp, const SensorInfo &sensor_info,
        const ThrottlingSeverity curr_severity, const std::chrono::milliseconds time_elapsed_ms,
        const std::unordered_map<std::string, PowerStatus> &power_status_map,
        const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map) {
    if (!thermal_throttling_status_map_.count(temp.name)) {
        return;
    }

    if (thermal_throttling_status_map_[temp.name].pid_power_budget_map.size()) {
        if (!allocatePowerToCdev(temp, sensor_info, curr_severity, time_elapsed_ms,
                                 power_status_map, cooling_device_info_map)) {
            LOG(ERROR) << "Sensor " << temp.name << " PID request cdev failed";
            // Clear the CDEV request if the power budget is failed to be allocated
            for (auto &pid_cdev_request_pair :
                 thermal_throttling_status_map_[temp.name].pid_cdev_request_map) {
                pid_cdev_request_pair.second = 0;
            }
        }
        updateCdevRequestByPower(temp.name, cooling_device_info_map);
    }

    if (thermal_throttling_status_map_[temp.name].hardlimit_cdev_request_map.size()) {
        updateCdevRequestBySeverity(temp.name.c_str(), sensor_info, curr_severity);
    }

    if (thermal_throttling_status_map_[temp.name].throttling_release_map.size()) {
        throttlingReleaseUpdate(temp.name.c_str(), cooling_device_info_map, power_status_map,
                                curr_severity, sensor_info);
    }
}

void ThermalThrottling::computeCoolingDevicesRequest(
        std::string_view sensor_name, const SensorInfo &sensor_info,
        const ThrottlingSeverity curr_severity, std::vector<std::string> *cooling_devices_to_update) {
    int release_step = 0;
    std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);

    if (!thermal_throttling_status_map_.count(sensor_name.data())) {
        return;
    }

    auto &thermal_throttling_status = thermal_throttling_status_map_.at(sensor_name.data());
    const auto &cdev_release_map = thermal_throttling_status.throttling_release_map;

    for (auto &cdev_request_pair : thermal_throttling_status.cdev_status_map) {
        int pid_cdev_request = 0;
        int hardlimit_cdev_request = 0;
        const auto &cdev_name = cdev_request_pair.first;
        const auto &binded_cdev_info =
                sensor_info.throttling_info->binded_cdev_info_map.at(cdev_name);
        const auto cdev_ceiling = binded_cdev_info.cdev_ceiling[static_cast<size_t>(curr_severity)];
        const auto cdev_floor =
                binded_cdev_info.cdev_floor_with_power_link[static_cast<size_t>(curr_severity)];
        release_step = 0;

        if (thermal_throttling_status.pid_cdev_request_map.count(cdev_name)) {
            pid_cdev_request = thermal_throttling_status.pid_cdev_request_map.at(cdev_name);
        }

        if (thermal_throttling_status.hardlimit_cdev_request_map.count(cdev_name)) {
            hardlimit_cdev_request =
                    thermal_throttling_status.hardlimit_cdev_request_map.at(cdev_name);
        }

        if (cdev_release_map.count(cdev_name)) {
            release_step = cdev_release_map.at(cdev_name);
        }

        LOG(VERBOSE) << sensor_name.data() << " binded cooling device " << cdev_name
                     << "'s pid_request=" << pid_cdev_request
                     << " hardlimit_cdev_request=" << hardlimit_cdev_request
                     << " release_step=" << release_step
                     << " cdev_floor_with_power_link=" << cdev_floor
                     << " cdev_ceiling=" << cdev_ceiling;
        std::string atrace_prefix =
                ::android::base::StringPrintf("%s-%s", sensor_name.data(), cdev_name.data());
        ATRACE_INT((atrace_prefix + std::string("-pid_request")).c_str(), pid_cdev_request);
        ATRACE_INT((atrace_prefix + std::string("-hardlimit_request")).c_str(),
                   hardlimit_cdev_request);
        ATRACE_INT((atrace_prefix + std::string("-release_step")).c_str(), release_step);
        ATRACE_INT((atrace_prefix + std::string("-cdev_floor")).c_str(), cdev_floor);
        ATRACE_INT((atrace_prefix + std::string("-cdev_ceiling")).c_str(), cdev_ceiling);

        auto request_state = std::max(pid_cdev_request, hardlimit_cdev_request);
        if (release_step) {
            if (release_step >= request_state) {
                request_state = 0;
            } else {
                request_state = request_state - release_step;
            }
            // Only check the cdev_floor when release step is non zero
            request_state = std::max(request_state, cdev_floor);
        }
        request_state = std::min(request_state, cdev_ceiling);
        if (cdev_request_pair.second != request_state) {
            if (updateCdevMaxRequestAndNotifyIfChange(cdev_name, cdev_request_pair.second,
                                                      request_state)) {
                cooling_devices_to_update->emplace_back(cdev_name);
            }
            cdev_request_pair.second = request_state;
        }
    }
}

bool ThermalThrottling::updateCdevMaxRequestAndNotifyIfChange(std::string_view cdev_name,
                                                              int cur_request, int new_request) {
    std::unique_lock<std::shared_mutex> _lock(cdev_all_request_map_mutex_);
    auto &request_set = cdev_all_request_map_.at(cdev_name.data());
    int cur_max_request = (*request_set.begin());
    // Remove old cdev request and add the new one.
    request_set.erase(request_set.find(cur_request));
    request_set.insert(new_request);
    // Check if there is any change in aggregated max cdev request.
    int new_max_request = (*request_set.begin());
    LOG(VERBOSE) << "For cooling device [" << cdev_name.data()
                 << "] cur_max_request is: " << cur_max_request
                 << " new_max_request is: " << new_max_request;
    return new_max_request != cur_max_request;
}

bool ThermalThrottling::getCdevMaxRequest(std::string_view cdev_name, int *max_state) {
    std::shared_lock<std::shared_mutex> _lock(cdev_all_request_map_mutex_);
    if (!cdev_all_request_map_.count(cdev_name.data())) {
        LOG(ERROR) << "Cooling device [" << cdev_name.data()
                   << "] not present in cooling device request map";
        return false;
    }
    *max_state = *cdev_all_request_map_.at(cdev_name.data()).begin();
    return true;
}

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