aidl: Remove thermal HAL
* Pixel thermal HAL can now be used directly
Change-Id: Ied8350355b819453e84026585f47e097d3f502f5
diff --git a/aidl/thermal/Android.bp b/aidl/thermal/Android.bp
deleted file mode 100644
index e615115..0000000
--- a/aidl/thermal/Android.bp
+++ /dev/null
@@ -1,71 +0,0 @@
-cc_binary {
- name: "android.hardware.thermal-service.samsung",
- srcs: [
- "service.cpp",
- "Thermal.cpp",
- "thermal-helper.cpp",
- "utils/thermal_throttling.cpp",
- "utils/thermal_info.cpp",
- "utils/thermal_files.cpp",
- "utils/power_files.cpp",
- "utils/powerhal_helper.cpp",
- "utils/thermal_watcher.cpp",
- ],
- vendor: true,
- relative_install_path: "hw",
- vintf_fragments: [
- "android.hardware.thermal-service.samsung.xml"
- ],
- init_rc: [
- "android.hardware.thermal-service.samsung.rc",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "libjsoncpp",
- "libutils",
- "libnl",
- "libbinder_ndk",
- "android.hardware.power-V1-ndk",
- "android.hardware.thermal-V1-ndk",
- "pixel-power-ext-V1-ndk",
- ],
- static_libs: [
- "libpixelstats",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- "-Wunused",
- ],
- tidy: true,
- tidy_checks: [
- "android-*",
- "cert-*",
- "clang-analyzer-security*",
- ],
- tidy_checks_as_errors: [
- "android-*",
- "clang-analyzer-security*",
- "cert-*",
- ],
-}
-
-sh_binary {
- name: "thermal_logd.samsung",
- src: "init.thermal.logging.sh",
- vendor: true,
- init_rc: [
- "samsung-thermal-logd.rc",
- ],
-}
-
-sh_binary {
- name: "thermal_symlinks.samsung",
- src: "init.thermal.symlinks.sh",
- vendor: true,
- init_rc: [
- "samsung-thermal-symlinks.rc",
- ],
-}
diff --git a/aidl/thermal/Thermal.cpp b/aidl/thermal/Thermal.cpp
deleted file mode 100644
index f70cedd..0000000
--- a/aidl/thermal/Thermal.cpp
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * 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.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <utils/Trace.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-namespace {
-
-using std::chrono::system_clock;
-
-ndk::ScopedAStatus initErrorStatus() {
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
- "ThermalHAL not initialized properly.");
-}
-
-ndk::ScopedAStatus readErrorStatus() {
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
- EX_ILLEGAL_STATE, "ThermalHal cannot read any sensor data");
-}
-
-bool interfacesEqual(const std::shared_ptr<::ndk::ICInterface> left,
- const std::shared_ptr<::ndk::ICInterface> right) {
- if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
- return left == right;
- }
- return left->asBinder() == right->asBinder();
-}
-
-} // namespace
-
-Thermal::Thermal()
- : thermal_helper_(
- std::bind(&Thermal::sendThermalChangedCallback, this, std::placeholders::_1)) {}
-
-ndk::ScopedAStatus Thermal::getTemperatures(std::vector<Temperature> *_aidl_return) {
- return getFilteredTemperatures(false, TemperatureType::UNKNOWN, _aidl_return);
-}
-
-ndk::ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType type,
- std::vector<Temperature> *_aidl_return) {
- return getFilteredTemperatures(true, type, _aidl_return);
-}
-
-ndk::ScopedAStatus Thermal::getFilteredTemperatures(bool filterType, TemperatureType type,
- std::vector<Temperature> *_aidl_return) {
- *_aidl_return = {};
- if (!thermal_helper_.isInitializedOk()) {
- return initErrorStatus();
- }
- if (!thermal_helper_.fillCurrentTemperatures(filterType, false, type, _aidl_return)) {
- return readErrorStatus();
- }
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Thermal::getCoolingDevices(std::vector<CoolingDevice> *_aidl_return) {
- return getFilteredCoolingDevices(false, CoolingType::BATTERY, _aidl_return);
-}
-
-ndk::ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType type,
- std::vector<CoolingDevice> *_aidl_return) {
- return getFilteredCoolingDevices(true, type, _aidl_return);
-}
-
-ndk::ScopedAStatus Thermal::getFilteredCoolingDevices(bool filterType, CoolingType type,
- std::vector<CoolingDevice> *_aidl_return) {
- *_aidl_return = {};
- if (!thermal_helper_.isInitializedOk()) {
- return initErrorStatus();
- }
- if (!thermal_helper_.fillCurrentCoolingDevices(filterType, type, _aidl_return)) {
- return readErrorStatus();
- }
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Thermal::getTemperatureThresholds(
- std::vector<TemperatureThreshold> *_aidl_return) {
- *_aidl_return = {};
- return getFilteredTemperatureThresholds(false, TemperatureType::UNKNOWN, _aidl_return);
-}
-
-ndk::ScopedAStatus Thermal::getTemperatureThresholdsWithType(
- TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return) {
- return getFilteredTemperatureThresholds(true, type, _aidl_return);
-}
-
-ndk::ScopedAStatus Thermal::getFilteredTemperatureThresholds(
- bool filterType, TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return) {
- *_aidl_return = {};
- if (!thermal_helper_.isInitializedOk()) {
- return initErrorStatus();
- }
- if (!thermal_helper_.fillTemperatureThresholds(filterType, type, _aidl_return)) {
- return readErrorStatus();
- }
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Thermal::registerThermalChangedCallback(
- const std::shared_ptr<IThermalChangedCallback> &callback) {
- ATRACE_CALL();
- return registerThermalChangedCallback(callback, false, TemperatureType::UNKNOWN);
-}
-
-ndk::ScopedAStatus Thermal::registerThermalChangedCallbackWithType(
- const std::shared_ptr<IThermalChangedCallback> &callback, TemperatureType type) {
- ATRACE_CALL();
- return registerThermalChangedCallback(callback, true, type);
-}
-
-ndk::ScopedAStatus Thermal::unregisterThermalChangedCallback(
- const std::shared_ptr<IThermalChangedCallback> &callback) {
- if (callback == nullptr) {
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "Invalid nullptr callback");
- }
- bool removed = false;
- std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
- callbacks_.erase(
- std::remove_if(
- callbacks_.begin(), callbacks_.end(),
- [&](const CallbackSetting &c) {
- if (interfacesEqual(c.callback, callback)) {
- LOG(INFO)
- << "a callback has been unregistered to ThermalHAL, isFilter: "
- << c.is_filter_type << " Type: " << toString(c.type);
- removed = true;
- return true;
- }
- return false;
- }),
- callbacks_.end());
- if (!removed) {
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "Callback wasn't registered");
- }
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Thermal::registerThermalChangedCallback(
- const std::shared_ptr<IThermalChangedCallback> &callback, bool filterType,
- TemperatureType type) {
- ATRACE_CALL();
- if (callback == nullptr) {
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "Invalid nullptr callback");
- }
- if (!thermal_helper_.isInitializedOk()) {
- return initErrorStatus();
- }
- std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
- if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting &c) {
- return interfacesEqual(c.callback, callback);
- })) {
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "Callback already registered");
- }
- auto c = callbacks_.emplace_back(callback, filterType, type);
- LOG(INFO) << "a callback has been registered to ThermalHAL, isFilter: " << c.is_filter_type
- << " Type: " << toString(c.type);
- // Send notification right away after successful thermal callback registration
- std::function<void()> handler = [this, c, filterType, type]() {
- std::vector<Temperature> temperatures;
- if (thermal_helper_.fillCurrentTemperatures(filterType, true, type, &temperatures)) {
- for (const auto &t : temperatures) {
- if (!filterType || t.type == type) {
- LOG(INFO) << "Sending notification: "
- << " Type: " << toString(t.type) << " Name: " << t.name
- << " CurrentValue: " << t.value
- << " ThrottlingStatus: " << toString(t.throttlingStatus);
- c.callback->notifyThrottling(t);
- }
- }
- }
- };
- looper_.addEvent(Looper::Event{handler});
- return ndk::ScopedAStatus::ok();
-}
-
-void Thermal::sendThermalChangedCallback(const Temperature &t) {
- ATRACE_CALL();
- std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
- LOG(VERBOSE) << "Sending notification: "
- << " Type: " << toString(t.type) << " Name: " << t.name
- << " CurrentValue: " << t.value
- << " ThrottlingStatus: " << toString(t.throttlingStatus);
-
- callbacks_.erase(std::remove_if(callbacks_.begin(), callbacks_.end(),
- [&](const CallbackSetting &c) {
- if (!c.is_filter_type || t.type == c.type) {
- ::ndk::ScopedAStatus ret =
- c.callback->notifyThrottling(t);
- if (!ret.isOk()) {
- LOG(ERROR) << "a Thermal callback is dead, removed "
- "from callback list.";
- return true;
- }
- return false;
- }
- return false;
- }),
- callbacks_.end());
-}
-
-void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
- *dump_buf << "getVirtualSensorInfo:" << std::endl;
- const auto &map = thermal_helper_.GetSensorInfoMap();
- for (const auto &sensor_info_pair : map) {
- if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
- *dump_buf << " Name: " << sensor_info_pair.first << std::endl;
- *dump_buf << " LinkedSensorName: [";
- for (size_t i = 0;
- i < sensor_info_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
- *dump_buf << sensor_info_pair.second.virtual_sensor_info->linked_sensors[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " LinkedSensorCoefficient: [";
- for (size_t i = 0; i < sensor_info_pair.second.virtual_sensor_info->coefficients.size();
- i++) {
- *dump_buf << sensor_info_pair.second.virtual_sensor_info->coefficients[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " Offset: " << sensor_info_pair.second.virtual_sensor_info->offset
- << std::endl;
- *dump_buf << " Trigger Sensor: ";
- if (sensor_info_pair.second.virtual_sensor_info->trigger_sensors.empty()) {
- *dump_buf << "N/A" << std::endl;
- } else {
- for (size_t i = 0;
- i < sensor_info_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) {
- *dump_buf << sensor_info_pair.second.virtual_sensor_info->trigger_sensors[i]
- << " ";
- }
- *dump_buf << std::endl;
- }
- *dump_buf << " Formula: ";
- switch (sensor_info_pair.second.virtual_sensor_info->formula) {
- case FormulaOption::COUNT_THRESHOLD:
- *dump_buf << "COUNT_THRESHOLD";
- break;
- case FormulaOption::WEIGHTED_AVG:
- *dump_buf << "WEIGHTED_AVG";
- break;
- case FormulaOption::MAXIMUM:
- *dump_buf << "MAXIMUM";
- break;
- case FormulaOption::MINIMUM:
- *dump_buf << "MINIMUM";
- break;
- default:
- *dump_buf << "NONE";
- break;
- }
-
- *dump_buf << std::endl;
- }
- }
-}
-
-void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
- *dump_buf << "getThrottlingInfo:" << std::endl;
- const auto &map = thermal_helper_.GetSensorInfoMap();
- const auto &thermal_throttling_status_map = thermal_helper_.GetThermalThrottlingStatusMap();
- for (const auto &name_info_pair : map) {
- if (name_info_pair.second.throttling_info == nullptr) {
- continue;
- }
- if (name_info_pair.second.throttling_info->binded_cdev_info_map.size()) {
- if (thermal_throttling_status_map.find(name_info_pair.first) ==
- thermal_throttling_status_map.end()) {
- continue;
- }
- *dump_buf << " Name: " << name_info_pair.first << std::endl;
- if (thermal_throttling_status_map.at(name_info_pair.first)
- .pid_power_budget_map.size()) {
- *dump_buf << " PID Info:" << std::endl;
- *dump_buf << " K_po: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->k_po[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " K_pu: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->k_pu[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " K_i: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->k_i[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " K_d: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->k_d[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " i_max: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->i_max[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " max_alloc_power: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->max_alloc_power[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " min_alloc_power: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->min_alloc_power[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " s_power: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->s_power[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " i_cutoff: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << name_info_pair.second.throttling_info->i_cutoff[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- }
- *dump_buf << " Binded CDEV Info:" << std::endl;
- for (const auto &binded_cdev_info_pair :
- name_info_pair.second.throttling_info->binded_cdev_info_map) {
- *dump_buf << " Cooling device name: " << binded_cdev_info_pair.first << std::endl;
- if (thermal_throttling_status_map.at(name_info_pair.first)
- .pid_power_budget_map.size()) {
- *dump_buf << " WeightForPID: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << binded_cdev_info_pair.second.cdev_weight_for_pid[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- }
- *dump_buf << " Ceiling: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << binded_cdev_info_pair.second.cdev_ceiling[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " Hard limit: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << binded_cdev_info_pair.second.limit_info[i] << " ";
- }
- *dump_buf << "]" << std::endl;
-
- if (!binded_cdev_info_pair.second.power_rail.empty()) {
- *dump_buf << " Binded power rail: "
- << binded_cdev_info_pair.second.power_rail << std::endl;
- *dump_buf << " Power threshold: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << binded_cdev_info_pair.second.power_thresholds[i] << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " Floor with PowerLink: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- *dump_buf << binded_cdev_info_pair.second.cdev_floor_with_power_link[i]
- << " ";
- }
- *dump_buf << "]" << std::endl;
- *dump_buf << " Release logic: ";
- switch (binded_cdev_info_pair.second.release_logic) {
- case ReleaseLogic::INCREASE:
- *dump_buf << "INCREASE";
- break;
- case ReleaseLogic::DECREASE:
- *dump_buf << "DECREASE";
- break;
- case ReleaseLogic::STEPWISE:
- *dump_buf << "STEPWISE";
- break;
- case ReleaseLogic::RELEASE_TO_FLOOR:
- *dump_buf << "RELEASE_TO_FLOOR";
- break;
- default:
- *dump_buf << "NONE";
- break;
- }
- *dump_buf << std::endl;
- *dump_buf << " high_power_check: " << std::boolalpha
- << binded_cdev_info_pair.second.high_power_check << std::endl;
- *dump_buf << " throttling_with_power_link: " << std::boolalpha
- << binded_cdev_info_pair.second.throttling_with_power_link
- << std::endl;
- }
- }
- }
- }
-}
-
-void Thermal::dumpThrottlingRequestStatus(std::ostringstream *dump_buf) {
- const auto &thermal_throttling_status_map = thermal_helper_.GetThermalThrottlingStatusMap();
- if (!thermal_throttling_status_map.size()) {
- return;
- }
- *dump_buf << "getThrottlingRequestStatus:" << std::endl;
- for (const auto &thermal_throttling_status_pair : thermal_throttling_status_map) {
- *dump_buf << " Name: " << thermal_throttling_status_pair.first << std::endl;
- if (thermal_throttling_status_pair.second.pid_power_budget_map.size()) {
- *dump_buf << " power budget request state" << std::endl;
- for (const auto &request_pair :
- thermal_throttling_status_pair.second.pid_power_budget_map) {
- *dump_buf << " " << request_pair.first << ": " << request_pair.second
- << std::endl;
- }
- }
- if (thermal_throttling_status_pair.second.pid_cdev_request_map.size()) {
- *dump_buf << " pid cdev request state" << std::endl;
- for (const auto &request_pair :
- thermal_throttling_status_pair.second.pid_cdev_request_map) {
- *dump_buf << " " << request_pair.first << ": " << request_pair.second
- << std::endl;
- }
- }
- if (thermal_throttling_status_pair.second.hardlimit_cdev_request_map.size()) {
- *dump_buf << " hard limit cdev request state" << std::endl;
- for (const auto &request_pair :
- thermal_throttling_status_pair.second.hardlimit_cdev_request_map) {
- *dump_buf << " " << request_pair.first << ": " << request_pair.second
- << std::endl;
- }
- }
- if (thermal_throttling_status_pair.second.throttling_release_map.size()) {
- *dump_buf << " cdev release state" << std::endl;
- for (const auto &request_pair :
- thermal_throttling_status_pair.second.throttling_release_map) {
- *dump_buf << " " << request_pair.first << ": " << request_pair.second
- << std::endl;
- }
- }
- if (thermal_throttling_status_pair.second.cdev_status_map.size()) {
- *dump_buf << " cdev request state" << std::endl;
- for (const auto &request_pair : thermal_throttling_status_pair.second.cdev_status_map) {
- *dump_buf << " " << request_pair.first << ": " << request_pair.second
- << std::endl;
- }
- }
- }
-}
-
-void Thermal::dumpPowerRailInfo(std::ostringstream *dump_buf) {
- const auto &power_rail_info_map = thermal_helper_.GetPowerRailInfoMap();
- const auto &power_status_map = thermal_helper_.GetPowerStatusMap();
-
- *dump_buf << "getPowerRailInfo:" << std::endl;
- for (const auto &power_rail_pair : power_rail_info_map) {
- *dump_buf << " Power Rail: " << power_rail_pair.first << std::endl;
- *dump_buf << " Power Sample Count: " << power_rail_pair.second.power_sample_count
- << std::endl;
- *dump_buf << " Power Sample Delay: " << power_rail_pair.second.power_sample_delay.count()
- << std::endl;
- if (power_status_map.count(power_rail_pair.first)) {
- auto power_history = power_status_map.at(power_rail_pair.first).power_history;
- *dump_buf << " Last Updated AVG Power: "
- << power_status_map.at(power_rail_pair.first).last_updated_avg_power << " mW"
- << std::endl;
- if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
- *dump_buf << " Formula=";
- switch (power_rail_pair.second.virtual_power_rail_info->formula) {
- case FormulaOption::COUNT_THRESHOLD:
- *dump_buf << "COUNT_THRESHOLD";
- break;
- case FormulaOption::WEIGHTED_AVG:
- *dump_buf << "WEIGHTED_AVG";
- break;
- case FormulaOption::MAXIMUM:
- *dump_buf << "MAXIMUM";
- break;
- case FormulaOption::MINIMUM:
- *dump_buf << "MINIMUM";
- break;
- default:
- *dump_buf << "NONE";
- break;
- }
- *dump_buf << std::endl;
- }
- for (size_t i = 0; i < power_history.size(); ++i) {
- if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
- *dump_buf
- << " Linked power rail "
- << power_rail_pair.second.virtual_power_rail_info->linked_power_rails[i]
- << std::endl;
- *dump_buf << " Coefficient="
- << power_rail_pair.second.virtual_power_rail_info->coefficients[i]
- << std::endl;
- *dump_buf << " Power Samples: ";
- } else {
- *dump_buf << " Power Samples: ";
- }
- while (power_history[i].size() > 0) {
- const auto power_sample = power_history[i].front();
- power_history[i].pop();
- *dump_buf << "(T=" << power_sample.duration
- << ", uWs=" << power_sample.energy_counter << ") ";
- }
- *dump_buf << std::endl;
- }
- }
- }
-}
-
-void Thermal::dumpThermalData(int fd) {
- std::ostringstream dump_buf;
-
- if (!thermal_helper_.isInitializedOk()) {
- dump_buf << "ThermalHAL not initialized properly." << std::endl;
- } else {
- const auto &sensor_status_map = thermal_helper_.GetSensorStatusMap();
- {
- dump_buf << "getCachedTemperatures:" << std::endl;
- boot_clock::time_point now = boot_clock::now();
- for (const auto &sensor_status_pair : sensor_status_map) {
- if ((sensor_status_pair.second.thermal_cached.timestamp) ==
- boot_clock::time_point::min()) {
- continue;
- }
- dump_buf << " Name: " << sensor_status_pair.first
- << " CachedValue: " << sensor_status_pair.second.thermal_cached.temp
- << " TimeToCache: "
- << std::chrono::duration_cast<std::chrono::milliseconds>(
- now - sensor_status_pair.second.thermal_cached.timestamp)
- .count()
- << "ms" << std::endl;
- }
- }
- {
- dump_buf << "getEmulTemperatures:" << std::endl;
- for (const auto &sensor_status_pair : sensor_status_map) {
- if (sensor_status_pair.second.emul_setting == nullptr) {
- continue;
- }
- dump_buf << " Name: " << sensor_status_pair.first
- << " EmulTemp: " << sensor_status_pair.second.emul_setting->emul_temp
- << " EmulSeverity: "
- << sensor_status_pair.second.emul_setting->emul_severity << std::endl;
- }
- }
- {
- const auto &map = thermal_helper_.GetSensorInfoMap();
- dump_buf << "getCurrentTemperatures:" << std::endl;
- Temperature temp_2_0;
- for (const auto &name_info_pair : map) {
- thermal_helper_.readTemperature(name_info_pair.first, &temp_2_0, nullptr, true);
- dump_buf << " Type: " << toString(temp_2_0.type)
- << " Name: " << name_info_pair.first << " CurrentValue: " << temp_2_0.value
- << " ThrottlingStatus: " << toString(temp_2_0.throttlingStatus)
- << std::endl;
- }
- dump_buf << "getTemperatureThresholds:" << std::endl;
- for (const auto &name_info_pair : map) {
- if (!name_info_pair.second.is_watch) {
- continue;
- }
- dump_buf << " Type: " << toString(name_info_pair.second.type)
- << " Name: " << name_info_pair.first;
- dump_buf << " hotThrottlingThreshold: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- dump_buf << name_info_pair.second.hot_thresholds[i] << " ";
- }
- dump_buf << "] coldThrottlingThreshold: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- dump_buf << name_info_pair.second.cold_thresholds[i] << " ";
- }
- dump_buf << "] vrThrottlingThreshold: " << name_info_pair.second.vr_threshold;
- dump_buf << std::endl;
- }
- dump_buf << "getHysteresis:" << std::endl;
- for (const auto &name_info_pair : map) {
- if (!name_info_pair.second.is_watch) {
- continue;
- }
- dump_buf << " Name: " << name_info_pair.first;
- dump_buf << " hotHysteresis: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- dump_buf << name_info_pair.second.hot_hysteresis[i] << " ";
- }
- dump_buf << "] coldHysteresis: [";
- for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
- dump_buf << name_info_pair.second.cold_hysteresis[i] << " ";
- }
- dump_buf << "]" << std::endl;
- }
- }
- {
- dump_buf << "getCurrentCoolingDevices:" << std::endl;
- std::vector<CoolingDevice> cooling_devices;
- if (!thermal_helper_.fillCurrentCoolingDevices(false, CoolingType::CPU,
- &cooling_devices)) {
- dump_buf << " Failed to getCurrentCoolingDevices." << std::endl;
- }
-
- for (const auto &c : cooling_devices) {
- dump_buf << " Type: " << toString(c.type) << " Name: " << c.name
- << " CurrentValue: " << c.value << std::endl;
- }
- }
- {
- dump_buf << "getCallbacks:" << std::endl;
- dump_buf << " Total: " << callbacks_.size() << std::endl;
- for (const auto &c : callbacks_) {
- dump_buf << " IsFilter: " << c.is_filter_type << " Type: " << toString(c.type)
- << std::endl;
- }
- }
- {
- dump_buf << "sendCallback:" << std::endl;
- dump_buf << " Enabled List: ";
- const auto &map = thermal_helper_.GetSensorInfoMap();
- for (const auto &name_info_pair : map) {
- if (name_info_pair.second.send_cb) {
- dump_buf << name_info_pair.first << " ";
- }
- }
- dump_buf << std::endl;
- }
- {
- dump_buf << "sendPowerHint:" << std::endl;
- dump_buf << " Enabled List: ";
- const auto &map = thermal_helper_.GetSensorInfoMap();
- for (const auto &name_info_pair : map) {
- if (name_info_pair.second.send_powerhint) {
- dump_buf << name_info_pair.first << " ";
- }
- }
- dump_buf << std::endl;
- }
- dumpVirtualSensorInfo(&dump_buf);
- dumpThrottlingInfo(&dump_buf);
- dumpThrottlingRequestStatus(&dump_buf);
- dumpPowerRailInfo(&dump_buf);
- {
- dump_buf << "getAIDLPowerHalInfo:" << std::endl;
- dump_buf << " Exist: " << std::boolalpha << thermal_helper_.isAidlPowerHalExist()
- << std::endl;
- dump_buf << " Connected: " << std::boolalpha << thermal_helper_.isPowerHalConnected()
- << std::endl;
- dump_buf << " Ext connected: " << std::boolalpha
- << thermal_helper_.isPowerHalExtConnected() << std::endl;
- }
- }
- std::string buf = dump_buf.str();
- if (!::android::base::WriteStringToFd(buf, fd)) {
- PLOG(ERROR) << "Failed to dump state to fd";
- }
- fsync(fd);
-}
-
-binder_status_t Thermal::dump(int fd, const char **args, uint32_t numArgs) {
- if (numArgs == 0 || std::string(args[0]) == "-a") {
- dumpThermalData(fd);
- return STATUS_OK;
- }
-
- if (std::string(args[0]) == "emul_temp") {
- return (numArgs != 3 || !thermal_helper_.emulTemp(std::string(args[1]), std::atof(args[2])))
- ? STATUS_BAD_VALUE
- : STATUS_OK;
- } else if (std::string(args[0]) == "emul_severity") {
- return (numArgs != 3 ||
- !thermal_helper_.emulSeverity(std::string(args[1]), std::atoi(args[2])))
- ? STATUS_BAD_VALUE
- : STATUS_OK;
- } else if (std::string(args[0]) == "emul_clear") {
- return (numArgs != 2 || !thermal_helper_.emulClear(std::string(args[1]))) ? STATUS_BAD_VALUE
- : STATUS_OK;
- }
- return STATUS_BAD_VALUE;
-}
-
-void Thermal::Looper::addEvent(const Thermal::Looper::Event &e) {
- std::unique_lock<std::mutex> lock(mutex_);
- events_.push(e);
- cv_.notify_all();
-}
-
-void Thermal::Looper::loop() {
- while (true) {
- std::unique_lock<std::mutex> lock(mutex_);
- cv_.wait(lock, [&] { return !events_.empty(); });
- Event event = events_.front();
- events_.pop();
- lock.unlock();
- event.handler();
- }
-}
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/Thermal.h b/aidl/thermal/Thermal.h
deleted file mode 100644
index 5dd5648..0000000
--- a/aidl/thermal/Thermal.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/thermal/BnThermal.h>
-
-#include <mutex>
-#include <thread>
-
-#include "thermal-helper.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-struct CallbackSetting {
- CallbackSetting(std::shared_ptr<IThermalChangedCallback> callback, bool is_filter_type,
- TemperatureType type)
- : callback(std::move(callback)), is_filter_type(is_filter_type), type(type) {}
- std::shared_ptr<IThermalChangedCallback> callback;
- bool is_filter_type;
- TemperatureType type;
-};
-
-class Thermal : public BnThermal {
- public:
- Thermal();
- ~Thermal() = default;
- ndk::ScopedAStatus getTemperatures(std::vector<Temperature> *_aidl_return) override;
- ndk::ScopedAStatus getTemperaturesWithType(TemperatureType type,
- std::vector<Temperature> *_aidl_return) override;
-
- ndk::ScopedAStatus getCoolingDevices(std::vector<CoolingDevice> *_aidl_return) override;
- ndk::ScopedAStatus getCoolingDevicesWithType(CoolingType type,
- std::vector<CoolingDevice> *_aidl_return) override;
-
- ndk::ScopedAStatus getTemperatureThresholds(
- std::vector<TemperatureThreshold> *_aidl_return) override;
- ndk::ScopedAStatus getTemperatureThresholdsWithType(
- TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return) override;
-
- ndk::ScopedAStatus registerThermalChangedCallback(
- const std::shared_ptr<IThermalChangedCallback> &callback) override;
- ndk::ScopedAStatus registerThermalChangedCallbackWithType(
- const std::shared_ptr<IThermalChangedCallback> &callback,
- TemperatureType type) override;
- ndk::ScopedAStatus unregisterThermalChangedCallback(
- const std::shared_ptr<IThermalChangedCallback> &callback) override;
- binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
-
- // Helper function for calling callbacks
- void sendThermalChangedCallback(const Temperature &t);
-
- private:
- class Looper {
- public:
- struct Event {
- std::function<void()> handler;
- };
-
- Looper() {
- thread_ = std::thread([&] { loop(); });
- }
- void addEvent(const Event &e);
-
- private:
- std::condition_variable cv_;
- std::queue<Event> events_;
- std::mutex mutex_;
- std::thread thread_;
-
- void loop();
- };
-
- ThermalHelper thermal_helper_;
- std::mutex thermal_callback_mutex_;
- std::vector<CallbackSetting> callbacks_;
- Looper looper_;
-
- ndk::ScopedAStatus getFilteredTemperatures(bool filterType, TemperatureType type,
- std::vector<Temperature> *_aidl_return);
- ndk::ScopedAStatus getFilteredCoolingDevices(bool filterType, CoolingType type,
- std::vector<CoolingDevice> *_aidl_return);
- ndk::ScopedAStatus getFilteredTemperatureThresholds(
- bool filterType, TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return);
- ndk::ScopedAStatus registerThermalChangedCallback(
- const std::shared_ptr<IThermalChangedCallback> &callback, bool filterType,
- TemperatureType type);
-
- void dumpVirtualSensorInfo(std::ostringstream *dump_buf);
- void dumpThrottlingInfo(std::ostringstream *dump_buf);
- void dumpThrottlingRequestStatus(std::ostringstream *dump_buf);
- void dumpPowerRailInfo(std::ostringstream *dump_buf);
- void dumpThermalData(int fd);
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/android.hardware.thermal-service.samsung.rc b/aidl/thermal/android.hardware.thermal-service.samsung.rc
deleted file mode 100644
index 03eb6aa..0000000
--- a/aidl/thermal/android.hardware.thermal-service.samsung.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-on property:vendor.thermal.link_ready=1
- # queue the trigger to start thermal-hal and continue execute
- # per-device thermal setup "on property:vendor.thermal.link_ready=1"
- trigger enable-thermal-hal
-
-on enable-thermal-hal
- restart vendor.thermal-hal
-
-service vendor.thermal-hal /vendor/bin/hw/android.hardware.thermal-service.samsung
- class hal
- user system
- group system
- priority -20
- disabled
diff --git a/aidl/thermal/android.hardware.thermal-service.samsung.xml b/aidl/thermal/android.hardware.thermal-service.samsung.xml
deleted file mode 100644
index bdee744..0000000
--- a/aidl/thermal/android.hardware.thermal-service.samsung.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="aidl">
- <name>android.hardware.thermal</name>
- <version>1</version>
- <fqname>IThermal/default</fqname>
- </hal>
-</manifest>
diff --git a/aidl/thermal/init.thermal.logging.sh b/aidl/thermal/init.thermal.logging.sh
deleted file mode 100755
index de385ab..0000000
--- a/aidl/thermal/init.thermal.logging.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/vendor/bin/sh
-
-if [ $# -eq 1 ]; then
- interval=$1
-else
- exit 1
-fi
-
-while true
-do
- logline="tz:"
- for f in /sys/class/thermal/thermal*
- do
- temp=`cat $f/temp`
- logline+="|$temp"
- done
- logline+=" cdev:"
- for f in /sys/class/thermal/cooling_device*
- do
- cur_state=`cat $f/cur_state`
- logline+="|$cur_state"
- done
- log -p w -t THERMAL_LOG $logline
- sleep $interval
-done
diff --git a/aidl/thermal/init.thermal.symlinks.sh b/aidl/thermal/init.thermal.symlinks.sh
deleted file mode 100755
index d990897..0000000
--- a/aidl/thermal/init.thermal.symlinks.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/vendor/bin/sh
-
-for f in /sys/class/thermal/thermal_zone*
-do
- tz_name=`cat $f/type`
- ln -s $f /dev/thermal/tz-by-name/$tz_name
-done
-for f in /sys/class/thermal/cooling_device*
-do
- cdev_name=`cat $f/type`
- ln -s $f /dev/thermal/cdev-by-name/$cdev_name
-done
-setprop vendor.thermal.link_ready 1
diff --git a/aidl/thermal/samsung-thermal-logd.rc b/aidl/thermal/samsung-thermal-logd.rc
deleted file mode 100644
index fe14f1f..0000000
--- a/aidl/thermal/samsung-thermal-logd.rc
+++ /dev/null
@@ -1,130 +0,0 @@
-on property:persist.vendor.log.thermal=1
- start vendor.thermal.logd
-
-on property:persist.vendor.log.thermal=0
- stop vendor.thermal.logd
-
-on property:persist.vendor.log.thermal=1 && property:persist.vendor.log.thermal.interval=*
- restart vendor.thermal.logd
-
-service vendor.thermal.logd /vendor/bin/thermal_logd.samsung ${persist.vendor.log.thermal.interval:-5}
- class main
- user root
- group root system
- disabled
-
-# Switch thermal protection for Pixels
-on property:persist.vendor.disable.thermal.control=*
- setprop vendor.disable.thermal.control ${persist.vendor.disable.thermal.control}
-
-on property:persist.vendor.disable.thermalhal.control=*
- setprop vendor.disable.thermalhal.control ${persist.vendor.disable.thermalhal.control}
-
-on property:persist.vendor.disable.usb.overheat.mitigation=*
- setprop vendor.disable.usb.overheat.mitigation.control ${persist.vendor.disable.usb.overheat.mitigation}
-
-on property:persist.vendor.disable.bcl.control=*
- setprop vendor.disable.bcl.control ${persist.vendor.disable.bcl.control}
-
-on property:vendor.disable.thermalhal.control=* && property:vendor.thermal.link_ready=1
- restart vendor.thermal-hal
-
-on property:vendor.disable.thermal.control=1 && property:vendor.thermal.link_ready=1
- # common
- stop vendor.thermal-engine
- setprop vendor.disable.thermalhal.control 1
- # sdm845
- write /dev/thermal/tz-by-name/quiet-therm-adc/mode disabled
- write /dev/thermal/tz-by-name/quiet-therm-monitor/mode disabled
- write /dev/thermal/tz-by-name/fps-therm-adc/mode disabled
- write /dev/thermal/tz-by-name/fps-therm-monitor/mode disabled
- # sdm670
- write /dev/thermal/tz-by-name/mb-therm-adc/mode disabled
- write /dev/thermal/tz-by-name/mb-therm-monitor/mode disabled
- # sm8150
- write /dev/thermal/tz-by-name/sdm-therm/mode disabled
- write /dev/thermal/tz-by-name/sdm-therm-monitor/mode disabled
- # sm7150
- write /dev/thermal/tz-by-name/skin-therm-adc/mode disabled
- write /dev/thermal/tz-by-name/skin-therm-monitor/mode disabled
- # sm7250
- write /dev/thermal/tz-by-name/skin-therm/emul_temp 25000
- write /dev/thermal/tz-by-name/skin-therm/mode disabled
- write /dev/thermal/tz-by-name/skin-virt/emul_temp 25000
- write /dev/thermal/tz-by-name/skin-virt/mode disabled
- write /dev/thermal/tz-by-name/skin-therm-cpu/emul_temp 25000
- write /dev/thermal/tz-by-name/skin-therm-cpu/mode disabled
- write /dev/thermal/tz-by-name/skin-virt-cpu/emul_temp 25000
- write /dev/thermal/tz-by-name/skin-virt-cpu/mode disabled
- write /dev/thermal/tz-by-name/skin-therm-monitor/emul_temp 25000
- write /dev/thermal/tz-by-name/skin-therm-monitor/mode disabled
- write /dev/thermal/tz-by-name/skin-virt-monitor/emul_temp 25000
- write /dev/thermal/tz-by-name/skin-virt-monitor/mode disabled
- write /dev/thermal/tz-by-name/panel-audio-therm/emul_temp 25000
- write /dev/thermal/tz-by-name/panel-audio-therm/mode disabled
- write /dev/thermal/tz-by-name/cellular-emergency/emul_temp 25000
- write /dev/thermal/tz-by-name/cellular-emergency/mode disabled
- write /dev/thermal/tz-by-name/sdm-therm/emul_temp 25000
- write /dev/thermal/tz-by-name/sdm-therm/mode disabled
- write /dev/thermal/tz-by-name/charger-therm/emul_temp 25000
- write /dev/thermal/tz-by-name/charger-therm/mode disabled
- # P21
- write /dev/thermal/tz-by-name/disp_therm/mode disabled
-
-on property:vendor.disable.thermal.control=0 && property:vendor.thermal.link_ready=1
- # common
- start vendor.thermal-engine
- setprop vendor.disable.thermalhal.control 0
- # sdm845
- write /dev/thermal/tz-by-name/quiet-therm-adc/mode enabled
- write /dev/thermal/tz-by-name/quiet-therm-monitor/mode enabled
- write /dev/thermal/tz-by-name/fps-therm-adc/mode enabled
- write /dev/thermal/tz-by-name/fps-therm-monitor/mode enabled
- # sdm670
- write /dev/thermal/tz-by-name/mb-therm-adc/mode enabled
- write /dev/thermal/tz-by-name/mb-therm-monitor/mode enabled
- # sm8150
- write /dev/thermal/tz-by-name/sdm-therm/mode enabled
- write /dev/thermal/tz-by-name/sdm-therm-monitor/mode enabled
- # sm7150
- write /dev/thermal/tz-by-name/skin-therm-adc/mode enabled
- write /dev/thermal/tz-by-name/skin-therm-monitor/mode enabled
- # sm7250
- write /dev/thermal/tz-by-name/skin-therm/emul_temp 0
- write /dev/thermal/tz-by-name/skin-therm/mode enabled
- write /dev/thermal/tz-by-name/skin-virt/emul_temp 0
- write /dev/thermal/tz-by-name/skin-virt/mode enabled
- write /dev/thermal/tz-by-name/skin-therm-cpu/emul_temp 0
- write /dev/thermal/tz-by-name/skin-therm-cpu/mode enabled
- write /dev/thermal/tz-by-name/skin-virt-cpu/emul_temp 0
- write /dev/thermal/tz-by-name/skin-virt-cpu/mode enabled
- write /dev/thermal/tz-by-name/skin-therm-monitor/emul_temp 0
- write /dev/thermal/tz-by-name/skin-therm-monitor/mode enabled
- write /dev/thermal/tz-by-name/skin-virt-monitor/emul_temp 0
- write /dev/thermal/tz-by-name/skin-virt-monitor/mode enabled
- write /dev/thermal/tz-by-name/panel-audio-therm/emul_temp 0
- write /dev/thermal/tz-by-name/panel-audio-therm/mode enabled
- write /dev/thermal/tz-by-name/cellular-emergency/emul_temp 0
- write /dev/thermal/tz-by-name/cellular-emergency/mode enabled
- write /dev/thermal/tz-by-name/sdm-therm/emul_temp 0
- write /dev/thermal/tz-by-name/sdm-therm/mode enabled
- write /dev/thermal/tz-by-name/charger-therm/emul_temp 0
- write /dev/thermal/tz-by-name/charger-therm/mode enabled
- # P21
- write /dev/thermal/tz-by-name/disp_therm/mode enabled
-
-# Toggle BCL control
-on property:vendor.disable.bcl.control=1
- write /dev/thermal/tz-by-name/soc/mode disabled
-
-on property:vendor.disable.bcl.control=0
- write /dev/thermal/tz-by-name/soc/mode enabled
-
-# Switch USB port overheat protection
-on property:vendor.disable.usb.overheat.mitigation.control=1
- write /sys/module/overheat_mitigation/parameters/enable 0
- write /dev/thermal/tz-by-name/usb_pwr_therm2/emul_temp 25000
-
-on property:vendor.disable.usb.overheat.mitigation.control=0
- write /sys/module/overheat_mitigation/parameters/enable 1
- write /dev/thermal/tz-by-name/usb_pwr_therm2/emul_temp 0
diff --git a/aidl/thermal/samsung-thermal-symlinks.rc b/aidl/thermal/samsung-thermal-symlinks.rc
deleted file mode 100644
index fc2e38b..0000000
--- a/aidl/thermal/samsung-thermal-symlinks.rc
+++ /dev/null
@@ -1,11 +0,0 @@
-on boot
- mkdir /dev/thermal 0750 system system
- mkdir /dev/thermal/tz-by-name 0750 system system
- mkdir /dev/thermal/cdev-by-name 0750 system system
- start vendor.thermal.symlinks
-
-service vendor.thermal.symlinks /vendor/bin/thermal_symlinks.samsung
- user system
- group system
- oneshot
- disabled
diff --git a/aidl/thermal/service.cpp b/aidl/thermal/service.cpp
deleted file mode 100644
index 0e10d7b..0000000
--- a/aidl/thermal/service.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-#include "Thermal.h"
-
-constexpr std::string_view kThermalLogTag("samsung-thermal");
-
-using ::android::OK;
-using ::android::status_t;
-
-// Generated AIDL files:
-using Thermal = ::aidl::android::hardware::thermal::implementation::Thermal;
-
-#if !defined(THERMAL_INSTANCE_NAME)
-#define THERMAL_INSTANCE_NAME "default"
-#endif
-
-int main(int /* argc */, char ** /* argv */) {
- android::base::SetDefaultTag(kThermalLogTag.data());
-
- auto svc = ndk::SharedRefBase::make<Thermal>();
- const auto svcName = std::string() + svc->descriptor + "/" + THERMAL_INSTANCE_NAME;
- LOG(INFO) << "Samsung Thermal AIDL Service starting..." + svcName;
- ABinderProcess_setThreadPoolMaxThreadCount(0);
-
- auto svcBinder = svc->asBinder();
- binder_status_t status = AServiceManager_addService(svcBinder.get(), svcName.c_str());
- if (status != STATUS_OK) {
- LOG(ERROR) << "Samsung Thermal AIDL Service failed to start: " << status << ".";
- return EXIT_FAILURE;
- }
- LOG(INFO) << "Samsung Thermal HAL AIDL Service started.";
- ABinderProcess_joinThreadPool();
- return EXIT_FAILURE; // should not reach
-}
diff --git a/aidl/thermal/thermal-helper.cpp b/aidl/thermal/thermal-helper.cpp
deleted file mode 100644
index 928a7a3..0000000
--- a/aidl/thermal/thermal-helper.cpp
+++ /dev/null
@@ -1,1167 +0,0 @@
-/*
- * 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
diff --git a/aidl/thermal/thermal-helper.h b/aidl/thermal/thermal-helper.h
deleted file mode 100644
index dad4fea..0000000
--- a/aidl/thermal/thermal-helper.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/thermal/IThermal.h>
-
-#include <array>
-#include <chrono>
-#include <map>
-#include <mutex>
-#include <shared_mutex>
-#include <string>
-#include <string_view>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include "utils/power_files.h"
-#include "utils/powerhal_helper.h"
-#include "utils/thermal_files.h"
-#include "utils/thermal_info.h"
-#include "utils/thermal_throttling.h"
-#include "utils/thermal_watcher.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-using ::android::sp;
-
-using NotificationCallback = std::function<void(const Temperature &t)>;
-
-// Get thermal_zone type
-bool getThermalZoneTypeById(int tz_id, std::string *);
-
-struct ThermalSample {
- float temp;
- boot_clock::time_point timestamp;
-};
-
-struct EmulSetting {
- float emul_temp;
- int emul_severity;
- bool pending_update;
-};
-
-struct SensorStatus {
- ThrottlingSeverity severity;
- ThrottlingSeverity prev_hot_severity;
- ThrottlingSeverity prev_cold_severity;
- ThrottlingSeverity prev_hint_severity;
- boot_clock::time_point last_update_time;
- ThermalSample thermal_cached;
- std::unique_ptr<EmulSetting> emul_setting;
-};
-
-class ThermalHelper {
- public:
- explicit ThermalHelper(const NotificationCallback &cb);
- ~ThermalHelper() = default;
-
- bool fillCurrentTemperatures(bool filterType, bool filterCallback, TemperatureType type,
- std::vector<Temperature> *temperatures);
- bool fillTemperatureThresholds(bool filterType, TemperatureType type,
- std::vector<TemperatureThreshold> *thresholds) const;
- bool fillCurrentCoolingDevices(bool filterType, CoolingType type,
- std::vector<CoolingDevice> *coolingdevices) const;
- bool emulTemp(std::string_view target_sensor, const float temp);
- bool emulSeverity(std::string_view target_sensor, const int severity);
- bool emulClear(std::string_view target_sensor);
-
- // Disallow copy and assign.
- ThermalHelper(const ThermalHelper &) = delete;
- void operator=(const ThermalHelper &) = delete;
-
- bool isInitializedOk() const { return is_initialized_; }
-
- // Read the temperature of a single sensor.
- bool readTemperature(std::string_view sensor_name, Temperature *out);
- bool readTemperature(
- std::string_view sensor_name, Temperature *out,
- std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status = nullptr,
- const bool force_sysfs = false);
-
- bool readTemperatureThreshold(std::string_view sensor_name, TemperatureThreshold *out) const;
- // Read the value of a single cooling device.
- bool readCoolingDevice(std::string_view cooling_device, CoolingDevice *out) const;
- // Get SensorInfo Map
- const std::unordered_map<std::string, SensorInfo> &GetSensorInfoMap() const {
- return sensor_info_map_;
- }
- // Get CdevInfo Map
- const std::unordered_map<std::string, CdevInfo> &GetCdevInfoMap() const {
- return cooling_device_info_map_;
- }
- // Get SensorStatus Map
- const std::unordered_map<std::string, SensorStatus> &GetSensorStatusMap() const {
- std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
- return sensor_status_map_;
- }
- // Get ThermalThrottling Map
- const std::unordered_map<std::string, ThermalThrottlingStatus> &GetThermalThrottlingStatusMap()
- const {
- return thermal_throttling_.GetThermalThrottlingStatusMap();
- }
- // Get PowerRailInfo Map
- const std::unordered_map<std::string, PowerRailInfo> &GetPowerRailInfoMap() const {
- return power_files_.GetPowerRailInfoMap();
- }
-
- // Get PowerStatus Map
- const std::unordered_map<std::string, PowerStatus> &GetPowerStatusMap() const {
- return power_files_.GetPowerStatusMap();
- }
-
- void sendPowerExtHint(const Temperature &t);
- bool isAidlPowerHalExist() { return power_hal_service_.isAidlPowerHalExist(); }
- bool isPowerHalConnected() { return power_hal_service_.isPowerHalConnected(); }
- bool isPowerHalExtConnected() { return power_hal_service_.isPowerHalExtConnected(); }
-
- private:
- bool initializeSensorMap(const std::unordered_map<std::string, std::string> &path_map);
- bool initializeCoolingDevices(const std::unordered_map<std::string, std::string> &path_map);
- bool isSubSensorValid(std::string_view sensor_data, const SensorFusionType sensor_fusion_type);
- void setMinTimeout(SensorInfo *sensor_info);
- void initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
- std::set<std::string> *monitored_sensors, bool thermal_genl_enabled);
- void clearAllThrottling();
- // For thermal_watcher_'s polling thread, return the sleep interval
- std::chrono::milliseconds thermalWatcherCallbackFunc(
- const std::set<std::string> &uevent_sensors);
- // Return hot and cold severity status as std::pair
- std::pair<ThrottlingSeverity, ThrottlingSeverity> 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;
- // Read sensor data according to the type
- bool 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);
- // Read temperature data according to thermal sensor's info
- bool readThermalSensor(std::string_view sensor_name, float *temp, const bool force_sysfs,
- std::map<std::string, float> *sensor_log_map);
- bool connectToPowerHal();
- void updateSupportedPowerHints();
- void updateCoolingDevices(const std::vector<std::string> &cooling_devices_to_update);
- sp<ThermalWatcher> thermal_watcher_;
- PowerFiles power_files_;
- ThermalFiles thermal_sensors_;
- ThermalFiles cooling_devices_;
- ThermalThrottling thermal_throttling_;
- bool is_initialized_;
- const NotificationCallback cb_;
- std::unordered_map<std::string, CdevInfo> cooling_device_info_map_;
- std::unordered_map<std::string, SensorInfo> sensor_info_map_;
- std::unordered_map<std::string, std::unordered_map<ThrottlingSeverity, ThrottlingSeverity>>
- supported_powerhint_map_;
- PowerHalService power_hal_service_;
- mutable std::shared_mutex sensor_status_map_mutex_;
- std::unordered_map<std::string, SensorStatus> sensor_status_map_;
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/config_schema.json b/aidl/thermal/utils/config_schema.json
deleted file mode 100644
index fd493e1..0000000
--- a/aidl/thermal/utils/config_schema.json
+++ /dev/null
@@ -1,219 +0,0 @@
-{
- "definitions":{
-
- },
- "$schema":"http://json-schema.org/draft-07/schema#",
- "$id":"http://example.com/root.json",
- "type":"object",
- "title":"The Root Schema",
- "required":[
- "Sensors"
- ],
- "properties":{
- "Sensors":{
- "$id":"#/properties/Sensors",
- "type":"array",
- "title":"The Sensors Schema",
- "items":{
- "$id":"#/properties/Sensors/items",
- "type":"object",
- "title":"The Items Schema",
- "required":[
- "Name",
- "Type",
- "HotThreshold",
- "VrThreshold",
- "Multiplier"
- ],
- "properties":{
- "Name":{
- "$id":"#/properties/Sensors/items/properties/Name",
- "type":"string",
- "title":"The Name Schema",
- "default":"",
- "examples":[
- "cpu0-silver-usr"
- ],
- "pattern":"^(.+)$"
- },
- "Type":{
- "$id":"#/properties/Sensors/items/properties/Type",
- "type":"string",
- "title":"The Type Schema",
- "default":"",
- "examples":[
- "CPU"
- ],
- "pattern":"^(.+)$"
- },
- "HotThreshold":{
- "$id":"#/properties/Sensors/items/properties/HotThreshold",
- "type":"array",
- "title":"The hot threshold Schema, values are thresholds from ThrottlingSeverity::NONE to ThrottlingSeverity::SHUTDOWN",
- "default":"NAN",
- "maxItems":7,
- "minItems":7,
- "items":{
- "$id":"#/properties/Sensors/items/properties/HotThreshold/items",
- "type":[
- "string",
- "number"
- ],
- "title":"The Items Schema",
- "default":"",
- "examples":[
- "NAN",
- "NAN",
- "NAN",
- 95,
- "NAN",
- "NAN",
- 125
- ],
- "pattern":"^([-+]?[0-9]*\\.?[0-9]+|NAN)$"
- }
- },
- "HotHysteresis":{
- "$id":"#/properties/Sensors/items/properties/HotHysteresis",
- "type":"array",
- "title":"The hot hysteresis Schema, values are thresholds from ThrottlingSeverity::NONE to ThrottlingSeverity::SHUTDOWN. Throttling status will be cleared HotThreshold - HotHysteresis.",
- "default":null,
- "maxItems":7,
- "minItems":7,
- "items":{
- "$id":"#/properties/Sensors/items/properties/HotHysteresis/items",
- "type":[
- "number"
- ],
- "title":"The Items Schema",
- "default":0.0,
- "examples":[
- 0.0,
- 0.0,
- 0.0,
- 1.0,
- 1.5,
- 1.0,
- 2.0
- ]
- }
- },
- "ColdThreshold":{
- "$id":"#/properties/Sensors/items/properties/ColdThreshold",
- "type":"array",
- "title":"The cold threshold Schema, values are thresholds from ThrottlingSeverity::NONE to ThrottlingSeverity::SHUTDOWN, default to NAN",
- "default":null,
- "maxItems":7,
- "minItems":7,
- "items":{
- "$id":"#/properties/Sensors/items/properties/ColdThreshold/items",
- "type":"string",
- "title":"The Items Schema",
- "default":"NAN",
- "examples":[
- "NAN",
- "NAN",
- "NAN",
- "NAN",
- "NAN",
- "NAN",
- "NAN"
- ],
- "pattern":"^([-+]?[0-9]*\\.?[0-9]+|NAN)$"
- }
- },
- "ColdHysteresis":{
- "$id":"#/properties/Sensors/items/properties/ColdHysteresis",
- "type":"array",
- "title":"The cold hysteresis Schema, values are thresholds from ThrottlingSeverity::NONE to ThrottlingSeverity::SHUTDOWN. Throttling status will be cleared ColdThreshold + ColdHysteresis.",
- "default":null,
- "maxItems":7,
- "minItems":7,
- "items":{
- "$id":"#/properties/Sensors/items/properties/ColdHysteresis/items",
- "type":[
- "number"
- ],
- "title":"The Items Schema",
- "default":0.0,
- "examples":[
- 0.0,
- 0.0,
- 0.0,
- 1.0,
- 1.5,
- 1.0,
- 2.0
- ]
- }
- },
- "VrThreshold":{
- "$id":"#/properties/Sensors/items/properties/VrThreshold",
- "type":"string",
- "title":"The Vrthreshold Schema",
- "default":"",
- "examples":[
- "NAN"
- ],
- "pattern":"^(.*)$"
- },
- "Multiplier":{
- "$id":"#/properties/Sensors/items/properties/Multiplier",
- "type":"number",
- "title":"The Multiplier Schema",
- "default":0.001,
- "examples":[
- 0.001
- ],
- "exclusiveMinimum":0.0
- },
- "Monitor":{
- "$id":"#/properties/Sensors/items/properties/Monitor",
- "type":"boolean",
- "title":"The Monitor Schema, if the sensor will be monitored and used to trigger throttling event",
- "default":false,
- "examples":[
- true
- ]
- }
- }
- }
- },
- "CoolingDevices":{
- "$id":"#/properties/CoolingDevices",
- "type":"array",
- "title":"The Coolingdevices Schema",
- "items":{
- "$id":"#/properties/CoolingDevices/items",
- "type":"object",
- "title":"The Items Schema",
- "required":[
- "Name",
- "Type"
- ],
- "properties":{
- "Name":{
- "$id":"#/properties/CoolingDevices/items/properties/Name",
- "type":"string",
- "title":"The Name Schema",
- "default":"",
- "examples":[
- "thermal-cpufreq-0"
- ],
- "pattern":"^(.+)$"
- },
- "Type":{
- "$id":"#/properties/CoolingDevices/items/properties/Type",
- "type":"string",
- "title":"The Type Schema",
- "default":"",
- "examples":[
- "CPU"
- ],
- "pattern":"^(.+)$"
- }
- }
- }
- }
- }
-}
diff --git a/aidl/thermal/utils/power_files.cpp b/aidl/thermal/utils/power_files.cpp
deleted file mode 100644
index 50cc5b6..0000000
--- a/aidl/thermal/utils/power_files.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-
-/*
- * 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 "power_files.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <dirent.h>
-#include <utils/Trace.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-constexpr std::string_view kDeviceType("iio:device");
-constexpr std::string_view kIioRootDir("/sys/bus/iio/devices");
-constexpr std::string_view kEnergyValueNode("energy_value");
-
-using ::android::base::ReadFileToString;
-using ::android::base::StringPrintf;
-
-bool PowerFiles::registerPowerRailsToWatch(const Json::Value &config) {
- if (!ParsePowerRailInfo(config, &power_rail_info_map_)) {
- LOG(ERROR) << "Failed to parse power rail info config";
- return false;
- }
-
- if (!power_rail_info_map_.size()) {
- LOG(INFO) << " No power rail info config found";
- return true;
- }
-
- if (!findEnergySourceToWatch()) {
- LOG(ERROR) << "Cannot find energy source";
- return false;
- }
-
- if (!energy_info_map_.size() && !updateEnergyValues()) {
- LOG(ERROR) << "Faield to update energy info";
- return false;
- }
-
- for (const auto &power_rail_info_pair : power_rail_info_map_) {
- std::vector<std::queue<PowerSample>> power_history;
- if (!power_rail_info_pair.second.power_sample_count ||
- power_rail_info_pair.second.power_sample_delay == std::chrono::milliseconds::max()) {
- continue;
- }
-
- PowerSample power_sample = {
- .energy_counter = 0,
- .duration = 0,
- };
-
- if (power_rail_info_pair.second.virtual_power_rail_info != nullptr &&
- power_rail_info_pair.second.virtual_power_rail_info->linked_power_rails.size()) {
- for (size_t i = 0;
- i < power_rail_info_pair.second.virtual_power_rail_info->linked_power_rails.size();
- ++i) {
- if (!energy_info_map_.count(power_rail_info_pair.second.virtual_power_rail_info
- ->linked_power_rails[i])) {
- LOG(ERROR) << " Could not find energy source "
- << power_rail_info_pair.second.virtual_power_rail_info
- ->linked_power_rails[i];
- return false;
- }
- power_history.emplace_back(std::queue<PowerSample>());
- for (int j = 0; j < power_rail_info_pair.second.power_sample_count; j++) {
- power_history[i].emplace(power_sample);
- }
- }
- } else {
- if (energy_info_map_.count(power_rail_info_pair.first)) {
- power_history.emplace_back(std::queue<PowerSample>());
- for (int j = 0; j < power_rail_info_pair.second.power_sample_count; j++) {
- power_history[0].emplace(power_sample);
- }
- } else {
- LOG(ERROR) << "Could not find energy source " << power_rail_info_pair.first;
- return false;
- }
- }
-
- if (power_history.size()) {
- power_status_map_[power_rail_info_pair.first] = {
- .power_history = power_history,
- .last_update_time = boot_clock::time_point::min(),
- .last_updated_avg_power = NAN,
- };
- } else {
- LOG(ERROR) << "power history size is zero";
- return false;
- }
- LOG(INFO) << "Successfully to register power rail " << power_rail_info_pair.first;
- }
- return true;
-}
-
-bool PowerFiles::findEnergySourceToWatch(void) {
- std::string devicePath;
-
- if (energy_path_set_.size()) {
- return true;
- }
-
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kIioRootDir.data()), closedir);
- if (!dir) {
- PLOG(ERROR) << "Error opening directory" << kIioRootDir;
- return false;
- }
-
- // Find any iio:devices that support energy_value
- while (struct dirent *ent = readdir(dir.get())) {
- std::string devTypeDir = ent->d_name;
- if (devTypeDir.find(kDeviceType) != std::string::npos) {
- devicePath = StringPrintf("%s/%s", kIioRootDir.data(), devTypeDir.data());
- std::string deviceEnergyContent;
-
- if (!ReadFileToString(StringPrintf("%s/%s", devicePath.data(), kEnergyValueNode.data()),
- &deviceEnergyContent)) {
- } else if (deviceEnergyContent.size()) {
- energy_path_set_.emplace(
- StringPrintf("%s/%s", devicePath.data(), kEnergyValueNode.data()));
- }
- }
- }
-
- if (!energy_path_set_.size()) {
- return false;
- }
-
- return true;
-}
-
-bool PowerFiles::updateEnergyValues(void) {
- std::string deviceEnergyContent;
- std::string deviceEnergyContents;
- std::string line;
-
- ATRACE_CALL();
- for (const auto &path : energy_path_set_) {
- if (!::android::base::ReadFileToString(path, &deviceEnergyContent)) {
- LOG(ERROR) << "Failed to read energy content from " << path;
- return false;
- } else {
- deviceEnergyContents.append(deviceEnergyContent);
- }
- }
-
- std::istringstream energyData(deviceEnergyContents);
-
- while (std::getline(energyData, line)) {
- /* Read rail energy */
- uint64_t energy_counter = 0;
- uint64_t duration = 0;
-
- /* Format example: CH3(T=358356)[S2M_VDD_CPUCL2], 761330 */
- auto start_pos = line.find("T=");
- auto end_pos = line.find(')');
- if (start_pos != std::string::npos) {
- duration =
- strtoul(line.substr(start_pos + 2, end_pos - start_pos - 2).c_str(), NULL, 10);
- } else {
- continue;
- }
-
- start_pos = line.find(")[");
- end_pos = line.find(']');
- std::string railName;
- if (start_pos != std::string::npos) {
- railName = line.substr(start_pos + 2, end_pos - start_pos - 2);
- } else {
- continue;
- }
-
- start_pos = line.find("],");
- if (start_pos != std::string::npos) {
- energy_counter = strtoul(line.substr(start_pos + 2).c_str(), NULL, 10);
- } else {
- continue;
- }
-
- energy_info_map_[railName] = {
- .energy_counter = energy_counter,
- .duration = duration,
- };
- }
-
- return true;
-}
-
-float PowerFiles::updateAveragePower(std::string_view power_rail,
- std::queue<PowerSample> *power_history) {
- float avg_power = NAN;
-
- if (!energy_info_map_.count(power_rail.data())) {
- LOG(ERROR) << " Could not find power rail " << power_rail.data();
- return avg_power;
- }
- const auto last_sample = power_history->front();
- const auto curr_sample = energy_info_map_.at(power_rail.data());
- const auto duration = curr_sample.duration - last_sample.duration;
- const auto deltaEnergy = curr_sample.energy_counter - last_sample.energy_counter;
-
- if (!last_sample.duration) {
- LOG(VERBOSE) << "Power rail " << power_rail.data()
- << ": all power samples have not been collected yet";
- } else if (duration <= 0 || deltaEnergy < 0) {
- LOG(ERROR) << "Power rail " << power_rail.data() << " is invalid: duration = " << duration
- << ", deltaEnergy = " << deltaEnergy;
-
- return avg_power;
- } else {
- avg_power = static_cast<float>(deltaEnergy) / static_cast<float>(duration);
- LOG(VERBOSE) << "Power rail " << power_rail.data() << ", avg power = " << avg_power
- << ", duration = " << duration << ", deltaEnergy = " << deltaEnergy;
- }
-
- power_history->pop();
- power_history->push(curr_sample);
-
- return avg_power;
-}
-
-float PowerFiles::updatePowerRail(std::string_view power_rail) {
- float avg_power = NAN;
-
- if (!power_rail_info_map_.count(power_rail.data())) {
- return avg_power;
- }
-
- if (!power_status_map_.count(power_rail.data())) {
- return avg_power;
- }
-
- const auto &power_rail_info = power_rail_info_map_.at(power_rail.data());
- auto &power_status = power_status_map_.at(power_rail.data());
-
- boot_clock::time_point now = boot_clock::now();
- auto time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
- now - power_status.last_update_time);
-
- if (power_status.last_update_time != boot_clock::time_point::min() &&
- time_elapsed_ms < power_rail_info.power_sample_delay) {
- return power_status.last_updated_avg_power;
- }
-
- if (!energy_info_map_.size() && !updateEnergyValues()) {
- LOG(ERROR) << "Failed to update energy values";
- return avg_power;
- }
-
- if (power_rail_info.virtual_power_rail_info == nullptr) {
- avg_power = updateAveragePower(power_rail, &power_status.power_history[0]);
- } else {
- const auto offset = power_rail_info.virtual_power_rail_info->offset;
- float avg_power_val = 0.0;
- for (size_t i = 0; i < power_rail_info.virtual_power_rail_info->linked_power_rails.size();
- i++) {
- float coefficient = power_rail_info.virtual_power_rail_info->coefficients[i];
- float avg_power_number = updateAveragePower(
- power_rail_info.virtual_power_rail_info->linked_power_rails[i],
- &power_status.power_history[i]);
-
- switch (power_rail_info.virtual_power_rail_info->formula) {
- case FormulaOption::COUNT_THRESHOLD:
- if ((coefficient < 0 && avg_power_number < -coefficient) ||
- (coefficient >= 0 && avg_power_number >= coefficient))
- avg_power_val += 1;
- break;
- case FormulaOption::WEIGHTED_AVG:
- avg_power_val += avg_power_number * coefficient;
- break;
- case FormulaOption::MAXIMUM:
- if (i == 0)
- avg_power_val = std::numeric_limits<float>::lowest();
- if (avg_power_number * coefficient > avg_power_val)
- avg_power_val = avg_power_number * coefficient;
- break;
- case FormulaOption::MINIMUM:
- if (i == 0)
- avg_power_val = std::numeric_limits<float>::max();
- if (avg_power_number * coefficient < avg_power_val)
- avg_power_val = avg_power_number * coefficient;
- break;
- default:
- break;
- }
- }
- if (avg_power_val >= 0) {
- avg_power_val = avg_power_val + offset;
- }
-
- avg_power = avg_power_val;
- }
-
- if (avg_power < 0) {
- avg_power = NAN;
- }
-
- power_status.last_updated_avg_power = avg_power;
- power_status.last_update_time = now;
- return avg_power;
-}
-
-bool PowerFiles::refreshPowerStatus(void) {
- if (!updateEnergyValues()) {
- LOG(ERROR) << "Failed to update energy values";
- return false;
- }
-
- for (const auto &power_status_pair : power_status_map_) {
- updatePowerRail(power_status_pair.first);
- }
- return true;
-}
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/power_files.h b/aidl/thermal/utils/power_files.h
deleted file mode 100644
index bcf8e82..0000000
--- a/aidl/thermal/utils/power_files.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <android-base/chrono_utils.h>
-
-#include <chrono>
-#include <queue>
-#include <shared_mutex>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "thermal_info.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-using ::android::base::boot_clock;
-
-struct PowerSample {
- uint64_t energy_counter;
- uint64_t duration;
-};
-
-struct PowerStatus {
- boot_clock::time_point last_update_time;
- // A vector to record the queues of power sample history.
- std::vector<std::queue<PowerSample>> power_history;
- float last_updated_avg_power;
-};
-
-// A helper class for monitoring power rails.
-class PowerFiles {
- public:
- PowerFiles() = default;
- ~PowerFiles() = default;
- // Disallow copy and assign.
- PowerFiles(const PowerFiles &) = delete;
- void operator=(const PowerFiles &) = delete;
- bool registerPowerRailsToWatch(const Json::Value &config);
- // Update the power data from ODPM sysfs
- bool refreshPowerStatus(void);
- // Get power status map
- const std::unordered_map<std::string, PowerStatus> &GetPowerStatusMap() const {
- std::shared_lock<std::shared_mutex> _lock(power_status_map_mutex_);
- return power_status_map_;
- }
- // Get power rail info map
- const std::unordered_map<std::string, PowerRailInfo> &GetPowerRailInfoMap() const {
- return power_rail_info_map_;
- }
-
- private:
- // Update energy value to energy_info_map_, return false if the value is failed to update.
- bool updateEnergyValues(void);
- // Compute the average power for physical power rail.
- float updateAveragePower(std::string_view power_rail, std::queue<PowerSample> *power_history);
- // Update the power data for the target power rail.
- float updatePowerRail(std::string_view power_rail);
- // Find the energy source path, return false if no energy source found.
- bool findEnergySourceToWatch(void);
- // The map to record the energy counter for each power rail.
- std::unordered_map<std::string, PowerSample> energy_info_map_;
- // The map to record the power data for each thermal sensor.
- std::unordered_map<std::string, PowerStatus> power_status_map_;
- mutable std::shared_mutex power_status_map_mutex_;
- // The map to record the power rail information from thermal config
- std::unordered_map<std::string, PowerRailInfo> power_rail_info_map_;
- // The set to store the energy source paths
- std::unordered_set<std::string> energy_path_set_;
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/powerhal_helper.cpp b/aidl/thermal/utils/powerhal_helper.cpp
deleted file mode 100644
index c40d262..0000000
--- a/aidl/thermal/utils/powerhal_helper.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.
- */
-
-#include "powerhal_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 <android/binder_manager.h>
-
-#include <iterator>
-#include <set>
-#include <sstream>
-#include <thread>
-#include <vector>
-
-#include "thermal_info.h"
-#include "thermal_throttling.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-using ::android::base::StringPrintf;
-
-PowerHalService::PowerHalService()
- : power_hal_aidl_exist_(true), power_hal_aidl_(nullptr), power_hal_ext_aidl_(nullptr) {
- connect();
-}
-
-bool PowerHalService::connect() {
- std::lock_guard<std::mutex> lock(lock_);
-
- if (!power_hal_aidl_exist_) {
- return false;
- }
-
- if (power_hal_aidl_ && power_hal_ext_aidl_) {
- return true;
- }
-
- const std::string kInstance = std::string(IPower::descriptor) + "/default";
- ndk::SpAIBinder power_binder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
- ndk::SpAIBinder ext_power_binder;
-
- if (power_binder.get() == nullptr) {
- LOG(ERROR) << "Cannot get Power Hal Binder";
- power_hal_aidl_exist_ = false;
- return false;
- }
-
- power_hal_aidl_ = IPower::fromBinder(power_binder);
-
- if (power_hal_aidl_ == nullptr) {
- power_hal_aidl_exist_ = false;
- LOG(ERROR) << "Cannot get Power Hal AIDL" << kInstance.c_str();
- return false;
- }
-
- if (STATUS_OK != AIBinder_getExtension(power_binder.get(), ext_power_binder.getR()) ||
- ext_power_binder.get() == nullptr) {
- LOG(ERROR) << "Cannot get Power Hal Extension Binder";
- power_hal_aidl_exist_ = false;
- return false;
- }
-
- power_hal_ext_aidl_ = IPowerExt::fromBinder(ext_power_binder);
- if (power_hal_ext_aidl_ == nullptr) {
- LOG(ERROR) << "Cannot get Power Hal Extension AIDL";
- power_hal_aidl_exist_ = false;
- }
-
- return true;
-}
-
-bool PowerHalService::isModeSupported(const std::string &type, const ThrottlingSeverity &t) {
- bool isSupported = false;
- if (!connect()) {
- return false;
- }
- std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
- lock_.lock();
- if (!power_hal_ext_aidl_->isModeSupported(power_hint, &isSupported).isOk()) {
- LOG(ERROR) << "Fail to check supported mode, Hint: " << power_hint;
- power_hal_ext_aidl_ = nullptr;
- power_hal_aidl_ = nullptr;
- lock_.unlock();
- return false;
- }
- lock_.unlock();
- return isSupported;
-}
-
-void PowerHalService::setMode(const std::string &type, const ThrottlingSeverity &t,
- const bool &enable, const bool error_on_exit) {
- if (!connect()) {
- return;
- }
-
- std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
- LOG(INFO) << (error_on_exit ? "Resend Hint " : "Send Hint ") << power_hint
- << " Enable: " << std::boolalpha << enable;
- lock_.lock();
- if (!power_hal_ext_aidl_->setMode(power_hint, enable).isOk()) {
- LOG(ERROR) << "Fail to set mode, Hint: " << power_hint;
- power_hal_ext_aidl_ = nullptr;
- power_hal_aidl_ = nullptr;
- lock_.unlock();
- if (!error_on_exit) {
- setMode(type, t, enable, true);
- }
- return;
- }
- lock_.unlock();
-}
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/powerhal_helper.h b/aidl/thermal/utils/powerhal_helper.h
deleted file mode 100644
index 0769aa2..0000000
--- a/aidl/thermal/utils/powerhal_helper.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/power/IPower.h>
-#include <aidl/android/hardware/thermal/ThrottlingSeverity.h>
-#include <aidl/google/hardware/power/extension/pixel/IPowerExt.h>
-
-#include <queue>
-#include <shared_mutex>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-using ::aidl::android::hardware::power::IPower;
-using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
-
-using CdevRequestStatus = std::unordered_map<std::string, int>;
-
-class PowerHalService {
- public:
- PowerHalService();
- ~PowerHalService() = default;
- bool connect();
- bool isAidlPowerHalExist() { return power_hal_aidl_exist_; }
- bool isModeSupported(const std::string &type, const ThrottlingSeverity &t);
- bool isPowerHalConnected() { return power_hal_aidl_ != nullptr; }
- bool isPowerHalExtConnected() { return power_hal_ext_aidl_ != nullptr; }
- void setMode(const std::string &type, const ThrottlingSeverity &t, const bool &enable,
- const bool error_on_exit = false);
-
- private:
- bool power_hal_aidl_exist_;
- std::shared_ptr<IPower> power_hal_aidl_;
- std::shared_ptr<IPowerExt> power_hal_ext_aidl_;
- std::mutex lock_;
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_files.cpp b/aidl/thermal/utils/thermal_files.cpp
deleted file mode 100644
index 26aaf45..0000000
--- a/aidl/thermal/utils/thermal_files.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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_files.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <utils/Trace.h>
-
-#include <algorithm>
-#include <string_view>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-using ::android::base::StringPrintf;
-
-std::string ThermalFiles::getThermalFilePath(std::string_view thermal_name) const {
- auto sensor_itr = thermal_name_to_path_map_.find(thermal_name.data());
- if (sensor_itr == thermal_name_to_path_map_.end()) {
- return "";
- }
- return sensor_itr->second;
-}
-
-bool ThermalFiles::addThermalFile(std::string_view thermal_name, std::string_view path) {
- return thermal_name_to_path_map_.emplace(thermal_name, path).second;
-}
-
-bool ThermalFiles::readThermalFile(std::string_view thermal_name, std::string *data) const {
- std::string sensor_reading;
- std::string file_path = getThermalFilePath(std::string_view(thermal_name));
- *data = "";
-
- ATRACE_NAME(StringPrintf("ThermalFiles::readThermalFile - %s", thermal_name.data()).c_str());
- if (file_path.empty()) {
- PLOG(WARNING) << "Failed to find " << thermal_name << "'s path";
- return false;
- }
-
- if (!::android::base::ReadFileToString(file_path, &sensor_reading)) {
- PLOG(WARNING) << "Failed to read sensor: " << thermal_name;
- return false;
- }
-
- // Strip the newline.
- *data = ::android::base::Trim(sensor_reading);
- return true;
-}
-
-bool ThermalFiles::writeCdevFile(std::string_view cdev_name, std::string_view data) {
- std::string file_path =
- getThermalFilePath(::android::base::StringPrintf("%s_%s", cdev_name.data(), "w"));
-
- ATRACE_NAME(StringPrintf("ThermalFiles::writeCdevFile - %s", cdev_name.data()).c_str());
- if (!::android::base::WriteStringToFile(data.data(), file_path)) {
- PLOG(WARNING) << "Failed to write cdev: " << cdev_name << " to " << data.data();
- return false;
- }
-
- return true;
-}
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_files.h b/aidl/thermal/utils/thermal_files.h
deleted file mode 100644
index 4b83780..0000000
--- a/aidl/thermal/utils/thermal_files.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <string>
-#include <unordered_map>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-class ThermalFiles {
- public:
- ThermalFiles() = default;
- ~ThermalFiles() = default;
- ThermalFiles(const ThermalFiles &) = delete;
- void operator=(const ThermalFiles &) = delete;
-
- std::string getThermalFilePath(std::string_view thermal_name) const;
- // Returns true if add was successful, false otherwise.
- bool addThermalFile(std::string_view thermal_name, std::string_view path);
- // If thermal_name is not found in the thermal names to path map, this will set
- // data to empty and return false. If the thermal_name is found and its content
- // is read, this function will fill in data accordingly then return true.
- bool readThermalFile(std::string_view thermal_name, std::string *data) const;
- bool writeCdevFile(std::string_view thermal_name, std::string_view data);
- size_t getNumThermalFiles() const { return thermal_name_to_path_map_.size(); }
-
- private:
- std::unordered_map<std::string, std::string> thermal_name_to_path_map_;
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_info.cpp b/aidl/thermal/utils/thermal_info.cpp
deleted file mode 100644
index c00bf63..0000000
--- a/aidl/thermal/utils/thermal_info.cpp
+++ /dev/null
@@ -1,1184 +0,0 @@
-/*
- * 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.
- */
-#include "thermal_info.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <json/reader.h>
-
-#include <cmath>
-#include <unordered_set>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-constexpr std::string_view kPowerLinkDisabledProperty("vendor.disable.thermal.powerlink");
-
-namespace {
-
-template <typename T>
-// Return false when failed parsing
-bool getTypeFromString(std::string_view str, T *out) {
- auto types = ::ndk::enum_range<T>();
- for (const auto &type : types) {
- if (::aidl::android::hardware::thermal::toString(type) == str) {
- *out = type;
- return true;
- }
- }
- return false;
-}
-
-float getFloatFromValue(const Json::Value &value) {
- if (value.isString()) {
- return std::stof(value.asString());
- } else {
- return value.asFloat();
- }
-}
-
-int getIntFromValue(const Json::Value &value) {
- if (value.isString()) {
- return (value.asString() == "max") ? std::numeric_limits<int>::max()
- : std::stoul(value.asString());
- } else {
- return value.asInt();
- }
-}
-
-bool getIntFromJsonValues(const Json::Value &values, CdevArray *out, bool inc_check,
- bool dec_check) {
- CdevArray ret;
-
- if (inc_check && dec_check) {
- LOG(ERROR) << "Cannot enable inc_check and dec_check at the same time";
- return false;
- }
-
- if (values.size() != kThrottlingSeverityCount) {
- LOG(ERROR) << "Values size is invalid";
- return false;
- } else {
- int last;
- for (Json::Value::ArrayIndex i = 0; i < kThrottlingSeverityCount; ++i) {
- ret[i] = getIntFromValue(values[i]);
- if (inc_check && ret[i] < last) {
- LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " min=" << last;
- return false;
- }
- if (dec_check && ret[i] > last) {
- LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " max=" << last;
- return false;
- }
- last = ret[i];
- LOG(INFO) << "[" << i << "]: " << ret[i];
- }
- }
-
- *out = ret;
- return true;
-}
-
-bool getFloatFromJsonValues(const Json::Value &values, ThrottlingArray *out, bool inc_check,
- bool dec_check) {
- ThrottlingArray ret;
-
- if (inc_check && dec_check) {
- LOG(ERROR) << "Cannot enable inc_check and dec_check at the same time";
- return false;
- }
-
- if (values.size() != kThrottlingSeverityCount) {
- LOG(ERROR) << "Values size is invalid";
- return false;
- } else {
- float last = std::nanf("");
- for (Json::Value::ArrayIndex i = 0; i < kThrottlingSeverityCount; ++i) {
- ret[i] = getFloatFromValue(values[i]);
- if (inc_check && !std::isnan(last) && !std::isnan(ret[i]) && ret[i] < last) {
- LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " min=" << last;
- return false;
- }
- if (dec_check && !std::isnan(last) && !std::isnan(ret[i]) && ret[i] > last) {
- LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " max=" << last;
- return false;
- }
- last = std::isnan(ret[i]) ? last : ret[i];
- LOG(INFO) << "[" << i << "]: " << ret[i];
- }
- }
-
- *out = ret;
- return true;
-}
-} // namespace
-
-bool ParseThermalConfig(std::string_view config_path, Json::Value *config) {
- std::string json_doc;
- if (!::android::base::ReadFileToString(config_path.data(), &json_doc)) {
- LOG(ERROR) << "Failed to read JSON config from " << config_path;
- return false;
- }
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
- std::string errorMessage;
- if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), config, &errorMessage)) {
- LOG(ERROR) << "Failed to parse JSON config: " << errorMessage;
- return false;
- }
- return true;
-}
-
-bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sensor,
- std::unique_ptr<VirtualSensorInfo> *virtual_sensor_info) {
- if (sensor["VirtualSensor"].empty() || !sensor["VirtualSensor"].isBool()) {
- LOG(INFO) << "Failed to read Sensor[" << name << "]'s VirtualSensor";
- return true;
- }
- bool is_virtual_sensor = sensor["VirtualSensor"].asBool();
- LOG(INFO) << "Sensor[" << name << "]'s' VirtualSensor: " << is_virtual_sensor;
- if (!is_virtual_sensor) {
- return true;
- }
- float offset = 0;
- std::vector<std::string> linked_sensors;
- std::vector<SensorFusionType> linked_sensors_type;
- std::vector<std::string> trigger_sensors;
- std::vector<float> coefficients;
- FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
-
- Json::Value values = sensor["Combination"];
- if (values.size()) {
- linked_sensors.reserve(values.size());
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- linked_sensors.emplace_back(values[j].asString());
- LOG(INFO) << "Sensor[" << name << "]'s Combination[" << j << "]: " << linked_sensors[j];
- }
- } else {
- LOG(ERROR) << "Sensor[" << name << "] has no Combination setting";
- return false;
- }
-
- values = sensor["CombinationType"];
- if (!values.size()) {
- linked_sensors_type.reserve(linked_sensors.size());
- for (size_t j = 0; j < linked_sensors.size(); ++j) {
- linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
- }
- } else if (values.size() != linked_sensors.size()) {
- LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType size";
- return false;
- } else {
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- if (values[j].asString().compare("SENSOR") == 0) {
- linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
- } else if (values[j].asString().compare("ODPM") == 0) {
- linked_sensors_type.emplace_back(SensorFusionType::ODPM);
- } else {
- LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType settings "
- << values[j].asString();
- return false;
- }
- LOG(INFO) << "Sensor[" << name << "]'s CombinationType[" << j
- << "]: " << linked_sensors_type[j];
- }
- }
-
- values = sensor["Coefficient"];
- if (values.size()) {
- coefficients.reserve(values.size());
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- coefficients.emplace_back(getFloatFromValue(values[j]));
- LOG(INFO) << "Sensor[" << name << "]'s coefficient[" << j << "]: " << coefficients[j];
- }
- } else {
- LOG(ERROR) << "Sensor[" << name << "] has no Coefficient setting";
- return false;
- }
- if (linked_sensors.size() != coefficients.size()) {
- LOG(ERROR) << "Sensor[" << name << "] has invalid Coefficient size";
- return false;
- }
- if (!sensor["Offset"].empty()) {
- offset = sensor["Offset"].asFloat();
- }
-
- values = sensor["TriggerSensor"];
- if (!values.empty()) {
- if (values.isString()) {
- trigger_sensors.emplace_back(values.asString());
- LOG(INFO) << "Sensor[" << name << "]'s TriggerSensor: " << values.asString();
- } else if (values.size()) {
- trigger_sensors.reserve(values.size());
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- if (!values[j].isString()) {
- LOG(ERROR) << name << " TriggerSensor should be an array of string";
- return false;
- }
- trigger_sensors.emplace_back(values[j].asString());
- LOG(INFO) << "Sensor[" << name << "]'s TriggerSensor[" << j
- << "]: " << trigger_sensors[j];
- }
- } else {
- LOG(ERROR) << "Sensor[" << name << "]'s TriggerSensor should be a string";
- return false;
- }
- }
-
- if (sensor["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
- formula = FormulaOption::COUNT_THRESHOLD;
- } else if (sensor["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
- formula = FormulaOption::WEIGHTED_AVG;
- } else if (sensor["Formula"].asString().compare("MAXIMUM") == 0) {
- formula = FormulaOption::MAXIMUM;
- } else if (sensor["Formula"].asString().compare("MINIMUM") == 0) {
- formula = FormulaOption::MINIMUM;
- } else {
- LOG(ERROR) << "Sensor[" << name << "]'s Formula is invalid";
- return false;
- }
- virtual_sensor_info->reset(new VirtualSensorInfo{
- linked_sensors, linked_sensors_type, coefficients, offset, trigger_sensors, formula});
- return true;
-}
-
-bool ParseBindedCdevInfo(const Json::Value &values,
- std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map,
- const bool support_pid, bool *support_hard_limit) {
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- Json::Value sub_values;
- const std::string &cdev_name = values[j]["CdevRequest"].asString();
- ThrottlingArray cdev_weight_for_pid;
- cdev_weight_for_pid.fill(NAN);
- CdevArray cdev_ceiling;
- cdev_ceiling.fill(std::numeric_limits<int>::max());
- int max_release_step = std::numeric_limits<int>::max();
- int max_throttle_step = std::numeric_limits<int>::max();
- if (support_pid) {
- if (!values[j]["CdevWeightForPID"].empty()) {
- LOG(INFO) << "Star to parse " << cdev_name << "'s CdevWeightForPID";
- if (!getFloatFromJsonValues(values[j]["CdevWeightForPID"], &cdev_weight_for_pid,
- false, false)) {
- LOG(ERROR) << "Failed to parse CdevWeightForPID";
- binded_cdev_info_map->clear();
- return false;
- }
- }
- if (!values[j]["CdevCeiling"].empty()) {
- LOG(INFO) << "Start to parse CdevCeiling: " << cdev_name;
- if (!getIntFromJsonValues(values[j]["CdevCeiling"], &cdev_ceiling, false, false)) {
- LOG(ERROR) << "Failed to parse CdevCeiling";
- binded_cdev_info_map->clear();
- return false;
- }
- }
-
- if (!values[j]["MaxReleaseStep"].empty()) {
- max_release_step = getIntFromValue(values[j]["MaxReleaseStep"]);
- if (max_release_step < 0) {
- LOG(ERROR) << cdev_name << " MaxReleaseStep: " << max_release_step;
- binded_cdev_info_map->clear();
- return false;
- } else {
- LOG(INFO) << cdev_name << " MaxReleaseStep: " << max_release_step;
- }
- }
- if (!values[j]["MaxThrottleStep"].empty()) {
- max_throttle_step = getIntFromValue(values[j]["MaxThrottleStep"]);
- if (max_throttle_step < 0) {
- LOG(ERROR) << cdev_name << " MaxThrottleStep: " << max_throttle_step;
- binded_cdev_info_map->clear();
- return false;
- } else {
- LOG(INFO) << cdev_name << " MaxThrottleStep: " << max_throttle_step;
- }
- }
- }
- CdevArray limit_info;
- limit_info.fill(0);
- ThrottlingArray power_thresholds;
- power_thresholds.fill(NAN);
- ReleaseLogic release_logic = ReleaseLogic::NONE;
-
- sub_values = values[j]["LimitInfo"];
- if (sub_values.size()) {
- LOG(INFO) << "Start to parse LimitInfo: " << cdev_name;
- if (!getIntFromJsonValues(sub_values, &limit_info, false, false)) {
- LOG(ERROR) << "Failed to parse LimitInfo";
- binded_cdev_info_map->clear();
- return false;
- }
- *support_hard_limit = true;
- }
- // Parse linked power info
- std::string power_rail;
- bool high_power_check = false;
- bool throttling_with_power_link = false;
- CdevArray cdev_floor_with_power_link;
- cdev_floor_with_power_link.fill(0);
-
- const bool power_link_disabled =
- ::android::base::GetBoolProperty(kPowerLinkDisabledProperty.data(), false);
- if (!power_link_disabled) {
- power_rail = values[j]["BindedPowerRail"].asString();
-
- if (values[j]["HighPowerCheck"].asBool()) {
- high_power_check = true;
- }
- LOG(INFO) << "Highpowercheck: " << std::boolalpha << high_power_check;
-
- if (values[j]["ThrottlingWithPowerLink"].asBool()) {
- throttling_with_power_link = true;
- }
- LOG(INFO) << "ThrottlingwithPowerLink: " << std::boolalpha
- << throttling_with_power_link;
-
- sub_values = values[j]["CdevFloorWithPowerLink"];
- if (sub_values.size()) {
- LOG(INFO) << "Start to parse " << cdev_name << "'s CdevFloorWithPowerLink";
- if (!getIntFromJsonValues(sub_values, &cdev_floor_with_power_link, false, false)) {
- LOG(ERROR) << "Failed to parse CdevFloor";
- binded_cdev_info_map->clear();
- return false;
- }
- }
- sub_values = values[j]["PowerThreshold"];
- if (sub_values.size()) {
- LOG(INFO) << "Start to parse " << cdev_name << "'s PowerThreshold";
- if (!getFloatFromJsonValues(sub_values, &power_thresholds, false, false)) {
- LOG(ERROR) << "Failed to parse power thresholds";
- binded_cdev_info_map->clear();
- return false;
- }
- if (values[j]["ReleaseLogic"].asString() == "INCREASE") {
- release_logic = ReleaseLogic::INCREASE;
- LOG(INFO) << "Release logic: INCREASE";
- } else if (values[j]["ReleaseLogic"].asString() == "DECREASE") {
- release_logic = ReleaseLogic::DECREASE;
- LOG(INFO) << "Release logic: DECREASE";
- } else if (values[j]["ReleaseLogic"].asString() == "STEPWISE") {
- release_logic = ReleaseLogic::STEPWISE;
- LOG(INFO) << "Release logic: STEPWISE";
- } else if (values[j]["ReleaseLogic"].asString() == "RELEASE_TO_FLOOR") {
- release_logic = ReleaseLogic::RELEASE_TO_FLOOR;
- LOG(INFO) << "Release logic: RELEASE_TO_FLOOR";
- } else {
- LOG(ERROR) << "Release logic is invalid";
- binded_cdev_info_map->clear();
- return false;
- }
- }
- }
-
- (*binded_cdev_info_map)[cdev_name] = {
- .limit_info = limit_info,
- .power_thresholds = power_thresholds,
- .release_logic = release_logic,
- .high_power_check = high_power_check,
- .throttling_with_power_link = throttling_with_power_link,
- .cdev_weight_for_pid = cdev_weight_for_pid,
- .cdev_ceiling = cdev_ceiling,
- .max_release_step = max_release_step,
- .max_throttle_step = max_throttle_step,
- .cdev_floor_with_power_link = cdev_floor_with_power_link,
- .power_rail = power_rail,
- };
- }
- return true;
-}
-
-bool ParseSensorThrottlingInfo(const std::string_view name, const Json::Value &sensor,
- bool *support_throttling,
- std::shared_ptr<ThrottlingInfo> *throttling_info) {
- std::array<float, kThrottlingSeverityCount> k_po;
- k_po.fill(0.0);
- std::array<float, kThrottlingSeverityCount> k_pu;
- k_pu.fill(0.0);
- std::array<float, kThrottlingSeverityCount> k_i;
- k_i.fill(0.0);
- std::array<float, kThrottlingSeverityCount> k_d;
- k_d.fill(0.0);
- std::array<float, kThrottlingSeverityCount> i_max;
- i_max.fill(NAN);
- std::array<float, kThrottlingSeverityCount> max_alloc_power;
- max_alloc_power.fill(NAN);
- std::array<float, kThrottlingSeverityCount> min_alloc_power;
- min_alloc_power.fill(NAN);
- std::array<float, kThrottlingSeverityCount> s_power;
- s_power.fill(NAN);
- std::array<float, kThrottlingSeverityCount> i_cutoff;
- i_cutoff.fill(NAN);
- float i_default = 0.0;
- int tran_cycle = 0;
- bool support_pid = false;
- bool support_hard_limit = false;
-
- // Parse PID parameters
- if (!sensor["PIDInfo"].empty()) {
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s K_Po";
- if (sensor["PIDInfo"]["K_Po"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["K_Po"], &k_po, false, false)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Po";
- return false;
- }
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s K_Pu";
- if (sensor["PIDInfo"]["K_Pu"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["K_Pu"], &k_pu, false, false)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Pu";
- return false;
- }
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s K_I";
- if (sensor["PIDInfo"]["K_I"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["K_I"], &k_i, false, false)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_I";
- return false;
- }
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s K_D";
- if (sensor["PIDInfo"]["K_D"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["K_D"], &k_d, false, false)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_D";
- return false;
- }
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s I_Max";
- if (sensor["PIDInfo"]["I_Max"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["I_Max"], &i_max, false, false)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Max";
- return false;
- }
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s MaxAllocPower";
- if (sensor["PIDInfo"]["MaxAllocPower"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["MaxAllocPower"], &max_alloc_power, false,
- true)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MaxAllocPower";
- return false;
- }
- LOG(INFO) << "Start to parse"
- << " Sensor[" << name << "]'s MinAllocPower";
- if (sensor["PIDInfo"]["MinAllocPower"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["MinAllocPower"], &min_alloc_power, false,
- true)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MinAllocPower";
- return false;
- }
- LOG(INFO) << "Start to parse Sensor[" << name << "]'s S_Power";
- if (sensor["PIDInfo"]["S_Power"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["S_Power"], &s_power, false, true)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse S_Power";
- return false;
- }
- LOG(INFO) << "Start to parse Sensor[" << name << "]'s I_Cutoff";
- if (sensor["PIDInfo"]["I_Cutoff"].empty() ||
- !getFloatFromJsonValues(sensor["PIDInfo"]["I_Cutoff"], &i_cutoff, false, false)) {
- LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Cutoff";
- return false;
- }
- i_default = getFloatFromValue(sensor["PIDInfo"]["I_Default"]);
- LOG(INFO) << "Sensor[" << name << "]'s I_Default: " << i_default;
-
- tran_cycle = getFloatFromValue(sensor["PIDInfo"]["TranCycle"]);
- LOG(INFO) << "Sensor[" << name << "]'s TranCycle: " << tran_cycle;
-
- // Confirm we have at least one valid PID combination
- bool valid_pid_combination = false;
- for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
- if (!std::isnan(s_power[j])) {
- if (std::isnan(k_po[j]) || std::isnan(k_pu[j]) || std::isnan(k_i[j]) ||
- std::isnan(k_d[j]) || std::isnan(i_max[j]) || std::isnan(max_alloc_power[j]) ||
- std::isnan(min_alloc_power[j]) || std::isnan(i_cutoff[j])) {
- valid_pid_combination = false;
- break;
- } else {
- valid_pid_combination = true;
- }
- }
- }
- if (!valid_pid_combination) {
- LOG(ERROR) << "Sensor[" << name << "]: Invalid PID parameters combinations";
- return false;
- } else {
- support_pid = true;
- }
- }
-
- // Parse binded cooling device
- std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
- if (!ParseBindedCdevInfo(sensor["BindedCdevInfo"], &binded_cdev_info_map, support_pid,
- &support_hard_limit)) {
- LOG(ERROR) << "Sensor[" << name << "]: failed to parse BindedCdevInfo";
- return false;
- }
-
- std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
- Json::Value values = sensor["ExcludedPowerInfo"];
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- Json::Value sub_values;
- const std::string &power_rail = values[j]["PowerRail"].asString();
- if (power_rail.empty()) {
- LOG(ERROR) << "Sensor[" << name << "] failed to parse excluded PowerRail";
- return false;
- }
- ThrottlingArray power_weight;
- power_weight.fill(1);
- if (!values[j]["PowerWeight"].empty()) {
- LOG(INFO) << "Sensor[" << name << "]: Start to parse " << power_rail
- << "'s PowerWeight";
- if (!getFloatFromJsonValues(values[j]["PowerWeight"], &power_weight, false, false)) {
- LOG(ERROR) << "Failed to parse PowerWeight";
- return false;
- }
- }
- excluded_power_info_map[power_rail] = power_weight;
- }
- throttling_info->reset(new ThrottlingInfo{
- k_po, k_pu, k_i, k_d, i_max, max_alloc_power, min_alloc_power, s_power, i_cutoff,
- i_default, tran_cycle, excluded_power_info_map, binded_cdev_info_map});
- *support_throttling = support_pid | support_hard_limit;
- return true;
-}
-
-bool ParseSensorInfo(const Json::Value &config,
- std::unordered_map<std::string, SensorInfo> *sensors_parsed) {
- Json::Value sensors = config["Sensors"];
- std::size_t total_parsed = 0;
- std::unordered_set<std::string> sensors_name_parsed;
-
- for (Json::Value::ArrayIndex i = 0; i < sensors.size(); ++i) {
- const std::string &name = sensors[i]["Name"].asString();
- LOG(INFO) << "Sensor[" << i << "]'s Name: " << name;
- if (name.empty()) {
- LOG(ERROR) << "Failed to read Sensor[" << i << "]'s Name";
- sensors_parsed->clear();
- return false;
- }
-
- auto result = sensors_name_parsed.insert(name);
- if (!result.second) {
- LOG(ERROR) << "Duplicate Sensor[" << i << "]'s Name";
- sensors_parsed->clear();
- return false;
- }
-
- std::string sensor_type_str = sensors[i]["Type"].asString();
- LOG(INFO) << "Sensor[" << name << "]'s Type: " << sensor_type_str;
- TemperatureType sensor_type;
-
- if (!getTypeFromString(sensor_type_str, &sensor_type)) {
- LOG(ERROR) << "Invalid Sensor[" << name << "]'s Type: " << sensor_type_str;
- sensors_parsed->clear();
- return false;
- }
-
- bool send_cb = false;
- if (!sensors[i]["Monitor"].empty() && sensors[i]["Monitor"].isBool()) {
- send_cb = sensors[i]["Monitor"].asBool();
- } else if (!sensors[i]["SendCallback"].empty() && sensors[i]["SendCallback"].isBool()) {
- send_cb = sensors[i]["SendCallback"].asBool();
- }
- LOG(INFO) << "Sensor[" << name << "]'s SendCallback: " << std::boolalpha << send_cb
- << std::noboolalpha;
-
- bool send_powerhint = false;
- if (sensors[i]["SendPowerHint"].empty() || !sensors[i]["SendPowerHint"].isBool()) {
- LOG(INFO) << "Failed to read Sensor[" << name << "]'s SendPowerHint, set to 'false'";
- } else if (sensors[i]["SendPowerHint"].asBool()) {
- send_powerhint = true;
- }
- LOG(INFO) << "Sensor[" << name << "]'s SendPowerHint: " << std::boolalpha << send_powerhint
- << std::noboolalpha;
-
- bool is_hidden = false;
- if (sensors[i]["Hidden"].empty() || !sensors[i]["Hidden"].isBool()) {
- LOG(INFO) << "Failed to read Sensor[" << name << "]'s Hidden, set to 'false'";
- } else if (sensors[i]["Hidden"].asBool()) {
- is_hidden = true;
- }
- LOG(INFO) << "Sensor[" << name << "]'s Hidden: " << std::boolalpha << is_hidden
- << std::noboolalpha;
-
- std::array<float, kThrottlingSeverityCount> hot_thresholds;
- hot_thresholds.fill(NAN);
- std::array<float, kThrottlingSeverityCount> cold_thresholds;
- cold_thresholds.fill(NAN);
- std::array<float, kThrottlingSeverityCount> hot_hysteresis;
- hot_hysteresis.fill(0.0);
- std::array<float, kThrottlingSeverityCount> cold_hysteresis;
- cold_hysteresis.fill(0.0);
-
- Json::Value values = sensors[i]["HotThreshold"];
- if (!values.size()) {
- LOG(INFO) << "Sensor[" << name << "]'s HotThreshold, default all to NAN";
- } else if (values.size() != kThrottlingSeverityCount) {
- LOG(ERROR) << "Invalid Sensor[" << name << "]'s HotThreshold count:" << values.size();
- sensors_parsed->clear();
- return false;
- } else {
- float min = std::numeric_limits<float>::min();
- for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
- hot_thresholds[j] = getFloatFromValue(values[j]);
- if (!std::isnan(hot_thresholds[j])) {
- if (hot_thresholds[j] < min) {
- LOG(ERROR) << "Invalid "
- << "Sensor[" << name << "]'s HotThreshold[j" << j
- << "]: " << hot_thresholds[j] << " < " << min;
- sensors_parsed->clear();
- return false;
- }
- min = hot_thresholds[j];
- }
- LOG(INFO) << "Sensor[" << name << "]'s HotThreshold[" << j
- << "]: " << hot_thresholds[j];
- }
- }
-
- values = sensors[i]["HotHysteresis"];
- if (!values.size()) {
- LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis, default all to 0.0";
- } else if (values.size() != kThrottlingSeverityCount) {
- LOG(ERROR) << "Invalid Sensor[" << name << "]'s HotHysteresis, count:" << values.size();
- sensors_parsed->clear();
- return false;
- } else {
- for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
- hot_hysteresis[j] = getFloatFromValue(values[j]);
- if (std::isnan(hot_hysteresis[j])) {
- LOG(ERROR) << "Invalid Sensor[" << name
- << "]'s HotHysteresis: " << hot_hysteresis[j];
- sensors_parsed->clear();
- return false;
- }
- LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis[" << j
- << "]: " << hot_hysteresis[j];
- }
- }
-
- for (Json::Value::ArrayIndex j = 0; j < (kThrottlingSeverityCount - 1); ++j) {
- if (std::isnan(hot_thresholds[j])) {
- continue;
- }
- for (auto k = j + 1; k < kThrottlingSeverityCount; ++k) {
- if (std::isnan(hot_thresholds[k])) {
- continue;
- } else if (hot_thresholds[j] > (hot_thresholds[k] - hot_hysteresis[k])) {
- LOG(ERROR) << "Sensor[" << name << "]'s hot threshold " << j
- << " is overlapped";
- sensors_parsed->clear();
- return false;
- } else {
- break;
- }
- }
- }
-
- values = sensors[i]["ColdThreshold"];
- if (!values.size()) {
- LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold, default all to NAN";
- } else if (values.size() != kThrottlingSeverityCount) {
- LOG(ERROR) << "Invalid Sensor[" << name << "]'s ColdThreshold count:" << values.size();
- sensors_parsed->clear();
- return false;
- } else {
- float max = std::numeric_limits<float>::max();
- for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
- cold_thresholds[j] = getFloatFromValue(values[j]);
- if (!std::isnan(cold_thresholds[j])) {
- if (cold_thresholds[j] > max) {
- LOG(ERROR) << "Invalid "
- << "Sensor[" << name << "]'s ColdThreshold[j" << j
- << "]: " << cold_thresholds[j] << " > " << max;
- sensors_parsed->clear();
- return false;
- }
- max = cold_thresholds[j];
- }
- LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold[" << j
- << "]: " << cold_thresholds[j];
- }
- }
-
- values = sensors[i]["ColdHysteresis"];
- if (!values.size()) {
- LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis, default all to 0.0";
- } else if (values.size() != kThrottlingSeverityCount) {
- LOG(ERROR) << "Invalid Sensor[" << name << "]'s ColdHysteresis count:" << values.size();
- sensors_parsed->clear();
- return false;
- } else {
- for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
- cold_hysteresis[j] = getFloatFromValue(values[j]);
- if (std::isnan(cold_hysteresis[j])) {
- LOG(ERROR) << "Invalid Sensor[" << name
- << "]'s ColdHysteresis: " << cold_hysteresis[j];
- sensors_parsed->clear();
- return false;
- }
- LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis[" << j
- << "]: " << cold_hysteresis[j];
- }
- }
-
- for (Json::Value::ArrayIndex j = 0; j < (kThrottlingSeverityCount - 1); ++j) {
- if (std::isnan(cold_thresholds[j])) {
- continue;
- }
- for (auto k = j + 1; k < kThrottlingSeverityCount; ++k) {
- if (std::isnan(cold_thresholds[k])) {
- continue;
- } else if (cold_thresholds[j] < (cold_thresholds[k] + cold_hysteresis[k])) {
- LOG(ERROR) << "Sensor[" << name << "]'s cold threshold " << j
- << " is overlapped";
- sensors_parsed->clear();
- return false;
- } else {
- break;
- }
- }
- }
-
- std::string temp_path;
- if (!sensors[i]["TempPath"].empty()) {
- temp_path = sensors[i]["TempPath"].asString();
- LOG(INFO) << "Sensor[" << name << "]'s TempPath: " << temp_path;
- }
-
- float vr_threshold = NAN;
- if (!sensors[i]["VrThreshold"].empty()) {
- vr_threshold = getFloatFromValue(sensors[i]["VrThreshold"]);
- LOG(INFO) << "Sensor[" << name << "]'s VrThreshold: " << vr_threshold;
- }
- float multiplier = sensors[i]["Multiplier"].asFloat();
- LOG(INFO) << "Sensor[" << name << "]'s Multiplier: " << multiplier;
-
- std::chrono::milliseconds polling_delay = kUeventPollTimeoutMs;
- if (!sensors[i]["PollingDelay"].empty()) {
- const auto value = getIntFromValue(sensors[i]["PollingDelay"]);
- polling_delay = (value > 0) ? std::chrono::milliseconds(value)
- : std::chrono::milliseconds::max();
- }
- LOG(INFO) << "Sensor[" << name << "]'s Polling delay: " << polling_delay.count();
-
- std::chrono::milliseconds passive_delay = kMinPollIntervalMs;
- if (!sensors[i]["PassiveDelay"].empty()) {
- const auto value = getIntFromValue(sensors[i]["PassiveDelay"]);
- passive_delay = (value > 0) ? std::chrono::milliseconds(value)
- : std::chrono::milliseconds::max();
- }
- LOG(INFO) << "Sensor[" << name << "]'s Passive delay: " << passive_delay.count();
-
- std::chrono::milliseconds time_resolution;
- if (sensors[i]["TimeResolution"].empty()) {
- time_resolution = kMinPollIntervalMs;
- } else {
- time_resolution =
- std::chrono::milliseconds(getIntFromValue(sensors[i]["TimeResolution"]));
- }
- LOG(INFO) << "Sensor[" << name << "]'s Time resolution: " << time_resolution.count();
-
- if (is_hidden && send_cb) {
- LOG(ERROR) << "is_hidden and send_cb cannot be enabled together";
- sensors_parsed->clear();
- return false;
- }
-
- std::unique_ptr<VirtualSensorInfo> virtual_sensor_info;
- if (!ParseVirtualSensorInfo(name, sensors[i], &virtual_sensor_info)) {
- LOG(ERROR) << "Sensor[" << name << "]: failed to parse virtual sensor info";
- sensors_parsed->clear();
- return false;
- }
-
- bool support_throttling = false; // support pid or hard limit
- std::shared_ptr<ThrottlingInfo> throttling_info;
- if (!ParseSensorThrottlingInfo(name, sensors[i], &support_throttling, &throttling_info)) {
- LOG(ERROR) << "Sensor[" << name << "]: failed to parse throttling info";
- sensors_parsed->clear();
- return false;
- }
-
- bool is_watch = (send_cb | send_powerhint | support_throttling);
- LOG(INFO) << "Sensor[" << name << "]'s is_watch: " << std::boolalpha << is_watch;
-
- (*sensors_parsed)[name] = {
- .type = sensor_type,
- .hot_thresholds = hot_thresholds,
- .cold_thresholds = cold_thresholds,
- .hot_hysteresis = hot_hysteresis,
- .cold_hysteresis = cold_hysteresis,
- .temp_path = temp_path,
- .vr_threshold = vr_threshold,
- .multiplier = multiplier,
- .polling_delay = polling_delay,
- .passive_delay = passive_delay,
- .time_resolution = time_resolution,
- .send_cb = send_cb,
- .send_powerhint = send_powerhint,
- .is_watch = is_watch,
- .is_hidden = is_hidden,
- .virtual_sensor_info = std::move(virtual_sensor_info),
- .throttling_info = std::move(throttling_info),
- };
-
- ++total_parsed;
- }
- LOG(INFO) << total_parsed << " Sensors parsed successfully";
- return true;
-}
-
-bool ParseCoolingDevice(const Json::Value &config,
- std::unordered_map<std::string, CdevInfo> *cooling_devices_parsed) {
- Json::Value cooling_devices = config["CoolingDevices"];
- std::size_t total_parsed = 0;
- std::unordered_set<std::string> cooling_devices_name_parsed;
-
- for (Json::Value::ArrayIndex i = 0; i < cooling_devices.size(); ++i) {
- const std::string &name = cooling_devices[i]["Name"].asString();
- LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name;
- if (name.empty()) {
- LOG(ERROR) << "Failed to read CoolingDevice[" << i << "]'s Name";
- cooling_devices_parsed->clear();
- return false;
- }
-
- auto result = cooling_devices_name_parsed.insert(name.data());
- if (!result.second) {
- LOG(ERROR) << "Duplicate CoolingDevice[" << i << "]'s Name";
- cooling_devices_parsed->clear();
- return false;
- }
-
- std::string cooling_device_type_str = cooling_devices[i]["Type"].asString();
- LOG(INFO) << "CoolingDevice[" << name << "]'s Type: " << cooling_device_type_str;
- CoolingType cooling_device_type;
-
- if (!getTypeFromString(cooling_device_type_str, &cooling_device_type)) {
- LOG(ERROR) << "Invalid CoolingDevice[" << name
- << "]'s Type: " << cooling_device_type_str;
- cooling_devices_parsed->clear();
- return false;
- }
-
- const std::string &read_path = cooling_devices[i]["ReadPath"].asString();
- LOG(INFO) << "Cdev Read Path: " << (read_path.empty() ? "default" : read_path);
-
- const std::string &write_path = cooling_devices[i]["WritePath"].asString();
- LOG(INFO) << "Cdev Write Path: " << (write_path.empty() ? "default" : write_path);
-
- std::vector<float> state2power;
- Json::Value values = cooling_devices[i]["State2Power"];
- if (values.size()) {
- state2power.reserve(values.size());
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- state2power.emplace_back(getFloatFromValue(values[j]));
- LOG(INFO) << "Cooling device[" << name << "]'s Power2State[" << j
- << "]: " << state2power[j];
- }
- } else {
- LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name
- << " does not support State2Power";
- }
-
- const std::string &power_rail = cooling_devices[i]["PowerRail"].asString();
- LOG(INFO) << "Cooling device power rail : " << power_rail;
-
- (*cooling_devices_parsed)[name] = {
- .type = cooling_device_type,
- .read_path = read_path,
- .write_path = write_path,
- .state2power = state2power,
- };
- ++total_parsed;
- }
- LOG(INFO) << total_parsed << " CoolingDevices parsed successfully";
- return true;
-}
-
-bool ParsePowerRailInfo(const Json::Value &config,
- std::unordered_map<std::string, PowerRailInfo> *power_rails_parsed) {
- Json::Value power_rails = config["PowerRails"];
- std::size_t total_parsed = 0;
- std::unordered_set<std::string> power_rails_name_parsed;
-
- for (Json::Value::ArrayIndex i = 0; i < power_rails.size(); ++i) {
- const std::string &name = power_rails[i]["Name"].asString();
- LOG(INFO) << "PowerRail[" << i << "]'s Name: " << name;
- if (name.empty()) {
- LOG(ERROR) << "Failed to read PowerRail[" << i << "]'s Name";
- power_rails_parsed->clear();
- return false;
- }
-
- std::string rail;
- if (power_rails[i]["Rail"].empty()) {
- rail = name;
- } else {
- rail = power_rails[i]["Rail"].asString();
- }
- LOG(INFO) << "PowerRail[" << i << "]'s Rail: " << rail;
-
- std::vector<std::string> linked_power_rails;
- std::vector<float> coefficients;
- float offset = 0;
- FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
- bool is_virtual_power_rail = false;
- Json::Value values;
- int power_sample_count = 0;
- std::chrono::milliseconds power_sample_delay;
-
- if (!power_rails[i]["VirtualRails"].empty() && power_rails[i]["VirtualRails"].isBool()) {
- is_virtual_power_rail = power_rails[i]["VirtualRails"].asBool();
- LOG(INFO) << "PowerRails[" << name << "]'s VirtualRail, set to 'true'";
- }
-
- if (is_virtual_power_rail) {
- values = power_rails[i]["Combination"];
- if (values.size()) {
- linked_power_rails.reserve(values.size());
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- linked_power_rails.emplace_back(values[j].asString());
- LOG(INFO) << "PowerRail[" << name << "]'s combination[" << j
- << "]: " << linked_power_rails[j];
- }
- } else {
- LOG(ERROR) << "PowerRails[" << name << "] has no combination for VirtualRail";
- power_rails_parsed->clear();
- return false;
- }
-
- values = power_rails[i]["Coefficient"];
- if (values.size()) {
- coefficients.reserve(values.size());
- for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- coefficients.emplace_back(getFloatFromValue(values[j]));
- LOG(INFO) << "PowerRail[" << name << "]'s coefficient[" << j
- << "]: " << coefficients[j];
- }
- } else {
- LOG(ERROR) << "PowerRails[" << name << "] has no coefficient for VirtualRail";
- power_rails_parsed->clear();
- return false;
- }
-
- if (linked_power_rails.size() != coefficients.size()) {
- LOG(ERROR) << "PowerRails[" << name
- << "]'s combination size is not matched with coefficient size";
- power_rails_parsed->clear();
- return false;
- }
-
- if (!power_rails[i]["Offset"].empty()) {
- offset = power_rails[i]["Offset"].asFloat();
- }
-
- if (linked_power_rails.size() != coefficients.size()) {
- LOG(ERROR) << "PowerRails[" << name
- << "]'s combination size is not matched with coefficient size";
- power_rails_parsed->clear();
- return false;
- }
-
- if (power_rails[i]["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
- formula = FormulaOption::COUNT_THRESHOLD;
- } else if (power_rails[i]["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
- formula = FormulaOption::WEIGHTED_AVG;
- } else if (power_rails[i]["Formula"].asString().compare("MAXIMUM") == 0) {
- formula = FormulaOption::MAXIMUM;
- } else if (power_rails[i]["Formula"].asString().compare("MINIMUM") == 0) {
- formula = FormulaOption::MINIMUM;
- } else {
- LOG(ERROR) << "PowerRails[" << name << "]'s Formula is invalid";
- power_rails_parsed->clear();
- return false;
- }
- }
-
- std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
- if (is_virtual_power_rail) {
- virtual_power_rail_info.reset(
- new VirtualPowerRailInfo{linked_power_rails, coefficients, offset, formula});
- }
-
- power_sample_count = power_rails[i]["PowerSampleCount"].asInt();
- LOG(INFO) << "Power sample Count: " << power_sample_count;
-
- if (!power_rails[i]["PowerSampleDelay"]) {
- power_sample_delay = std::chrono::milliseconds::max();
- } else {
- power_sample_delay =
- std::chrono::milliseconds(getIntFromValue(power_rails[i]["PowerSampleDelay"]));
- }
-
- (*power_rails_parsed)[name] = {
- .rail = rail,
- .power_sample_count = power_sample_count,
- .power_sample_delay = power_sample_delay,
- .virtual_power_rail_info = std::move(virtual_power_rail_info),
- };
- ++total_parsed;
- }
- LOG(INFO) << total_parsed << " PowerRails parsed successfully";
- return true;
-}
-
-template <typename T, typename U>
-bool ParseStatsInfo(const Json::Value &stats_config,
- const std::unordered_map<std::string, U> &entity_info, StatsInfo<T> *stats_info,
- T min_value) {
- if (stats_config.empty()) {
- LOG(INFO) << "No stats config";
- return true;
- }
- std::variant<bool, std::unordered_set<std::string>>
- record_by_default_threshold_all_or_name_set_ = false;
- if (stats_config["DefaultThresholdEnableAll"].empty() ||
- !stats_config["DefaultThresholdEnableAll"].isBool()) {
- LOG(INFO) << "Failed to read stats DefaultThresholdEnableAll, set to 'false'";
- } else if (stats_config["DefaultThresholdEnableAll"].asBool()) {
- record_by_default_threshold_all_or_name_set_ = true;
- }
- LOG(INFO) << "DefaultThresholdEnableAll " << std::boolalpha
- << std::get<bool>(record_by_default_threshold_all_or_name_set_) << std::noboolalpha;
-
- Json::Value values = stats_config["RecordWithDefaultThreshold"];
- if (values.size()) {
- if (std::get<bool>(record_by_default_threshold_all_or_name_set_)) {
- LOG(ERROR) << "Cannot enable record with default threshold when "
- "DefaultThresholdEnableAll true.";
- return false;
- }
- record_by_default_threshold_all_or_name_set_ = std::unordered_set<std::string>();
- for (Json::Value::ArrayIndex i = 0; i < values.size(); ++i) {
- std::string name = values[i].asString();
- if (!entity_info.count(name)) {
- LOG(ERROR) << "Unknown name [" << name << "] not present in entity_info.";
- return false;
- }
- std::get<std::unordered_set<std::string>>(record_by_default_threshold_all_or_name_set_)
- .insert(name);
- }
- } else {
- LOG(INFO) << "No stat by default threshold enabled.";
- }
-
- std::unordered_map<std::string, std::vector<ThresholdList<T>>> record_by_threshold;
- values = stats_config["RecordWithThreshold"];
- if (values.size()) {
- Json::Value threshold_values;
- for (Json::Value::ArrayIndex i = 0; i < values.size(); i++) {
- const std::string &name = values[i]["Name"].asString();
- if (!entity_info.count(name)) {
- LOG(ERROR) << "Unknown name [" << name << "] not present in entity_info.";
- return false;
- }
-
- std::optional<std::string> logging_name;
- if (!values[i]["LoggingName"].empty()) {
- logging_name = values[i]["LoggingName"].asString();
- LOG(INFO) << "For [" << name << "]"
- << ", stats logging name is [" << logging_name.value() << "]";
- }
-
- LOG(INFO) << "Start to parse stats threshold for [" << name << "]";
- threshold_values = values[i]["Thresholds"];
- if (threshold_values.empty()) {
- LOG(ERROR) << "Empty stats threshold not valid.";
- return false;
- }
- const auto &threshold_values_count = threshold_values.size();
- if (threshold_values_count > kMaxStatsThresholdCount) {
- LOG(ERROR) << "Number of stats threshold " << threshold_values_count
- << " greater than max " << kMaxStatsThresholdCount;
- return false;
- }
- std::vector<T> stats_threshold(threshold_values_count);
- T prev_value = min_value;
- LOG(INFO) << "Thresholds:";
- for (Json::Value::ArrayIndex i = 0; i < threshold_values_count; ++i) {
- stats_threshold[i] = std::is_floating_point_v<T>
- ? getFloatFromValue(threshold_values[i])
- : getIntFromValue(threshold_values[i]);
- if (stats_threshold[i] <= prev_value) {
- LOG(ERROR) << "Invalid array[" << i << "]" << stats_threshold[i]
- << " is <=" << prev_value;
- return false;
- }
- prev_value = stats_threshold[i];
- LOG(INFO) << "[" << i << "]: " << stats_threshold[i];
- }
- record_by_threshold[name].emplace_back(logging_name, stats_threshold);
- }
- } else {
- LOG(INFO) << "No stat by threshold enabled.";
- }
-
- (*stats_info) = {.record_by_default_threshold_all_or_name_set_ =
- record_by_default_threshold_all_or_name_set_,
- .record_by_threshold = record_by_threshold};
- return true;
-}
-
-bool ParseStatsConfig(const Json::Value &config,
- const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
- const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_,
- StatsConfig *stats_config_parsed) {
- Json::Value stats_config = config["Stats"];
-
- if (stats_config.empty()) {
- LOG(INFO) << "No Stats Config present.";
- return true;
- }
-
- LOG(INFO) << "Parse Stats Config for Sensor Temp.";
- // Parse sensor stats config
- if (!ParseStatsInfo(stats_config["Sensors"], sensor_info_map_,
- &stats_config_parsed->sensor_stats_info,
- std::numeric_limits<float>::lowest())) {
- LOG(ERROR) << "Failed to parse sensor temp stats info.";
- stats_config_parsed->clear();
- return false;
- }
-
- // Parse cooling device user vote
- if (stats_config["CoolingDevices"].empty()) {
- LOG(INFO) << "No cooling device stats present.";
- return true;
- }
-
- LOG(INFO) << "Parse Stats Config for Sensor CDev Request.";
- if (!ParseStatsInfo(stats_config["CoolingDevices"]["RecordVotePerSensor"],
- cooling_device_info_map_, &stats_config_parsed->cooling_device_request_info,
- -1)) {
- LOG(ERROR) << "Failed to parse cooling device user vote stats info.";
- stats_config_parsed->clear();
- return false;
- }
- return true;
-}
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_info.h b/aidl/thermal/utils/thermal_info.h
deleted file mode 100644
index 5b2e8b8..0000000
--- a/aidl/thermal/utils/thermal_info.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/thermal/CoolingType.h>
-#include <aidl/android/hardware/thermal/TemperatureType.h>
-#include <aidl/android/hardware/thermal/ThrottlingSeverity.h>
-#include <json/value.h>
-
-#include <chrono>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <variant>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-constexpr size_t kThrottlingSeverityCount =
- std::distance(::ndk::enum_range<ThrottlingSeverity>().begin(),
- ::ndk::enum_range<ThrottlingSeverity>().end());
-using ThrottlingArray = std::array<float, static_cast<size_t>(kThrottlingSeverityCount)>;
-using CdevArray = std::array<int, static_cast<size_t>(kThrottlingSeverityCount)>;
-constexpr std::chrono::milliseconds kMinPollIntervalMs = std::chrono::milliseconds(2000);
-constexpr std::chrono::milliseconds kUeventPollTimeoutMs = std::chrono::milliseconds(300000);
-// Max number of time_in_state buckets is 20 in atoms
-// VendorSensorCoolingDeviceStats, VendorTempResidencyStats
-constexpr int kMaxStatsResidencyCount = 20;
-constexpr int kMaxStatsThresholdCount = kMaxStatsResidencyCount - 1;
-
-enum FormulaOption : uint32_t {
- COUNT_THRESHOLD = 0,
- WEIGHTED_AVG,
- MAXIMUM,
- MINIMUM,
-};
-
-template <typename T>
-struct ThresholdList {
- std::optional<std::string> logging_name;
- std::vector<T> thresholds;
- explicit ThresholdList(std::optional<std::string> logging_name, std::vector<T> thresholds)
- : logging_name(logging_name), thresholds(thresholds) {}
-
- ThresholdList() = default;
- ThresholdList(const ThresholdList &) = default;
- ThresholdList &operator=(const ThresholdList &) = default;
- ThresholdList(ThresholdList &&) = default;
- ThresholdList &operator=(ThresholdList &&) = default;
- ~ThresholdList() = default;
-};
-
-template <typename T>
-struct StatsInfo {
- // if bool, record all or none depending on flag
- // if set, check name present in set
- std::variant<bool, std::unordered_set<std::string> >
- record_by_default_threshold_all_or_name_set_;
- // map name to list of thresholds
- std::unordered_map<std::string, std::vector<ThresholdList<T> > > record_by_threshold;
- void clear() {
- record_by_default_threshold_all_or_name_set_ = false;
- record_by_threshold.clear();
- }
-};
-
-struct StatsConfig {
- StatsInfo<float> sensor_stats_info;
- StatsInfo<int> cooling_device_request_info;
- void clear() {
- sensor_stats_info.clear();
- cooling_device_request_info.clear();
- }
-};
-
-enum SensorFusionType : uint32_t {
- SENSOR = 0,
- ODPM,
-};
-
-struct VirtualSensorInfo {
- std::vector<std::string> linked_sensors;
- std::vector<SensorFusionType> linked_sensors_type;
- std::vector<float> coefficients;
- float offset;
- std::vector<std::string> trigger_sensors;
- FormulaOption formula;
-};
-
-struct VirtualPowerRailInfo {
- std::vector<std::string> linked_power_rails;
- std::vector<float> coefficients;
- float offset;
- FormulaOption formula;
-};
-
-// The method when the ODPM power is lower than threshold
-enum ReleaseLogic : uint32_t {
- INCREASE = 0, // Increase throttling by step
- DECREASE, // Decrease throttling by step
- STEPWISE, // Support both increase and decrease logix
- RELEASE_TO_FLOOR, // Release throttling to floor directly
- NONE,
-};
-
-struct BindedCdevInfo {
- CdevArray limit_info;
- ThrottlingArray power_thresholds;
- ReleaseLogic release_logic;
- ThrottlingArray cdev_weight_for_pid;
- CdevArray cdev_ceiling;
- int max_release_step;
- int max_throttle_step;
- CdevArray cdev_floor_with_power_link;
- std::string power_rail;
- // The flag for activate release logic when power is higher than power threshold
- bool high_power_check;
- // The flag for only triggering throttling until all power samples are collected
- bool throttling_with_power_link;
-};
-
-struct ThrottlingInfo {
- ThrottlingArray k_po;
- ThrottlingArray k_pu;
- ThrottlingArray k_i;
- ThrottlingArray k_d;
- ThrottlingArray i_max;
- ThrottlingArray max_alloc_power;
- ThrottlingArray min_alloc_power;
- ThrottlingArray s_power;
- ThrottlingArray i_cutoff;
- float i_default;
- int tran_cycle;
- std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
- std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
-};
-
-struct SensorInfo {
- TemperatureType type;
- ThrottlingArray hot_thresholds;
- ThrottlingArray cold_thresholds;
- ThrottlingArray hot_hysteresis;
- ThrottlingArray cold_hysteresis;
- std::string temp_path;
- float vr_threshold;
- float multiplier;
- std::chrono::milliseconds polling_delay;
- std::chrono::milliseconds passive_delay;
- std::chrono::milliseconds time_resolution;
- bool send_cb;
- bool send_powerhint;
- bool is_watch;
- bool is_hidden;
- std::unique_ptr<VirtualSensorInfo> virtual_sensor_info;
- std::shared_ptr<ThrottlingInfo> throttling_info;
-};
-
-struct CdevInfo {
- CoolingType type;
- std::string read_path;
- std::string write_path;
- std::vector<float> state2power;
- int max_state;
-};
-
-struct PowerRailInfo {
- std::string rail;
- int power_sample_count;
- std::chrono::milliseconds power_sample_delay;
- std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
-};
-
-bool ParseThermalConfig(std::string_view config_path, Json::Value *config);
-bool ParseSensorInfo(const Json::Value &config,
- std::unordered_map<std::string, SensorInfo> *sensors_parsed);
-bool ParseCoolingDevice(const Json::Value &config,
- std::unordered_map<std::string, CdevInfo> *cooling_device_parsed);
-bool ParsePowerRailInfo(const Json::Value &config,
- std::unordered_map<std::string, PowerRailInfo> *power_rail_parsed);
-bool ParseStatsConfig(const Json::Value &config,
- const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
- const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_,
- StatsConfig *stats_config);
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_throttling.cpp b/aidl/thermal/utils/thermal_throttling.cpp
deleted file mode 100644
index d90ed9b..0000000
--- a/aidl/thermal/utils/thermal_throttling.cpp
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- * 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
diff --git a/aidl/thermal/utils/thermal_throttling.h b/aidl/thermal/utils/thermal_throttling.h
deleted file mode 100644
index 01e9e60..0000000
--- a/aidl/thermal/utils/thermal_throttling.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <aidl/android/hardware/thermal/Temperature.h>
-
-#include <queue>
-#include <set>
-#include <shared_mutex>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-#include "power_files.h"
-#include "thermal_info.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-struct ThermalThrottlingStatus {
- std::unordered_map<std::string, int> pid_power_budget_map;
- std::unordered_map<std::string, int> pid_cdev_request_map;
- std::unordered_map<std::string, int> hardlimit_cdev_request_map;
- std::unordered_map<std::string, int> throttling_release_map;
- std::unordered_map<std::string, int> cdev_status_map;
- float prev_err;
- float i_budget;
- float prev_target;
- float prev_power_budget;
- float budget_transient;
- int tran_cycle;
-};
-
-// Return the control temp target of PID algorithm
-size_t getTargetStateOfPID(const SensorInfo &sensor_info, const ThrottlingSeverity curr_severity);
-
-// A helper class for conducting thermal throttling
-class ThermalThrottling {
- public:
- ThermalThrottling() = default;
- ~ThermalThrottling() = default;
- // Disallow copy and assign.
- ThermalThrottling(const ThermalThrottling &) = delete;
- void operator=(const ThermalThrottling &) = delete;
-
- // Clear throttling data
- void clearThrottlingData(std::string_view sensor_name, const SensorInfo &sensor_info);
- // Register map for throttling algo
- bool registerThermalThrottling(
- std::string_view sensor_name, const std::shared_ptr<ThrottlingInfo> &throttling_info,
- const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map);
- // Register map for throttling release algo
- bool registerThrottlingReleaseToWatch(std::string_view sensor_name, std::string_view cdev_name,
- const BindedCdevInfo &binded_cdev_info);
- // Get throttling status map
- const std::unordered_map<std::string, ThermalThrottlingStatus> &GetThermalThrottlingStatusMap()
- const {
- std::shared_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
- return thermal_throttling_status_map_;
- }
- // Update thermal throttling request for the specific sensor
- void 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);
-
- // Compute the throttling target from all the sensors' request
- void computeCoolingDevicesRequest(std::string_view sensor_name, const SensorInfo &sensor_info,
- const ThrottlingSeverity curr_severity,
- std::vector<std::string> *cooling_devices_to_update);
- // Get the aggregated (from all sensor) max request for a cooling device
- bool getCdevMaxRequest(std::string_view cdev_name, int *max_state);
-
- private:
- // PID algo - get the total power budget
- float updatePowerBudget(const Temperature &temp, const SensorInfo &sensor_info,
- std::chrono::milliseconds time_elapsed_ms,
- ThrottlingSeverity curr_severity);
-
- // PID algo - return the power number from excluded power rail list
- float 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);
-
- // PID algo - allocate the power to target CDEV according to the ODPM
- bool 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);
- // PID algo - map the target throttling state according to the power budget
- void updateCdevRequestByPower(
- std::string sensor_name,
- const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map);
- // Hard limit algo - assign the throttling state according to the severity
- void updateCdevRequestBySeverity(std::string_view sensor_name, const SensorInfo &sensor_info,
- ThrottlingSeverity curr_severity);
- // Throttling release algo - decide release step according to the predefined power threshold,
- // return false if the throttling release is not registered in thermal config
- bool 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);
- // Update the cooling device request set for new request and notify the caller if there is
- // change in max_request for the cooling device.
- bool updateCdevMaxRequestAndNotifyIfChange(std::string_view cdev_name, int cur_request,
- int new_request);
- mutable std::shared_mutex thermal_throttling_status_map_mutex_;
- // Thermal throttling status from each sensor
- std::unordered_map<std::string, ThermalThrottlingStatus> thermal_throttling_status_map_;
- std::shared_mutex cdev_all_request_map_mutex_;
- // Set of all request for a cooling device from each sensor
- std::unordered_map<std::string, std::multiset<int, std::greater<int>>> cdev_all_request_map_;
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_watcher.cpp b/aidl/thermal/utils/thermal_watcher.cpp
deleted file mode 100644
index d8bc92e..0000000
--- a/aidl/thermal/utils/thermal_watcher.cpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * 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_watcher.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <cutils/uevent.h>
-#include <dirent.h>
-#include <linux/netlink.h>
-#include <linux/thermal.h>
-#include <sys/inotify.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <utils/Trace.h>
-
-#include <chrono>
-#include <fstream>
-
-#include "../thermal-helper.h"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-namespace {
-
-static int nlErrorHandle(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
- int *ret = reinterpret_cast<int *>(arg);
- *ret = err->error;
- LOG(ERROR) << __func__ << "nl_groups: " << nla->nl_groups << ", nl_pid: " << nla->nl_pid;
-
- return NL_STOP;
-}
-
-static int nlFinishHandle(struct nl_msg *msg, void *arg) {
- int *ret = reinterpret_cast<int *>(arg);
- *ret = 1;
- struct nlmsghdr *nlh = nlmsg_hdr(msg);
-
- LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
-
- return NL_OK;
-}
-
-static int nlAckHandle(struct nl_msg *msg, void *arg) {
- int *ret = reinterpret_cast<int *>(arg);
- *ret = 1;
- struct nlmsghdr *nlh = nlmsg_hdr(msg);
-
- LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
-
- return NL_OK;
-}
-
-static int nlSeqCheckHandle(struct nl_msg *msg, void *arg) {
- int *ret = reinterpret_cast<int *>(arg);
- *ret = 1;
- struct nlmsghdr *nlh = nlmsg_hdr(msg);
-
- LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
-
- return NL_OK;
-}
-
-struct HandlerArgs {
- const char *group;
- int id;
-};
-
-static int nlSendMsg(struct nl_sock *sock, struct nl_msg *msg,
- int (*rx_handler)(struct nl_msg *, void *), void *data) {
- int err, done = 0;
-
- std::unique_ptr<nl_cb, decltype(&nl_cb_put)> cb(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
-
- err = nl_send_auto_complete(sock, msg);
- if (err < 0)
- return err;
-
- err = 0;
- nl_cb_err(cb.get(), NL_CB_CUSTOM, nlErrorHandle, &err);
- nl_cb_set(cb.get(), NL_CB_FINISH, NL_CB_CUSTOM, nlFinishHandle, &done);
- nl_cb_set(cb.get(), NL_CB_ACK, NL_CB_CUSTOM, nlAckHandle, &done);
-
- if (rx_handler != NULL)
- nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data);
-
- while (err == 0 && done == 0) nl_recvmsgs(sock, cb.get());
-
- return err;
-}
-
-static int nlFamilyHandle(struct nl_msg *msg, void *arg) {
- struct HandlerArgs *grp = reinterpret_cast<struct HandlerArgs *>(arg);
- struct nlattr *tb[CTRL_ATTR_MAX + 1];
- struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *mcgrp;
- int rem_mcgrp;
-
- nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
-
- if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
- LOG(ERROR) << __func__ << "Multicast group not found";
- return -1;
- }
-
- nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
- struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
-
- nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, reinterpret_cast<nlattr *>(nla_data(mcgrp)),
- nla_len(mcgrp), NULL);
-
- if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
- continue;
-
- if (strncmp(reinterpret_cast<char *>(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])),
- grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
- continue;
-
- grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
-
- break;
- }
-
- return 0;
-}
-
-static int nlGetMulticastId(struct nl_sock *sock, const char *family, const char *group) {
- int err = 0, ctrlid;
- struct HandlerArgs grp = {
- .group = group,
- .id = -ENOENT,
- };
-
- std::unique_ptr<nl_msg, decltype(&nlmsg_free)> msg(nlmsg_alloc(), nlmsg_free);
-
- ctrlid = genl_ctrl_resolve(sock, "nlctrl");
-
- genlmsg_put(msg.get(), 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
-
- nla_put_string(msg.get(), CTRL_ATTR_FAMILY_NAME, family);
-
- err = nlSendMsg(sock, msg.get(), nlFamilyHandle, &grp);
- if (err)
- return err;
-
- err = grp.id;
- LOG(INFO) << group << " multicast_id: " << grp.id;
-
- return err;
-}
-
-static bool socketAddMembership(struct nl_sock *sock, const char *group) {
- int mcid = nlGetMulticastId(sock, THERMAL_GENL_FAMILY_NAME, group);
- if (mcid < 0) {
- LOG(ERROR) << "Failed to get multicast id: " << group;
- return false;
- }
-
- if (nl_socket_add_membership(sock, mcid)) {
- LOG(ERROR) << "Failed to add netlink socket membership: " << group;
- return false;
- }
-
- LOG(INFO) << "Added netlink socket membership: " << group;
- return true;
-}
-
-static int handleEvent(struct nl_msg *n, void *arg) {
- struct nlmsghdr *nlh = nlmsg_hdr(n);
- struct genlmsghdr *glh = genlmsg_hdr(nlh);
- struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
- int *tz_id = reinterpret_cast<int *>(arg);
-
- genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_UP) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_UP";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
- LOG(INFO) << "Thermal zone trip id: "
- << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_DOWN) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_DOWN";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
- LOG(INFO) << "Thermal zone trip id: "
- << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_GOV_CHANGE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_GOV_CHANGE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_GOV_NAME])
- LOG(INFO) << "Governor name: " << nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_CREATE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_CREATE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_TZ_NAME])
- LOG(INFO) << "Thermal zone name: " << nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_DELETE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_DELETE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_DISABLE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_DISABLE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_ENABLE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_ENABLE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_CHANGE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_CHANGE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
- LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE])
- LOG(INFO) << "Trip type: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP])
- LOG(INFO) << "Trip temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST])
- LOG(INFO) << "Trip hyst: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_ADD) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_ADD";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID])
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
- LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE])
- LOG(INFO) << "Trip type: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP])
- LOG(INFO) << "Trip temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]);
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST])
- LOG(INFO) << "Trip hyst: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_DELETE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_DELETE";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
- LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_CDEV_STATE_UPDATE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_STATE_UPDATE";
- if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
- LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
- if (attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE])
- LOG(INFO) << "Cooling device current state: "
- << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_CDEV_ADD) {
- LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_ADD";
- if (attrs[THERMAL_GENL_ATTR_CDEV_NAME])
- LOG(INFO) << "Cooling device name: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_NAME]);
- if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
- LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
- if (attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE])
- LOG(INFO) << "Cooling device max state: "
- << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]);
- }
-
- if (glh->cmd == THERMAL_GENL_EVENT_CDEV_DELETE) {
- LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_DELETE";
- if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
- LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
- }
-
- if (glh->cmd == THERMAL_GENL_SAMPLING_TEMP) {
- LOG(INFO) << "THERMAL_GENL_SAMPLING_TEMP";
- if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
- LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
- }
- if (attrs[THERMAL_GENL_ATTR_TZ_TEMP])
- LOG(INFO) << "Thermal zone temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]);
- }
-
- return 0;
-}
-
-} // namespace
-
-void ThermalWatcher::registerFilesToWatch(const std::set<std::string> &sensors_to_watch) {
- LOG(INFO) << "Uevent register file to watch...";
- monitored_sensors_.insert(sensors_to_watch.begin(), sensors_to_watch.end());
-
- uevent_fd_.reset((TEMP_FAILURE_RETRY(uevent_open_socket(64 * 1024, true))));
- if (uevent_fd_.get() < 0) {
- LOG(ERROR) << "failed to open uevent socket";
- return;
- }
-
- fcntl(uevent_fd_, F_SETFL, O_NONBLOCK);
-
- looper_->addFd(uevent_fd_.get(), 0, ::android::Looper::EVENT_INPUT, nullptr, nullptr);
- sleep_ms_ = std::chrono::milliseconds(0);
- last_update_time_ = boot_clock::now();
-}
-
-void ThermalWatcher::registerFilesToWatchNl(const std::set<std::string> &sensors_to_watch) {
- LOG(INFO) << "Thermal genl register file to watch...";
- monitored_sensors_.insert(sensors_to_watch.begin(), sensors_to_watch.end());
-
- sk_thermal = nl_socket_alloc();
- if (!sk_thermal) {
- LOG(ERROR) << "nl_socket_alloc failed";
- return;
- }
-
- if (genl_connect(sk_thermal)) {
- LOG(ERROR) << "genl_connect failed: sk_thermal";
- return;
- }
-
- thermal_genl_fd_.reset(nl_socket_get_fd(sk_thermal));
- if (thermal_genl_fd_.get() < 0) {
- LOG(ERROR) << "Failed to create thermal netlink socket";
- return;
- }
-
- if (!socketAddMembership(sk_thermal, THERMAL_GENL_EVENT_GROUP_NAME)) {
- return;
- }
-
- /*
- * Currently, only the update_temperature() will send thermal genl samlping events
- * from kernel. To avoid thermal-hal busy because samlping events are sent
- * too frequently, ignore thermal genl samlping events until we figure out how to use it.
- *
- if (!socketAddMembership(sk_thermal, THERMAL_GENL_SAMPLING_GROUP_NAME)) {
- return;
- }
- */
-
- fcntl(thermal_genl_fd_, F_SETFL, O_NONBLOCK);
- looper_->addFd(thermal_genl_fd_.get(), 0, ::android::Looper::EVENT_INPUT, nullptr, nullptr);
- sleep_ms_ = std::chrono::milliseconds(0);
- last_update_time_ = boot_clock::now();
-}
-
-bool ThermalWatcher::startWatchingDeviceFiles() {
- if (cb_) {
- auto ret = this->run("FileWatcherThread", ::android::PRIORITY_HIGHEST);
- if (ret != ::android::NO_ERROR) {
- LOG(ERROR) << "ThermalWatcherThread start fail";
- return false;
- } else {
- LOG(INFO) << "ThermalWatcherThread started";
- return true;
- }
- }
- return false;
-}
-void ThermalWatcher::parseUevent(std::set<std::string> *sensors_set) {
- bool thermal_event = false;
- constexpr int kUeventMsgLen = 2048;
- char msg[kUeventMsgLen + 2];
- char *cp;
-
- while (true) {
- int n = uevent_kernel_multicast_recv(uevent_fd_.get(), msg, kUeventMsgLen);
- if (n <= 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- LOG(ERROR) << "Error reading from Uevent Fd";
- }
- break;
- }
-
- if (n >= kUeventMsgLen) {
- LOG(ERROR) << "Uevent overflowed buffer, discarding";
- continue;
- }
-
- msg[n] = '\0';
- msg[n + 1] = '\0';
-
- cp = msg;
- while (*cp) {
- std::string uevent = cp;
- auto findSubSystemThermal = uevent.find("SUBSYSTEM=thermal");
- if (!thermal_event) {
- if (::android::base::StartsWith(uevent, "SUBSYSTEM=")) {
- if (findSubSystemThermal != std::string::npos) {
- thermal_event = true;
- } else {
- break;
- }
- }
- } else {
- auto start_pos = uevent.find("NAME=");
- if (start_pos != std::string::npos) {
- start_pos += 5;
- std::string name = uevent.substr(start_pos);
- if (monitored_sensors_.find(name) != monitored_sensors_.end()) {
- sensors_set->insert(name);
- }
- break;
- }
- }
- while (*cp++) {
- }
- }
- }
-}
-
-// TODO(b/175367921): Consider for potentially adding more type of event in the function
-// instead of just add the sensors to the list.
-void ThermalWatcher::parseGenlink(std::set<std::string> *sensors_set) {
- int err = 0, done = 0, tz_id = -1;
-
- std::unique_ptr<nl_cb, decltype(&nl_cb_put)> cb(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
-
- nl_cb_err(cb.get(), NL_CB_CUSTOM, nlErrorHandle, &err);
- nl_cb_set(cb.get(), NL_CB_FINISH, NL_CB_CUSTOM, nlFinishHandle, &done);
- nl_cb_set(cb.get(), NL_CB_ACK, NL_CB_CUSTOM, nlAckHandle, &done);
- nl_cb_set(cb.get(), NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nlSeqCheckHandle, &done);
- nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, handleEvent, &tz_id);
-
- while (!done && !err) {
- nl_recvmsgs(sk_thermal, cb.get());
-
- if (tz_id < 0) {
- break;
- }
-
- std::string name;
- if (getThermalZoneTypeById(tz_id, &name) &&
- monitored_sensors_.find(name) != monitored_sensors_.end()) {
- sensors_set->insert(name);
- }
- }
-}
-
-void ThermalWatcher::wake() {
- looper_->wake();
-}
-
-bool ThermalWatcher::threadLoop() {
- LOG(VERBOSE) << "ThermalWatcher polling...";
-
- int fd;
- std::set<std::string> sensors;
-
- auto time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now() -
- last_update_time_);
-
- if (time_elapsed_ms < sleep_ms_ &&
- looper_->pollOnce(sleep_ms_.count(), &fd, nullptr, nullptr) >= 0) {
- ATRACE_NAME("ThermalWatcher::threadLoop - receive event");
- if (fd != uevent_fd_.get() && fd != thermal_genl_fd_.get()) {
- return true;
- } else if (fd == thermal_genl_fd_.get()) {
- parseGenlink(&sensors);
- } else if (fd == uevent_fd_.get()) {
- parseUevent(&sensors);
- }
- // Ignore cb_ if uevent is not from monitored sensors
- if (sensors.size() == 0) {
- return true;
- }
- }
-
- sleep_ms_ = cb_(sensors);
- last_update_time_ = boot_clock::now();
- return true;
-}
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl
diff --git a/aidl/thermal/utils/thermal_watcher.h b/aidl/thermal/utils/thermal_watcher.h
deleted file mode 100644
index 8f8b398..0000000
--- a/aidl/thermal/utils/thermal_watcher.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <android-base/chrono_utils.h>
-#include <android-base/unique_fd.h>
-#include <linux/genetlink.h>
-#include <netlink/genl/ctrl.h>
-#include <netlink/genl/genl.h>
-#include <utils/Looper.h>
-#include <utils/Thread.h>
-
-#include <chrono>
-#include <condition_variable>
-#include <future>
-#include <list>
-#include <mutex>
-#include <set>
-#include <string>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace thermal {
-namespace implementation {
-
-using ::android::base::boot_clock;
-using ::android::base::unique_fd;
-using WatcherCallback = std::function<std::chrono::milliseconds(const std::set<std::string> &name)>;
-
-// A helper class for monitoring thermal files changes.
-class ThermalWatcher : public ::android::Thread {
- public:
- explicit ThermalWatcher(const WatcherCallback &cb)
- : Thread(false), cb_(cb), looper_(new ::android::Looper(true)) {}
- ~ThermalWatcher() = default;
-
- // Disallow copy and assign.
- ThermalWatcher(const ThermalWatcher &) = delete;
- void operator=(const ThermalWatcher &) = delete;
-
- // Start the thread and return true if it succeeds.
- bool startWatchingDeviceFiles();
- // Give the file watcher a list of files to start watching. This helper
- // class will by default wait for modifications to the file with a looper.
- // This should be called before starting watcher thread.
- // For monitoring uevents.
- void registerFilesToWatch(const std::set<std::string> &sensors_to_watch);
- // For monitoring thermal genl events.
- void registerFilesToWatchNl(const std::set<std::string> &sensors_to_watch);
- // Wake up the looper thus the worker thread, immediately. This can be called
- // in any thread.
- void wake();
-
- private:
- // The work done by the watcher thread. This will use inotify to check for
- // modifications to the files to watch. If any modification is seen this
- // will callback the registered function with the new data read from the
- // modified file.
- bool threadLoop() override;
-
- // Parse uevent message
- void parseUevent(std::set<std::string> *sensor_name);
-
- // Parse thermal netlink message
- void parseGenlink(std::set<std::string> *sensor_name);
-
- // Maps watcher filer descriptor to watched file path.
- std::unordered_map<int, std::string> watch_to_file_path_map_;
-
- // The callback function. Called whenever thermal uevent is seen.
- // The function passed in should expect a string in the form (type).
- // Where type is the name of the thermal zone that trigger a uevent notification.
- // Callback will return thermal trigger status for next polling decision.
- const WatcherCallback cb_;
-
- ::android::sp<::android::Looper> looper_;
-
- // For uevent socket registration.
- ::android::base::unique_fd uevent_fd_;
- // For thermal genl socket registration.
- ::android::base::unique_fd thermal_genl_fd_;
- // Sensor list which monitor flag is enabled.
- std::set<std::string> monitored_sensors_;
- // Sleep interval voting result
- std::chrono::milliseconds sleep_ms_;
- // Timestamp for last thermal update
- boot_clock::time_point last_update_time_;
- // For thermal genl socket object.
- struct nl_sock *sk_thermal;
-};
-
-} // namespace implementation
-} // namespace thermal
-} // namespace hardware
-} // namespace android
-} // namespace aidl