aidl: thermal: Update AIDL Thermal HAL from android-15.0.0_r20
HEAD to 387cefaab6d1e4ac30a859f512387cffa640abc1 ("Merge changes from
topic "p25_thermal_config_checker" into main")
Change-Id: I63223eb7562c6218104b774c0ffaae8e8baeb02c
This commit is contained in:
@@ -10,6 +10,7 @@ cc_binary {
|
||||
"utils/power_files.cpp",
|
||||
"utils/powerhal_helper.cpp",
|
||||
"utils/thermal_stats_helper.cpp",
|
||||
"utils/thermal_predictions_helper.cpp",
|
||||
"utils/thermal_watcher.cpp",
|
||||
"virtualtemp_estimator/virtualtemp_estimator.cpp",
|
||||
],
|
||||
@@ -33,7 +34,7 @@ cc_binary {
|
||||
"libbinder_ndk",
|
||||
"android.frameworks.stats-V2-ndk",
|
||||
"android.hardware.power-V1-ndk",
|
||||
"android.hardware.thermal-V2-ndk",
|
||||
"android.hardware.thermal-V3-ndk",
|
||||
"pixel-power-ext-V1-ndk",
|
||||
"pixelatoms-cpp",
|
||||
],
|
||||
|
||||
@@ -297,6 +297,10 @@ ndk::ScopedAStatus Thermal::unregisterCoolingDeviceChangedCallback(
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus Thermal::forecastSkinTemperature(int32_t, float *) {
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
}
|
||||
|
||||
void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
|
||||
*dump_buf << "getVirtualSensorInfo:" << std::endl;
|
||||
const auto &map = thermal_helper_->GetSensorInfoMap();
|
||||
|
||||
@@ -68,6 +68,8 @@ class Thermal : public BnThermal {
|
||||
CoolingType type) override;
|
||||
ndk::ScopedAStatus unregisterCoolingDeviceChangedCallback(
|
||||
const std::shared_ptr<ICoolingDeviceChangedCallback> &callback) override;
|
||||
ndk::ScopedAStatus forecastSkinTemperature(int32_t forecastSeconds,
|
||||
float *_aidl_return) override;
|
||||
|
||||
binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.thermal</name>
|
||||
<version>2</version>
|
||||
<version>3</version>
|
||||
<fqname>IThermal/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
|
||||
@@ -179,6 +179,11 @@ ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (!thermal_predictions_helper_.initializePredictionSensors(sensor_info_map_)) {
|
||||
LOG(ERROR) << "Failed to initialize prediction sensors";
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (!thermal_stats_helper_.initializeStats(config, sensor_info_map_,
|
||||
cooling_device_info_map_, this)) {
|
||||
@@ -279,7 +284,8 @@ ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
|
||||
}
|
||||
}
|
||||
// Check predictor info config
|
||||
if (name_status_pair.second.predictor_info != nullptr) {
|
||||
if ((name_status_pair.second.predictor_info != nullptr) &&
|
||||
name_status_pair.second.predictor_info->support_pid_compensation) {
|
||||
std::string predict_sensor_name = name_status_pair.second.predictor_info->sensor;
|
||||
if (!(sensor_info_map_.count(predict_sensor_name))) {
|
||||
LOG(ERROR) << name_status_pair.first << "'s predictor " << predict_sensor_name
|
||||
@@ -297,31 +303,29 @@ ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_status_pair.second.predictor_info->support_pid_compensation) {
|
||||
std::vector<float> output_template;
|
||||
size_t prediction_weight_count =
|
||||
name_status_pair.second.predictor_info->prediction_weights.size();
|
||||
// read predictor out to get the size of output vector
|
||||
::thermal::vtestimator::VtEstimatorStatus predict_check =
|
||||
predictor_sensor_info.virtual_sensor_info->vt_estimator->GetAllPredictions(
|
||||
&output_template);
|
||||
std::vector<float> output_template;
|
||||
size_t prediction_weight_count =
|
||||
name_status_pair.second.predictor_info->prediction_weights.size();
|
||||
// read predictor out to get the size of output vector
|
||||
::thermal::vtestimator::VtEstimatorStatus predict_check =
|
||||
predictor_sensor_info.virtual_sensor_info->vt_estimator->GetAllPredictions(
|
||||
&output_template);
|
||||
|
||||
if (predict_check != ::thermal::vtestimator::kVtEstimatorOk) {
|
||||
LOG(ERROR) << "Failed to get output size of " << name_status_pair.first
|
||||
<< "'s predictor " << predict_sensor_name
|
||||
<< " GetAllPredictions ret: " << ret << ")";
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
if (predict_check != ::thermal::vtestimator::kVtEstimatorOk) {
|
||||
LOG(ERROR) << "Failed to get output size of " << name_status_pair.first
|
||||
<< "'s predictor " << predict_sensor_name
|
||||
<< " GetAllPredictions ret: " << ret << ")";
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (prediction_weight_count != output_template.size()) {
|
||||
LOG(ERROR) << "Sensor [" << name_status_pair.first << "]: "
|
||||
<< "prediction weights size (" << prediction_weight_count
|
||||
<< ") doesn't match predictor [" << predict_sensor_name
|
||||
<< "]'s output size (" << output_template.size() << ")";
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
if (prediction_weight_count != output_template.size()) {
|
||||
LOG(ERROR) << "Sensor [" << name_status_pair.first
|
||||
<< "]: " << "prediction weights size (" << prediction_weight_count
|
||||
<< ") doesn't match predictor [" << predict_sensor_name
|
||||
<< "]'s output size (" << output_template.size() << ")";
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,23 +511,29 @@ bool ThermalHelperImpl::readCoolingDevice(std::string_view cooling_device,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThermalHelperImpl::readTemperature(std::string_view sensor_name, Temperature *out,
|
||||
const bool force_no_cache) {
|
||||
SensorReadStatus ThermalHelperImpl::readTemperature(std::string_view sensor_name, Temperature *out,
|
||||
const bool force_no_cache) {
|
||||
// Return fail if the thermal sensor cannot be read.
|
||||
float temp = NAN;
|
||||
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)) {
|
||||
const auto ret = readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log_map);
|
||||
if (ret == SensorReadStatus::ERROR) {
|
||||
LOG(ERROR) << "Failed to read thermal sensor " << sensor_name.data();
|
||||
thermal_stats_helper_.reportThermalAbnormality(
|
||||
ThermalSensorAbnormalityDetected::TEMP_READ_FAIL, sensor_name, std::nullopt);
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
|
||||
if (ret == SensorReadStatus::UNDER_COLLECTING) {
|
||||
LOG(INFO) << "Thermal sensor " << sensor_name.data() << " is under collecting";
|
||||
return SensorReadStatus::UNDER_COLLECTING;
|
||||
}
|
||||
|
||||
if (std::isnan(temp)) {
|
||||
LOG(INFO) << "Sensor " << sensor_name.data() << " temperature is nan.";
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
const auto severity_reference = getSeverityReference(sensor_name.data());
|
||||
|
||||
@@ -537,7 +547,7 @@ bool ThermalHelperImpl::readTemperature(std::string_view sensor_name, Temperatur
|
||||
|
||||
// Only update status if the thermal sensor is being monitored
|
||||
if (!sensor_info.is_watch) {
|
||||
return true;
|
||||
return SensorReadStatus::OKAY;
|
||||
}
|
||||
ThrottlingSeverity prev_hot_severity, prev_cold_severity;
|
||||
{
|
||||
@@ -589,7 +599,7 @@ bool ThermalHelperImpl::readTemperature(std::string_view sensor_name, Temperatur
|
||||
ATRACE_INT((sensor_name.data() + std::string("-severity")).c_str(),
|
||||
static_cast<int>(out->throttlingStatus));
|
||||
|
||||
return true;
|
||||
return SensorReadStatus::OKAY;
|
||||
}
|
||||
|
||||
bool ThermalHelperImpl::readTemperatureThreshold(std::string_view sensor_name,
|
||||
@@ -822,7 +832,6 @@ bool ThermalHelperImpl::initializeCoolingDevices(
|
||||
<< cooling_device_info_pair.second.state2power.size()
|
||||
<< ", number should be " << cooling_device_info_pair.second.max_state + 1
|
||||
<< " (max_state + 1)";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,9 +950,11 @@ bool ThermalHelperImpl::fillCurrentTemperatures(bool filterType, bool filterCall
|
||||
if (filterCallback && !name_info_pair.second.send_cb) {
|
||||
continue;
|
||||
}
|
||||
if (readTemperature(name_info_pair.first, &temp, false)) {
|
||||
|
||||
const auto status = readTemperature(name_info_pair.first, &temp, false);
|
||||
if (status == SensorReadStatus::OKAY) {
|
||||
ret.emplace_back(std::move(temp));
|
||||
} else {
|
||||
} else if (status == SensorReadStatus::ERROR) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": error reading temperature for sensor: " << name_info_pair.first;
|
||||
}
|
||||
@@ -1006,7 +1017,7 @@ ThrottlingSeverity ThermalHelperImpl::getSeverityReference(std::string_view sens
|
||||
}
|
||||
|
||||
Temperature temp;
|
||||
if (!readTemperature(severity_reference, &temp, false)) {
|
||||
if (readTemperature(severity_reference, &temp, false) != SensorReadStatus::OKAY) {
|
||||
return ThrottlingSeverity::NONE;
|
||||
}
|
||||
LOG(VERBOSE) << sensor_name << "'s severity reference " << severity_reference
|
||||
@@ -1019,8 +1030,8 @@ bool ThermalHelperImpl::readDataByType(std::string_view sensor_data, float *read
|
||||
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)) {
|
||||
if (readThermalSensor(sensor_data.data(), reading_value, force_no_cache,
|
||||
sensor_log_map) == SensorReadStatus::ERROR) {
|
||||
LOG(ERROR) << "Failed to get " << sensor_data.data() << " data";
|
||||
return false;
|
||||
}
|
||||
@@ -1096,6 +1107,9 @@ bool ThermalHelperImpl::runVirtualTempEstimator(std::string_view sensor_name,
|
||||
sensor_info.virtual_sensor_info->vt_estimator->Estimate(model_inputs, &model_outputs);
|
||||
|
||||
if (ret == ::thermal::vtestimator::kVtEstimatorOk) {
|
||||
if (sensor_info.predictor_info && sensor_info.predictor_info->supports_predictions) {
|
||||
thermal_predictions_helper_.updateSensor(sensor_name, model_outputs);
|
||||
}
|
||||
*outputs = model_outputs;
|
||||
return true;
|
||||
} else if (ret == ::thermal::vtestimator::kVtEstimatorLowConfidence ||
|
||||
@@ -1241,16 +1255,16 @@ bool ThermalHelperImpl::readTemperaturePredictions(std::string_view sensor_name,
|
||||
|
||||
constexpr int kTranTimeoutParam = 2;
|
||||
|
||||
bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *temp,
|
||||
const bool force_no_cache,
|
||||
std::map<std::string, float> *sensor_log_map) {
|
||||
SensorReadStatus ThermalHelperImpl::readThermalSensor(
|
||||
std::string_view sensor_name, float *temp, const bool force_no_cache,
|
||||
std::map<std::string, float> *sensor_log_map) {
|
||||
std::string file_reading;
|
||||
boot_clock::time_point now = boot_clock::now();
|
||||
|
||||
ATRACE_NAME(StringPrintf("ThermalHelper::readThermalSensor - %s", sensor_name.data()).c_str());
|
||||
if (!(sensor_info_map_.count(sensor_name.data()) &&
|
||||
sensor_status_map_.count(sensor_name.data()))) {
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
|
||||
const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
|
||||
@@ -1261,7 +1275,7 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
if (sensor_status.override_status.emul_temp != nullptr) {
|
||||
*temp = sensor_status.override_status.emul_temp->temp;
|
||||
(*sensor_log_map)[sensor_name.data()] = *temp;
|
||||
return true;
|
||||
return SensorReadStatus::OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1276,7 +1290,7 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
*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;
|
||||
return SensorReadStatus::OKAY;
|
||||
}
|
||||
|
||||
// Reading thermal sensor according to it's composition
|
||||
@@ -1284,7 +1298,7 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading) ||
|
||||
file_reading.empty()) {
|
||||
LOG(ERROR) << "failed to read sensor: " << sensor_name << " zone: " << sensor_info.zone_name;
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
*temp = std::stof(::android::base::Trim(file_reading));
|
||||
} else {
|
||||
@@ -1299,21 +1313,26 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
force_no_cache, sensor_log_map)) {
|
||||
LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s linked sensor "
|
||||
<< sensor_info.virtual_sensor_info->linked_sensors[i];
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
if (std::isnan(sensor_readings[i])) {
|
||||
LOG(INFO) << sensor_name << " data is under collecting";
|
||||
return true;
|
||||
return SensorReadStatus::UNDER_COLLECTING;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sensor_info.virtual_sensor_info->formula == FormulaOption::USE_ML_MODEL) ||
|
||||
(sensor_info.virtual_sensor_info->formula == FormulaOption::USE_LINEAR_MODEL)) {
|
||||
if (sensor_info.virtual_sensor_info->formula == FormulaOption::PREVIOUSLY_PREDICTED) {
|
||||
const auto ret = thermal_predictions_helper_.readSensor(sensor_name, temp);
|
||||
if (ret != SensorReadStatus::OKAY) {
|
||||
return ret;
|
||||
}
|
||||
} else if ((sensor_info.virtual_sensor_info->formula == FormulaOption::USE_ML_MODEL) ||
|
||||
(sensor_info.virtual_sensor_info->formula == FormulaOption::USE_LINEAR_MODEL)) {
|
||||
std::vector<float> vt_estimator_out;
|
||||
if (!runVirtualTempEstimator(sensor_name, sensor_log_map, force_no_cache,
|
||||
&vt_estimator_out)) {
|
||||
LOG(ERROR) << "Failed running VirtualEstimator for " << sensor_name;
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
*temp = vt_estimator_out[0];
|
||||
} else {
|
||||
@@ -1325,11 +1344,11 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
force_no_cache, sensor_log_map)) {
|
||||
LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
|
||||
<< sensor_info.virtual_sensor_info->coefficients[i];
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
if (std::isnan(coefficient)) {
|
||||
LOG(INFO) << sensor_name << " data is under collecting";
|
||||
return true;
|
||||
return SensorReadStatus::UNDER_COLLECTING;
|
||||
}
|
||||
switch (sensor_info.virtual_sensor_info->formula) {
|
||||
case FormulaOption::COUNT_THRESHOLD:
|
||||
@@ -1354,7 +1373,7 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown formula type for sensor " << sensor_name.data();
|
||||
return false;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
}
|
||||
*temp = (temp_val + sensor_info.virtual_sensor_info->offset);
|
||||
@@ -1377,7 +1396,7 @@ bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *t
|
||||
}
|
||||
auto real_temp = (*temp) * sensor_info.multiplier;
|
||||
thermal_stats_helper_.updateSensorTempStatsByThreshold(sensor_name, real_temp);
|
||||
return true;
|
||||
return SensorReadStatus::OKAY;
|
||||
}
|
||||
|
||||
// This is called in the different thread context and will update sensor_status
|
||||
@@ -1493,12 +1512,19 @@ std::chrono::milliseconds ThermalHelperImpl::thermalWatcherCallbackFunc(
|
||||
}
|
||||
|
||||
std::pair<ThrottlingSeverity, ThrottlingSeverity> throttling_status;
|
||||
if (!readTemperature(name_status_pair.first, &temp, force_no_cache)) {
|
||||
const auto ret = readTemperature(name_status_pair.first, &temp, force_no_cache);
|
||||
if (ret == SensorReadStatus::ERROR) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": error reading temperature for sensor: " << name_status_pair.first;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == SensorReadStatus::UNDER_COLLECTING) {
|
||||
LOG(INFO) << __func__
|
||||
<< ": data under collecting for sensor: " << name_status_pair.first;
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
|
||||
if (sensor_status.pending_notification) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "utils/powerhal_helper.h"
|
||||
#include "utils/thermal_files.h"
|
||||
#include "utils/thermal_info.h"
|
||||
#include "utils/thermal_predictions_helper.h"
|
||||
#include "utils/thermal_stats_helper.h"
|
||||
#include "utils/thermal_throttling.h"
|
||||
#include "utils/thermal_watcher.h"
|
||||
@@ -81,8 +82,8 @@ class ThermalHelper {
|
||||
const bool max_throttling) = 0;
|
||||
virtual bool emulClear(std::string_view target_sensor) = 0;
|
||||
virtual bool isInitializedOk() const = 0;
|
||||
virtual bool readTemperature(std::string_view sensor_name, Temperature *out,
|
||||
const bool force_sysfs = false) = 0;
|
||||
virtual SensorReadStatus readTemperature(std::string_view sensor_name, Temperature *out,
|
||||
const bool force_sysfs = false) = 0;
|
||||
virtual bool readTemperatureThreshold(std::string_view sensor_name,
|
||||
TemperatureThreshold *out) const = 0;
|
||||
virtual bool readCoolingDevice(std::string_view cooling_device, CoolingDevice *out) const = 0;
|
||||
@@ -130,8 +131,8 @@ class ThermalHelperImpl : public ThermalHelper {
|
||||
bool isInitializedOk() const override { return is_initialized_; }
|
||||
|
||||
// Read the temperature of a single sensor.
|
||||
bool readTemperature(std::string_view sensor_name, Temperature *out,
|
||||
const bool force_sysfs = false) override;
|
||||
SensorReadStatus readTemperature(std::string_view sensor_name, Temperature *out,
|
||||
const bool force_sysfs = false) override;
|
||||
|
||||
bool readTemperatureThreshold(std::string_view sensor_name,
|
||||
TemperatureThreshold *out) const override;
|
||||
@@ -203,8 +204,9 @@ class ThermalHelperImpl : public ThermalHelper {
|
||||
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);
|
||||
bool readThermalSensor(std::string_view sensor_name, float *temp, const bool force_sysfs,
|
||||
std::map<std::string, float> *sensor_log_map);
|
||||
SensorReadStatus readThermalSensor(std::string_view sensor_name, float *temp,
|
||||
const bool force_sysfs,
|
||||
std::map<std::string, float> *sensor_log_map);
|
||||
bool runVirtualTempEstimator(std::string_view sensor_name,
|
||||
std::map<std::string, float> *sensor_log_map,
|
||||
const bool force_no_cache, std::vector<float> *outputs);
|
||||
@@ -231,6 +233,7 @@ class ThermalHelperImpl : public ThermalHelper {
|
||||
supported_powerhint_map_;
|
||||
PowerHalService power_hal_service_;
|
||||
ThermalStatsHelper thermal_stats_helper_;
|
||||
ThermalPredictionsHelper thermal_predictions_helper_;
|
||||
mutable std::shared_mutex sensor_status_map_mutex_;
|
||||
std::unordered_map<std::string, SensorStatus> sensor_status_map_;
|
||||
};
|
||||
|
||||
@@ -348,8 +348,11 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
|
||||
formula = FormulaOption::USE_ML_MODEL;
|
||||
} else if (sensor["Formula"].asString().compare("USE_LINEAR_MODEL") == 0) {
|
||||
formula = FormulaOption::USE_LINEAR_MODEL;
|
||||
} else if (sensor["Formula"].asString().compare("PREVIOUSLY_PREDICTED") == 0) {
|
||||
formula = FormulaOption::PREVIOUSLY_PREDICTED;
|
||||
} else {
|
||||
LOG(ERROR) << "Sensor[" << name << "]'s Formula is invalid";
|
||||
LOG(ERROR) << "Sensor[" << name << "]'s Formula: " << sensor["Formula"].asString()
|
||||
<< " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -389,12 +392,14 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
|
||||
coefficients.emplace_back(values[j].asString());
|
||||
LOG(INFO) << "Sensor[" << name << "]'s coefficient[" << j << "]: " << coefficients[j];
|
||||
}
|
||||
} else if ((formula != FormulaOption::USE_ML_MODEL)) {
|
||||
} else if ((formula != FormulaOption::USE_ML_MODEL) &&
|
||||
(formula != FormulaOption::PREVIOUSLY_PREDICTED)) {
|
||||
LOG(ERROR) << "Sensor[" << name << "] has no Coefficient setting";
|
||||
return false;
|
||||
}
|
||||
if ((linked_sensors.size() != coefficients.size()) &&
|
||||
(formula != FormulaOption::USE_ML_MODEL) && (formula != FormulaOption::USE_LINEAR_MODEL)) {
|
||||
(formula != FormulaOption::USE_ML_MODEL) && (formula != FormulaOption::USE_LINEAR_MODEL) &&
|
||||
(formula != FormulaOption::PREVIOUSLY_PREDICTED)) {
|
||||
LOG(ERROR) << "Sensor[" << name << "] has invalid Coefficient size";
|
||||
return false;
|
||||
}
|
||||
@@ -594,47 +599,88 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
|
||||
bool ParsePredictorInfo(const std::string_view name, const Json::Value &sensor,
|
||||
std::unique_ptr<PredictorInfo> *predictor_info) {
|
||||
Json::Value predictor = sensor["PredictorInfo"];
|
||||
if (predictor.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Start to parse Sensor[" << name << "]'s PredictorInfo";
|
||||
if (predictor["Sensor"].empty()) {
|
||||
LOG(ERROR) << "Failed to parse Sensor [" << name << "]'s PredictorInfo";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string predict_sensor;
|
||||
bool support_pid_compensation = false;
|
||||
std::vector<float> prediction_weights;
|
||||
ThrottlingArray k_p_compensate;
|
||||
predict_sensor = predictor["Sensor"].asString();
|
||||
LOG(INFO) << "Sensor [" << name << "]'s predictor name is " << predict_sensor;
|
||||
// parse pid compensation configuration
|
||||
if ((!predictor["PredictionWeight"].empty()) && (!predictor["KPCompensate"].empty())) {
|
||||
support_pid_compensation = true;
|
||||
if (!predictor["PredictionWeight"].size()) {
|
||||
LOG(ERROR) << "Failed to parse PredictionWeight";
|
||||
|
||||
bool supports_predictions = false;
|
||||
int prediction_sample_interval = 0;
|
||||
int num_prediction_samples = 0;
|
||||
int prediction_duration = 0;
|
||||
bool set_predictor_info = false;
|
||||
|
||||
if (!predictor.empty()) {
|
||||
set_predictor_info = true;
|
||||
LOG(INFO) << "Start to parse Sensor[" << name << "]'s PredictorInfo";
|
||||
if (predictor["Sensor"].empty()) {
|
||||
LOG(ERROR) << "Failed to parse Sensor [" << name << "]'s PredictorInfo";
|
||||
return false;
|
||||
}
|
||||
prediction_weights.reserve(predictor["PredictionWeight"].size());
|
||||
for (Json::Value::ArrayIndex i = 0; i < predictor["PredictionWeight"].size(); ++i) {
|
||||
float weight = predictor["PredictionWeight"][i].asFloat();
|
||||
if (std::isnan(weight)) {
|
||||
LOG(ERROR) << "Unexpected NAN prediction weight for sensor [" << name << "]";
|
||||
|
||||
predict_sensor = predictor["Sensor"].asString();
|
||||
LOG(INFO) << "Sensor [" << name << "]'s predictor name is " << predict_sensor;
|
||||
// parse pid compensation configuration
|
||||
if ((!predictor["PredictionWeight"].empty()) && (!predictor["KPCompensate"].empty())) {
|
||||
support_pid_compensation = true;
|
||||
if (!predictor["PredictionWeight"].size()) {
|
||||
LOG(ERROR) << "Failed to parse PredictionWeight";
|
||||
return false;
|
||||
}
|
||||
prediction_weights.reserve(predictor["PredictionWeight"].size());
|
||||
for (Json::Value::ArrayIndex i = 0; i < predictor["PredictionWeight"].size(); ++i) {
|
||||
float weight = predictor["PredictionWeight"][i].asFloat();
|
||||
if (std::isnan(weight)) {
|
||||
LOG(ERROR) << "Unexpected NAN prediction weight for sensor [" << name << "]";
|
||||
}
|
||||
prediction_weights.emplace_back(weight);
|
||||
LOG(INFO) << "Sensor[" << name << "]'s prediction weights [" << i
|
||||
<< "]: " << weight;
|
||||
}
|
||||
if (!getFloatFromJsonValues(predictor["KPCompensate"], &k_p_compensate, false, false)) {
|
||||
LOG(ERROR) << "Failed to parse KPCompensate";
|
||||
return false;
|
||||
}
|
||||
prediction_weights.emplace_back(weight);
|
||||
LOG(INFO) << "Sensor[" << name << "]'s prediction weights [" << i << "]: " << weight;
|
||||
}
|
||||
if (!getFloatFromJsonValues(predictor["KPCompensate"], &k_p_compensate, false, false)) {
|
||||
LOG(ERROR) << "Failed to parse KPCompensate";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Successfully created PredictorInfo for Sensor[" << name << "]";
|
||||
predictor_info->reset(new PredictorInfo{predict_sensor, support_pid_compensation,
|
||||
prediction_weights, k_p_compensate});
|
||||
if (sensor["SupportPrediction"].asBool()) {
|
||||
set_predictor_info = true;
|
||||
supports_predictions = true;
|
||||
LOG(INFO) << "Sensor[" << name << "] supports predictions.";
|
||||
|
||||
if (sensor["SampleDuration"].empty()) {
|
||||
LOG(ERROR) << "SampleDuration is empty for predictor sensor: " << name;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sensor["OutputLabelCount"].empty()) {
|
||||
LOG(ERROR) << "OutputLabelCount is empty for predictor sensor: " << name;
|
||||
return false;
|
||||
}
|
||||
|
||||
prediction_sample_interval = sensor["SampleDuration"].asInt();
|
||||
num_prediction_samples = sensor["OutputLabelCount"].asInt();
|
||||
}
|
||||
|
||||
if (sensor["Formula"].asString().compare("PREVIOUSLY_PREDICTED") == 0) {
|
||||
set_predictor_info = true;
|
||||
if (sensor["PredictionDuration"].empty()) {
|
||||
LOG(ERROR) << "Sensor[" << name
|
||||
<< "] is a PREVIOUSLY_PREDICTED sensor and has no PredictionDuration";
|
||||
return false;
|
||||
}
|
||||
|
||||
prediction_duration = sensor["PredictionDuration"].asInt();
|
||||
}
|
||||
|
||||
if (set_predictor_info) {
|
||||
LOG(INFO) << "Successfully created PredictorInfo for Sensor[" << name << "]";
|
||||
predictor_info->reset(new PredictorInfo{predict_sensor, support_pid_compensation,
|
||||
prediction_weights, k_p_compensate,
|
||||
supports_predictions, prediction_sample_interval,
|
||||
num_prediction_samples, prediction_duration});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1477,8 +1523,8 @@ bool ParseSensorInfo(const Json::Value &config,
|
||||
.hot_hysteresis = hot_hysteresis,
|
||||
.cold_hysteresis = cold_hysteresis,
|
||||
.temp_path = temp_path,
|
||||
.zone_name = zone_name,
|
||||
.severity_reference = severity_reference,
|
||||
.zone_name = zone_name,
|
||||
.vr_threshold = vr_threshold,
|
||||
.multiplier = multiplier,
|
||||
.polling_delay = polling_delay,
|
||||
|
||||
@@ -46,7 +46,8 @@ enum class FormulaOption : uint32_t {
|
||||
MAXIMUM,
|
||||
MINIMUM,
|
||||
USE_ML_MODEL,
|
||||
USE_LINEAR_MODEL
|
||||
USE_LINEAR_MODEL,
|
||||
PREVIOUSLY_PREDICTED
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -120,6 +121,12 @@ enum class SensorFusionType : uint32_t {
|
||||
CDEV,
|
||||
};
|
||||
|
||||
enum class SensorReadStatus : uint32_t {
|
||||
OKAY = 0,
|
||||
UNDER_COLLECTING,
|
||||
ERROR,
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const SensorFusionType &sensor_fusion_type);
|
||||
|
||||
struct VirtualSensorInfo {
|
||||
@@ -141,6 +148,11 @@ struct PredictorInfo {
|
||||
bool support_pid_compensation;
|
||||
std::vector<float> prediction_weights;
|
||||
ThrottlingArray k_p_compensate;
|
||||
|
||||
bool supports_predictions; // Does this sensor support predictions
|
||||
int prediction_sample_interval; // Interval between each predicted sample
|
||||
int num_prediction_samples; // How many samples are predicted for each iteration
|
||||
int prediction_duration; // Prediction duration for a PREDICTED sensor
|
||||
};
|
||||
|
||||
struct VirtualPowerRailInfo {
|
||||
@@ -205,8 +217,8 @@ struct SensorInfo {
|
||||
ThrottlingArray hot_hysteresis;
|
||||
ThrottlingArray cold_hysteresis;
|
||||
std::string temp_path;
|
||||
std::string zone_name;
|
||||
std::string severity_reference;
|
||||
std::string zone_name;
|
||||
float vr_threshold;
|
||||
float multiplier;
|
||||
std::chrono::milliseconds polling_delay;
|
||||
|
||||
205
aidl/thermal/utils/thermal_predictions_helper.cpp
Normal file
205
aidl/thermal/utils/thermal_predictions_helper.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "thermal_predictions_helper.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <string_view>
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace implementation {
|
||||
|
||||
bool ThermalPredictionsHelper::registerPredictorSensor(std::string_view sensor_name,
|
||||
int sample_duration, int num_out_samples) {
|
||||
if (sample_duration <= 0 || num_out_samples <= 0) {
|
||||
LOG(ERROR) << "Invalid sample_duration: " << sample_duration
|
||||
<< " or num_out_samples: " << num_out_samples << " for sensor: " << sensor_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (predictor_sensors_.count(sensor_name.data())) {
|
||||
LOG(ERROR) << "sensor_name " << sensor_name << " is already registered as predictor";
|
||||
return false;
|
||||
}
|
||||
|
||||
predictor_sensors_[sensor_name.data()] = PredictorSensorInfo(
|
||||
{std::string(sensor_name), sample_duration, num_out_samples,
|
||||
std::vector<PredictionSample>(num_out_samples, PredictionSample(num_out_samples)), 0});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThermalPredictionsHelper::registerPredictedSensor(std::string_view sensor_name,
|
||||
std::string_view linked_sensor,
|
||||
int duration) {
|
||||
if (duration < 0) {
|
||||
LOG(ERROR) << "Invalid duration: " << duration << " for sensor: " << sensor_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (predicted_sensors_.count(sensor_name.data())) {
|
||||
LOG(ERROR) << "sensor_name " << sensor_name << " is already registered as predicted sensor";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (predictor_sensors_.count(linked_sensor.data()) == 0) {
|
||||
LOG(ERROR) << "linked_sensor_name " << linked_sensor << " is not registered as predictor";
|
||||
return false;
|
||||
}
|
||||
|
||||
PredictorSensorInfo &predictor_sensor_info = predictor_sensors_[linked_sensor.data()];
|
||||
const int max_prediction_duration =
|
||||
(predictor_sensor_info.num_out_samples - 1) * predictor_sensor_info.sample_duration;
|
||||
|
||||
if (duration > max_prediction_duration) {
|
||||
LOG(ERROR) << "Predicted sensor " << sensor_name
|
||||
<< " duration is greater than max prediction duration of predictor "
|
||||
<< linked_sensor << " which is " << max_prediction_duration;
|
||||
return false;
|
||||
}
|
||||
|
||||
// round up to nearest lower index
|
||||
const int prediction_index = duration / predictor_sensor_info.sample_duration;
|
||||
if (duration % predictor_sensor_info.sample_duration != 0) {
|
||||
LOG(INFO) << "Predicted sensor " << sensor_name << " duration " << duration
|
||||
<< " is not a multiple of " << linked_sensor << " sample duration "
|
||||
<< predictor_sensor_info.sample_duration << " and hence updated to "
|
||||
<< prediction_index * predictor_sensor_info.sample_duration;
|
||||
}
|
||||
|
||||
predicted_sensors_[sensor_name.data()] = PredictedSensorInfo(
|
||||
{std::string(sensor_name), std::string(linked_sensor), duration, prediction_index});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThermalPredictionsHelper::updateSensor(std::string_view sensor_name,
|
||||
std::vector<float> &values) {
|
||||
std::unique_lock<std::shared_mutex> _lock(sensor_predictions_mutex_);
|
||||
const auto sensor_itr = predictor_sensors_.find(sensor_name.data());
|
||||
if (sensor_itr == predictor_sensors_.end()) {
|
||||
LOG(ERROR) << "sensor_name " << sensor_name << " is not registered as predictor";
|
||||
return false;
|
||||
}
|
||||
|
||||
PredictorSensorInfo &predictor_sensor_info = predictor_sensors_[sensor_name.data()];
|
||||
if (values.size() != static_cast<size_t>(predictor_sensor_info.num_out_samples)) {
|
||||
LOG(ERROR) << "Invalid number of values: " << values.size()
|
||||
<< " for sensor: " << sensor_name
|
||||
<< ", expected: " << predictor_sensor_info.num_out_samples;
|
||||
return false;
|
||||
}
|
||||
|
||||
predictor_sensor_info.samples[predictor_sensor_info.cur_index].timestamp = boot_clock::now();
|
||||
predictor_sensor_info.samples[predictor_sensor_info.cur_index].values = values;
|
||||
predictor_sensor_info.cur_index++;
|
||||
predictor_sensor_info.cur_index %= predictor_sensor_info.num_out_samples;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SensorReadStatus ThermalPredictionsHelper::readSensor(std::string_view sensor_name, float *temp) {
|
||||
std::shared_lock<std::shared_mutex> _lock(sensor_predictions_mutex_);
|
||||
const auto sensor_itr = predicted_sensors_.find(sensor_name.data());
|
||||
if (sensor_itr == predicted_sensors_.end()) {
|
||||
LOG(ERROR) << "sensor_name " << sensor_name << " is not registered as predicted sensor";
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
|
||||
PredictedSensorInfo &predicted_sensor_info = predicted_sensors_[sensor_name.data()];
|
||||
const int prediction_index = predicted_sensor_info.prediction_index;
|
||||
|
||||
const auto linked_sensor_itr = predictor_sensors_.find(predicted_sensor_info.linked_sensor);
|
||||
if (linked_sensor_itr == predictor_sensors_.end()) {
|
||||
LOG(ERROR) << "linked_sensor_name " << predicted_sensor_info.linked_sensor
|
||||
<< " is not registered as predictor for sensor" << sensor_name;
|
||||
return SensorReadStatus::ERROR;
|
||||
}
|
||||
|
||||
PredictorSensorInfo predictor_sensor_info = linked_sensor_itr->second;
|
||||
boot_clock::time_point now = boot_clock::now();
|
||||
const auto min_time_elapsed_ms = predicted_sensor_info.duration - kToleranceIntervalMs;
|
||||
const auto max_time_elapsed_ms = predicted_sensor_info.duration + kToleranceIntervalMs;
|
||||
int loop_count = 0;
|
||||
do {
|
||||
int index = predictor_sensor_info.cur_index - loop_count - 1;
|
||||
if (index < 0) {
|
||||
index += predictor_sensor_info.num_out_samples;
|
||||
}
|
||||
|
||||
const auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - predictor_sensor_info.samples[index].timestamp);
|
||||
if (time_elapsed.count() <= max_time_elapsed_ms &&
|
||||
time_elapsed.count() >= min_time_elapsed_ms) {
|
||||
*temp = predictor_sensor_info.samples[index].values[prediction_index];
|
||||
return SensorReadStatus::OKAY;
|
||||
}
|
||||
|
||||
loop_count++;
|
||||
} while (loop_count < predictor_sensor_info.num_out_samples);
|
||||
|
||||
LOG(INFO) << "sensor_name: " << sensor_name << " no valid prediction samples found";
|
||||
return SensorReadStatus::UNDER_COLLECTING;
|
||||
}
|
||||
|
||||
bool ThermalPredictionsHelper::initializePredictionSensors(
|
||||
const std::unordered_map<std::string, SensorInfo> &sensor_info_map) {
|
||||
std::unique_lock<std::shared_mutex> _lock(sensor_predictions_mutex_);
|
||||
|
||||
for (auto it = sensor_info_map.begin(); it != sensor_info_map.end(); ++it) {
|
||||
const std::string_view sensor_name = it->first;
|
||||
const SensorInfo &sensor_info = it->second;
|
||||
|
||||
if (!sensor_info.predictor_info || !sensor_info.virtual_sensor_info ||
|
||||
(!sensor_info.predictor_info->supports_predictions)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!registerPredictorSensor(sensor_name,
|
||||
sensor_info.predictor_info->prediction_sample_interval,
|
||||
sensor_info.predictor_info->num_prediction_samples)) {
|
||||
LOG(ERROR) << "Failed to register predictor sensor: " << sensor_name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = sensor_info_map.begin(); it != sensor_info_map.end(); ++it) {
|
||||
const std::string_view sensor_name = it->first;
|
||||
const SensorInfo &sensor_info = it->second;
|
||||
|
||||
if (!sensor_info.predictor_info || !sensor_info.virtual_sensor_info ||
|
||||
(sensor_info.virtual_sensor_info->formula != FormulaOption::PREVIOUSLY_PREDICTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sensor_info.virtual_sensor_info->linked_sensors.size() != 1) {
|
||||
LOG(ERROR) << "Invalid number of linked sensors: "
|
||||
<< sensor_info.virtual_sensor_info->linked_sensors.size()
|
||||
<< " for sensor: " << sensor_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!registerPredictedSensor(sensor_name,
|
||||
sensor_info.virtual_sensor_info->linked_sensors[0],
|
||||
sensor_info.predictor_info->prediction_duration)) {
|
||||
LOG(ERROR) << "Failed to register predicted sensor: " << sensor_name;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
81
aidl/thermal/utils/thermal_predictions_helper.h
Normal file
81
aidl/thermal/utils/thermal_predictions_helper.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/thermal/Temperature.h>
|
||||
#include <android-base/chrono_utils.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <shared_mutex>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "thermal_info.h"
|
||||
|
||||
namespace aidl {
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace thermal {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::base::boot_clock;
|
||||
constexpr int kToleranceIntervalMs = 1000;
|
||||
|
||||
struct PredictionSample {
|
||||
PredictionSample(int num_out_samples) {
|
||||
timestamp = boot_clock::time_point::min();
|
||||
values = std::vector<float>(num_out_samples, NAN);
|
||||
}
|
||||
boot_clock::time_point timestamp;
|
||||
std::vector<float> values;
|
||||
};
|
||||
|
||||
struct PredictorSensorInfo {
|
||||
std::string sensor_name;
|
||||
int sample_duration;
|
||||
int num_out_samples;
|
||||
std::vector<PredictionSample> samples;
|
||||
int cur_index;
|
||||
};
|
||||
|
||||
struct PredictedSensorInfo {
|
||||
std::string sensor_name;
|
||||
std::string linked_sensor;
|
||||
int duration;
|
||||
int prediction_index;
|
||||
};
|
||||
|
||||
class ThermalPredictionsHelper {
|
||||
public:
|
||||
ThermalPredictionsHelper() = default;
|
||||
~ThermalPredictionsHelper() = default;
|
||||
// Disallow copy and assign
|
||||
ThermalPredictionsHelper(const ThermalPredictionsHelper &) = delete;
|
||||
void operator=(const ThermalPredictionsHelper &) = delete;
|
||||
|
||||
bool initializePredictionSensors(
|
||||
const std::unordered_map<std::string, SensorInfo> &sensor_info_map);
|
||||
bool updateSensor(std::string_view sensor_name, std::vector<float> &values);
|
||||
SensorReadStatus readSensor(std::string_view sensor_name, float *temp);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, PredictorSensorInfo> predictor_sensors_;
|
||||
std::unordered_map<std::string, PredictedSensorInfo> predicted_sensors_;
|
||||
mutable std::shared_mutex sensor_predictions_mutex_;
|
||||
|
||||
bool registerPredictedSensor(std::string_view sensor_name, std::string_view linked_sensor,
|
||||
int duration);
|
||||
bool registerPredictorSensor(std::string_view sensor_name, int sample_duration,
|
||||
int num_out_samples);
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace thermal
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
} // namespace aidl
|
||||
@@ -181,14 +181,33 @@ float ThermalThrottling::updatePowerBudget(
|
||||
float p = 0, d = 0;
|
||||
float power_budget = std::numeric_limits<float>::max();
|
||||
bool target_changed = false;
|
||||
bool is_fully_throttle = true;
|
||||
bool is_fully_release = true;
|
||||
float budget_transient = 0.0;
|
||||
auto &throttling_status = thermal_throttling_status_map_.at(temp.name);
|
||||
const auto &profile = throttling_status.profile;
|
||||
std::string sensor_name = temp.name;
|
||||
|
||||
if (curr_severity == ThrottlingSeverity::NONE) {
|
||||
return power_budget;
|
||||
}
|
||||
|
||||
// Go through the binded cdev, check current throttle status
|
||||
for (const auto &binded_cdev_info_pair :
|
||||
((sensor_info.throttling_info->profile_map.empty() ||
|
||||
!sensor_info.throttling_info->profile_map.contains(profile))
|
||||
? sensor_info.throttling_info->binded_cdev_info_map
|
||||
: sensor_info.throttling_info->profile_map.at(profile))) {
|
||||
if (throttling_status.pid_cdev_request_map.at(binded_cdev_info_pair.first) >
|
||||
binded_cdev_info_pair.second.limit_info[static_cast<size_t>(curr_severity)]) {
|
||||
is_fully_release = false;
|
||||
}
|
||||
if (throttling_status.pid_cdev_request_map.at(binded_cdev_info_pair.first) <
|
||||
binded_cdev_info_pair.second.cdev_ceiling[static_cast<size_t>(curr_severity)]) {
|
||||
is_fully_throttle = false;
|
||||
}
|
||||
}
|
||||
|
||||
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 &&
|
||||
@@ -206,9 +225,11 @@ float ThermalThrottling::updatePowerBudget(
|
||||
return sensor_info.throttling_info->min_alloc_power[target_state];
|
||||
}
|
||||
|
||||
// Calculate P budget
|
||||
p = err * (err < 0 ? sensor_info.throttling_info->k_po[target_state]
|
||||
: sensor_info.throttling_info->k_pu[target_state]);
|
||||
|
||||
// Calculate I budget
|
||||
if (std::isnan(throttling_status.i_budget)) {
|
||||
if (std::isnan(sensor_info.throttling_info->i_default_pct)) {
|
||||
throttling_status.i_budget = sensor_info.throttling_info->i_default;
|
||||
@@ -227,15 +248,16 @@ float ThermalThrottling::updatePowerBudget(
|
||||
}
|
||||
|
||||
if (err < sensor_info.throttling_info->i_cutoff[target_state]) {
|
||||
if (!(throttling_status.prev_power_budget <=
|
||||
sensor_info.throttling_info->min_alloc_power[target_state] &&
|
||||
err < 0) &&
|
||||
!(throttling_status.prev_power_budget >=
|
||||
sensor_info.throttling_info->max_alloc_power[target_state] &&
|
||||
err > 0)) {
|
||||
throttling_status.i_budget +=
|
||||
err * (err < 0 ? sensor_info.throttling_info->k_io[target_state]
|
||||
: sensor_info.throttling_info->k_iu[target_state]);
|
||||
if (err < 0 &&
|
||||
throttling_status.prev_power_budget >
|
||||
sensor_info.throttling_info->min_alloc_power[target_state] &&
|
||||
!is_fully_throttle) {
|
||||
throttling_status.i_budget += err * sensor_info.throttling_info->k_io[target_state];
|
||||
} else if (err > 0 &&
|
||||
throttling_status.prev_power_budget <
|
||||
sensor_info.throttling_info->max_alloc_power[target_state] &&
|
||||
!is_fully_release) {
|
||||
throttling_status.i_budget += err * sensor_info.throttling_info->k_iu[target_state];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +266,7 @@ float ThermalThrottling::updatePowerBudget(
|
||||
(throttling_status.i_budget > 0 ? 1 : -1);
|
||||
}
|
||||
|
||||
// Calculate D budget
|
||||
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) /
|
||||
@@ -382,7 +405,7 @@ bool ThermalThrottling::allocatePowerToCdev(
|
||||
}
|
||||
}
|
||||
|
||||
// Compute total cdev weight
|
||||
// Go through binded cdev, compute total cdev weight
|
||||
for (const auto &binded_cdev_info_pair :
|
||||
(sensor_info.throttling_info->profile_map.count(profile)
|
||||
? sensor_info.throttling_info->profile_map.at(profile)
|
||||
|
||||
Reference in New Issue
Block a user