1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "thermal_info.h"
17 
18 #include <android-base/file.h>
19 #include <android-base/logging.h>
20 #include <android-base/properties.h>
21 #include <android-base/strings.h>
22 #include <json/reader.h>
23 
24 #include <cmath>
25 #include <unordered_set>
26 
27 namespace aidl {
28 namespace android {
29 namespace hardware {
30 namespace thermal {
31 namespace implementation {
32 
33 constexpr std::string_view kPowerLinkDisabledProperty("vendor.disable.thermal.powerlink");
34 
35 namespace {
36 
37 template <typename T>
38 // Return false when failed parsing
getTypeFromString(std::string_view str,T * out)39 bool getTypeFromString(std::string_view str, T *out) {
40     auto types = ::ndk::enum_range<T>();
41     for (const auto &type : types) {
42         if (::aidl::android::hardware::thermal::toString(type) == str) {
43             *out = type;
44             return true;
45         }
46     }
47     return false;
48 }
49 
getFloatFromValue(const Json::Value & value)50 float getFloatFromValue(const Json::Value &value) {
51     if (value.isString()) {
52         return std::stof(value.asString());
53     } else {
54         return value.asFloat();
55     }
56 }
57 
getIntFromValue(const Json::Value & value)58 int getIntFromValue(const Json::Value &value) {
59     if (value.isString()) {
60         return (value.asString() == "max") ? std::numeric_limits<int>::max()
61                                            : std::stoul(value.asString());
62     } else {
63         return value.asInt();
64     }
65 }
66 
getIntFromJsonValues(const Json::Value & values,CdevArray * out,bool inc_check,bool dec_check)67 bool getIntFromJsonValues(const Json::Value &values, CdevArray *out, bool inc_check,
68                           bool dec_check) {
69     CdevArray ret;
70 
71     if (inc_check && dec_check) {
72         LOG(ERROR) << "Cannot enable inc_check and dec_check at the same time";
73         return false;
74     }
75 
76     if (values.size() != kThrottlingSeverityCount) {
77         LOG(ERROR) << "Values size is invalid";
78         return false;
79     } else {
80         int last = (inc_check) ? std::numeric_limits<int>::min() : std::numeric_limits<int>::max();
81         for (Json::Value::ArrayIndex i = 0; i < kThrottlingSeverityCount; ++i) {
82             ret[i] = getIntFromValue(values[i]);
83             if (inc_check && ret[i] < last) {
84                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " min=" << last;
85                 return false;
86             }
87             if (dec_check && ret[i] > last) {
88                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " max=" << last;
89                 return false;
90             }
91             last = ret[i];
92             LOG(INFO) << "[" << i << "]: " << ret[i];
93         }
94     }
95 
96     *out = ret;
97     return true;
98 }
99 
getFloatFromJsonValues(const Json::Value & values,ThrottlingArray * out,bool inc_check,bool dec_check)100 bool getFloatFromJsonValues(const Json::Value &values, ThrottlingArray *out, bool inc_check,
101                             bool dec_check) {
102     ThrottlingArray ret;
103 
104     if (inc_check && dec_check) {
105         LOG(ERROR) << "Cannot enable inc_check and dec_check at the same time";
106         return false;
107     }
108 
109     if (values.size() != kThrottlingSeverityCount) {
110         LOG(ERROR) << "Values size is invalid";
111         return false;
112     } else {
113         float last = std::nanf("");
114         for (Json::Value::ArrayIndex i = 0; i < kThrottlingSeverityCount; ++i) {
115             ret[i] = getFloatFromValue(values[i]);
116             if (inc_check && !std::isnan(last) && !std::isnan(ret[i]) && ret[i] < last) {
117                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " min=" << last;
118                 return false;
119             }
120             if (dec_check && !std::isnan(last) && !std::isnan(ret[i]) && ret[i] > last) {
121                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " max=" << last;
122                 return false;
123             }
124             last = std::isnan(ret[i]) ? last : ret[i];
125             LOG(INFO) << "[" << i << "]: " << ret[i];
126         }
127     }
128 
129     *out = ret;
130     return true;
131 }
132 
getTempRangeInfoFromJsonValues(const Json::Value & values,TempRangeInfo * temp_range_info)133 bool getTempRangeInfoFromJsonValues(const Json::Value &values, TempRangeInfo *temp_range_info) {
134     if (values.size() != 2) {
135         LOG(ERROR) << "Temp Range Values size: " << values.size() << "is invalid.";
136         return false;
137     }
138 
139     float min_temp = getFloatFromValue(values[0]);
140     float max_temp = getFloatFromValue(values[1]);
141 
142     if (std::isnan(min_temp) || std::isnan(max_temp)) {
143         LOG(ERROR) << "Illegal temp range: thresholds not defined properly " << min_temp << " : "
144                    << max_temp;
145         return false;
146     }
147 
148     if (min_temp > max_temp) {
149         LOG(ERROR) << "Illegal temp range: temp_min_threshold(" << min_temp
150                    << ") > temp_max_threshold(" << max_temp << ")";
151         return false;
152     }
153     temp_range_info->min_temp_threshold = min_temp;
154     temp_range_info->max_temp_threshold = max_temp;
155     LOG(INFO) << "Temp Range Info: " << temp_range_info->min_temp_threshold
156               << " <= t <= " << temp_range_info->max_temp_threshold;
157     return true;
158 }
159 
getTempStuckInfoFromJsonValue(const Json::Value & values,TempStuckInfo * temp_stuck_info)160 bool getTempStuckInfoFromJsonValue(const Json::Value &values, TempStuckInfo *temp_stuck_info) {
161     if (values["MinStuckDuration"].empty()) {
162         LOG(ERROR) << "Minimum stuck duration not present.";
163         return false;
164     }
165     int min_stuck_duration_int = getIntFromValue(values["MinStuckDuration"]);
166     if (min_stuck_duration_int <= 0) {
167         LOG(ERROR) << "Invalid Minimum stuck duration " << min_stuck_duration_int;
168         return false;
169     }
170 
171     if (values["MinPollingCount"].empty()) {
172         LOG(ERROR) << "Minimum polling count not present.";
173         return false;
174     }
175     int min_polling_count = getIntFromValue(values["MinPollingCount"]);
176     if (min_polling_count <= 0) {
177         LOG(ERROR) << "Invalid Minimum stuck duration " << min_polling_count;
178         return false;
179     }
180     temp_stuck_info->min_stuck_duration = std::chrono::milliseconds(min_stuck_duration_int);
181     temp_stuck_info->min_polling_count = min_polling_count;
182     LOG(INFO) << "Temp Stuck Info: polling_count=" << temp_stuck_info->min_polling_count
183               << " stuck_duration=" << temp_stuck_info->min_stuck_duration.count();
184     return true;
185 }
186 }  // namespace
187 
operator <<(std::ostream & stream,const SensorFusionType & sensor_fusion_type)188 std::ostream &operator<<(std::ostream &stream, const SensorFusionType &sensor_fusion_type) {
189     switch (sensor_fusion_type) {
190         case SensorFusionType::SENSOR:
191             return stream << "SENSOR";
192         case SensorFusionType::ODPM:
193             return stream << "ODPM";
194         case SensorFusionType::CONSTANT:
195             return stream << "CONSTANT";
196         default:
197             return stream << "UNDEFINED";
198     }
199 }
200 
ParseThermalConfig(std::string_view config_path,Json::Value * config)201 bool ParseThermalConfig(std::string_view config_path, Json::Value *config) {
202     std::string json_doc;
203     if (!::android::base::ReadFileToString(config_path.data(), &json_doc)) {
204         LOG(ERROR) << "Failed to read JSON config from " << config_path;
205         return false;
206     }
207     Json::CharReaderBuilder builder;
208     std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
209     std::string errorMessage;
210     if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), config, &errorMessage)) {
211         LOG(ERROR) << "Failed to parse JSON config: " << errorMessage;
212         return false;
213     }
214     return true;
215 }
216 
ParseOffsetThresholds(const std::string_view name,const Json::Value & sensor,std::vector<float> * offset_thresholds,std::vector<float> * offset_values)217 bool ParseOffsetThresholds(const std::string_view name, const Json::Value &sensor,
218                            std::vector<float> *offset_thresholds,
219                            std::vector<float> *offset_values) {
220     Json::Value config_offset_thresholds = sensor["OffsetThresholds"];
221     Json::Value config_offset_values = sensor["OffsetValues"];
222 
223     if (config_offset_thresholds.empty()) {
224         return true;
225     }
226 
227     if (config_offset_thresholds.size() != config_offset_values.size()) {
228         LOG(ERROR) << "Sensor[" << name
229                    << "]'s offset_thresholds size does not match with offset_values size";
230         return false;
231     }
232 
233     for (Json::Value::ArrayIndex i = 0; i < config_offset_thresholds.size(); ++i) {
234         float offset_threshold = config_offset_thresholds[i].asFloat();
235         float offset_value = config_offset_values[i].asFloat();
236         if (std::isnan(offset_threshold) || std::isnan(offset_value)) {
237             LOG(ERROR) << "Nan offset_threshold or offset_value unexpected for sensor " << name;
238             return false;
239         }
240 
241         if ((i != 0) && (offset_threshold < (*offset_thresholds).back())) {
242             LOG(ERROR) << "offset_thresholds are not in increasing order for sensor " << name;
243             return false;
244         }
245 
246         (*offset_thresholds).emplace_back(offset_threshold);
247         (*offset_values).emplace_back(offset_value);
248 
249         LOG(INFO) << "Sensor[" << name << "]'s offset_thresholds[" << i
250                   << "]: " << (*offset_thresholds)[i] << " offset_values[" << i
251                   << "]: " << (*offset_values)[i];
252     }
253 
254     return true;
255 }
256 
ParseVirtualSensorInfo(const std::string_view name,const Json::Value & sensor,std::unique_ptr<VirtualSensorInfo> * virtual_sensor_info)257 bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sensor,
258                             std::unique_ptr<VirtualSensorInfo> *virtual_sensor_info) {
259     if (sensor["VirtualSensor"].empty() || !sensor["VirtualSensor"].isBool()) {
260         LOG(INFO) << "Failed to read Sensor[" << name << "]'s VirtualSensor";
261         return true;
262     }
263     bool is_virtual_sensor = sensor["VirtualSensor"].asBool();
264     LOG(INFO) << "Sensor[" << name << "]'s' VirtualSensor: " << is_virtual_sensor;
265     if (!is_virtual_sensor) {
266         return true;
267     }
268     float offset = 0;
269     std::vector<std::string> linked_sensors;
270     std::vector<SensorFusionType> linked_sensors_type;
271     std::vector<std::string> trigger_sensors;
272     std::vector<std::string> coefficients;
273     std::vector<SensorFusionType> coefficients_type;
274     FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
275     std::string vt_estimator_model_file;
276     std::unique_ptr<::thermal::vtestimator::VirtualTempEstimator> vt_estimator;
277     std::string backup_sensor;
278 
279     Json::Value values = sensor["Combination"];
280     if (values.size()) {
281         linked_sensors.reserve(values.size());
282         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
283             linked_sensors.emplace_back(values[j].asString());
284             LOG(INFO) << "Sensor[" << name << "]'s Combination[" << j << "]: " << linked_sensors[j];
285         }
286     } else {
287         LOG(ERROR) << "Sensor[" << name << "] has no Combination setting";
288         return false;
289     }
290 
291     if (sensor["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
292         formula = FormulaOption::COUNT_THRESHOLD;
293     } else if (sensor["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
294         formula = FormulaOption::WEIGHTED_AVG;
295     } else if (sensor["Formula"].asString().compare("MAXIMUM") == 0) {
296         formula = FormulaOption::MAXIMUM;
297     } else if (sensor["Formula"].asString().compare("MINIMUM") == 0) {
298         formula = FormulaOption::MINIMUM;
299     } else if (sensor["Formula"].asString().compare("USE_ML_MODEL") == 0) {
300         formula = FormulaOption::USE_ML_MODEL;
301     } else if (sensor["Formula"].asString().compare("USE_LINEAR_MODEL") == 0) {
302         formula = FormulaOption::USE_LINEAR_MODEL;
303     } else {
304         LOG(ERROR) << "Sensor[" << name << "]'s Formula is invalid";
305         return false;
306     }
307 
308     values = sensor["CombinationType"];
309     if (!values.size()) {
310         linked_sensors_type.reserve(linked_sensors.size());
311         for (size_t j = 0; j < linked_sensors.size(); ++j) {
312             linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
313         }
314     } else if (values.size() != linked_sensors.size()) {
315         LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType size";
316         return false;
317     } else {
318         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
319             if (values[j].asString().compare("SENSOR") == 0) {
320                 linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
321             } else if (values[j].asString().compare("ODPM") == 0) {
322                 linked_sensors_type.emplace_back(SensorFusionType::ODPM);
323             } else if (values[j].asString().compare("CONSTANT") == 0) {
324                 linked_sensors_type.emplace_back(SensorFusionType::CONSTANT);
325             } else {
326                 LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType settings "
327                            << values[j].asString();
328                 return false;
329             }
330             LOG(INFO) << "Sensor[" << name << "]'s CombinationType[" << j
331                       << "]: " << linked_sensors_type[j];
332         }
333     }
334 
335     values = sensor["Coefficient"];
336     if (values.size()) {
337         coefficients.reserve(values.size());
338         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
339             coefficients.emplace_back(values[j].asString());
340             LOG(INFO) << "Sensor[" << name << "]'s coefficient[" << j << "]: " << coefficients[j];
341         }
342     } else if ((formula != FormulaOption::USE_ML_MODEL)) {
343         LOG(ERROR) << "Sensor[" << name << "] has no Coefficient setting";
344         return false;
345     }
346     if ((linked_sensors.size() != coefficients.size()) &&
347         (formula != FormulaOption::USE_ML_MODEL) && (formula != FormulaOption::USE_LINEAR_MODEL)) {
348         LOG(ERROR) << "Sensor[" << name << "] has invalid Coefficient size";
349         return false;
350     }
351 
352     values = sensor["CoefficientType"];
353     if (!values.size()) {
354         coefficients_type.reserve(linked_sensors.size());
355         for (size_t j = 0; j < linked_sensors.size(); ++j) {
356             coefficients_type.emplace_back(SensorFusionType::CONSTANT);
357         }
358     } else if (values.size() != coefficients.size()) {
359         LOG(ERROR) << "Sensor[" << name << "] has invalid coefficient type size";
360         return false;
361     } else {
362         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
363             if (values[j].asString().compare("CONSTANT") == 0) {
364                 coefficients_type.emplace_back(SensorFusionType::CONSTANT);
365             } else if (values[j].asString().compare("SENSOR") == 0) {
366                 coefficients_type.emplace_back(SensorFusionType::SENSOR);
367             } else if (values[j].asString().compare("ODPM") == 0) {
368                 coefficients_type.emplace_back(SensorFusionType::ODPM);
369             } else {
370                 LOG(ERROR) << "Sensor[" << name << "] has invalid coefficient options "
371                            << values[j].asString();
372                 return false;
373             }
374             LOG(INFO) << "Sensor[" << name << "]'s coefficient type[" << j
375                       << "]: " << coefficients_type[j];
376         }
377     }
378 
379     if (linked_sensors.size() != coefficients_type.size()) {
380         LOG(ERROR) << "Sensor[" << name
381                    << "]'s combination size is not matched with coefficient type size";
382         return false;
383     }
384 
385     if (!sensor["Offset"].empty()) {
386         offset = sensor["Offset"].asFloat();
387     }
388 
389     if (!sensor["BackupSensor"].empty()) {
390         backup_sensor = sensor["BackupSensor"].asString();
391     }
392 
393     values = sensor["TriggerSensor"];
394     if (!values.empty()) {
395         if (values.isString()) {
396             trigger_sensors.emplace_back(values.asString());
397             LOG(INFO) << "Sensor[" << name << "]'s TriggerSensor: " << values.asString();
398         } else if (values.size()) {
399             trigger_sensors.reserve(values.size());
400             for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
401                 if (!values[j].isString()) {
402                     LOG(ERROR) << name << " TriggerSensor should be an array of string";
403                     return false;
404                 }
405                 trigger_sensors.emplace_back(values[j].asString());
406                 LOG(INFO) << "Sensor[" << name << "]'s TriggerSensor[" << j
407                           << "]: " << trigger_sensors[j];
408             }
409         } else {
410             LOG(ERROR) << "Sensor[" << name << "]'s TriggerSensor should be a string";
411             return false;
412         }
413     }
414 
415     if (formula == FormulaOption::USE_ML_MODEL) {
416         ::thermal::vtestimator::VtEstimationInitData init_data(::thermal::vtestimator::kUseMLModel);
417         if (sensor["ModelPath"].empty()) {
418             LOG(ERROR) << "Sensor[" << name << "] has no ModelPath";
419             return false;
420         }
421 
422         if (!linked_sensors.size()) {
423             LOG(ERROR) << "Sensor[" << name << "] uses USE_ML_MODEL and has zero linked_sensors";
424             return false;
425         }
426 
427         vt_estimator = std::make_unique<::thermal::vtestimator::VirtualTempEstimator>(
428                 name, ::thermal::vtestimator::kUseMLModel, linked_sensors.size());
429         if (!vt_estimator) {
430             LOG(ERROR) << "Failed to create vt estimator for Sensor[" << name
431                        << "] with linked sensor size : " << linked_sensors.size();
432             return false;
433         }
434 
435         vt_estimator_model_file = "vendor/etc/" + sensor["ModelPath"].asString();
436         init_data.ml_model_init_data.model_path = vt_estimator_model_file;
437 
438         if (!ParseOffsetThresholds(name, sensor, &init_data.ml_model_init_data.offset_thresholds,
439                                    &init_data.ml_model_init_data.offset_values)) {
440             LOG(ERROR) << "Failed to parse offset thresholds and values for Sensor[" << name << "]";
441             return false;
442         }
443 
444         if (!sensor["PreviousSampleCount"].empty()) {
445             init_data.ml_model_init_data.use_prev_samples = true;
446             init_data.ml_model_init_data.prev_samples_order = sensor["PreviousSampleCount"].asInt();
447             LOG(INFO) << "Sensor[" << name << "] takes "
448                       << init_data.ml_model_init_data.prev_samples_order << " historic samples";
449         }
450 
451         if (!sensor["OutputLabelCount"].empty()) {
452             init_data.ml_model_init_data.output_label_count = sensor["OutputLabelCount"].asInt();
453             LOG(INFO) << "Sensor[" << name << "] outputs "
454                       << init_data.ml_model_init_data.output_label_count << " labels";
455         }
456 
457         if (!sensor["PredictHotSpotCount"].empty()) {
458             init_data.ml_model_init_data.num_hot_spots = sensor["PredictHotSpotCount"].asInt();
459             LOG(INFO) << "Sensor[" << name << "] predicts temperature at "
460                       << init_data.ml_model_init_data.num_hot_spots << " hot spots";
461         }
462 
463         if (sensor["ValidateInput"].asBool()) {
464             init_data.ml_model_init_data.enable_input_validation = true;
465             LOG(INFO) << "Sensor[" << name << "] enable input validation.";
466         }
467 
468         if (sensor["SupportUnderSampling"].asBool()) {
469             init_data.ml_model_init_data.support_under_sampling = true;
470             LOG(INFO) << "Sensor[" << name << "] supports under sampling estimation.";
471         }
472 
473         ::thermal::vtestimator::VtEstimatorStatus ret = vt_estimator->Initialize(init_data);
474         if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
475             LOG(ERROR) << "Failed to initialize vt estimator for Sensor[" << name
476                        << "] with ModelPath: " << vt_estimator_model_file
477                        << " with ret code : " << ret;
478             return false;
479         }
480 
481         LOG(INFO) << "Successfully created vt_estimator for Sensor[" << name
482                   << "] with input samples: " << linked_sensors.size();
483 
484     } else if (formula == FormulaOption::USE_LINEAR_MODEL) {
485         ::thermal::vtestimator::VtEstimationInitData init_data(
486                 ::thermal::vtestimator::kUseLinearModel);
487 
488         if ((!linked_sensors.size()) || (linked_sensors.size() > coefficients.size())) {
489             LOG(ERROR) << "Sensor[" << name
490                        << "] uses USE_LINEAR_MODEL and has invalid linked_sensors size["
491                        << linked_sensors.size() << "] or coefficients size[" << coefficients.size()
492                        << "]";
493             return false;
494         }
495 
496         vt_estimator = std::make_unique<::thermal::vtestimator::VirtualTempEstimator>(
497                 name, ::thermal::vtestimator::kUseLinearModel, linked_sensors.size());
498         if (!vt_estimator) {
499             LOG(ERROR) << "Failed to create vt estimator for Sensor[" << name
500                        << "] with linked sensor size : " << linked_sensors.size();
501             return false;
502         }
503 
504         init_data.linear_model_init_data.prev_samples_order =
505                 coefficients.size() / linked_sensors.size();
506 
507         if (!ParseOffsetThresholds(name, sensor,
508                                    &init_data.linear_model_init_data.offset_thresholds,
509                                    &init_data.linear_model_init_data.offset_values)) {
510             LOG(ERROR) << "Failed to parse offset thresholds and values for Sensor[" << name << "]";
511             return false;
512         }
513 
514         for (size_t i = 0; i < coefficients.size(); ++i) {
515             float coefficient = getFloatFromValue(coefficients[i]);
516             if (std::isnan(coefficient)) {
517                 LOG(ERROR) << "Nan coefficient unexpected for sensor " << name;
518                 return false;
519             }
520             init_data.linear_model_init_data.coefficients.emplace_back(coefficient);
521         }
522         if (coefficients.size() > linked_sensors.size()) {
523             init_data.linear_model_init_data.use_prev_samples = true;
524         }
525 
526         ::thermal::vtestimator::VtEstimatorStatus ret = vt_estimator->Initialize(init_data);
527         if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
528             LOG(ERROR) << "Failed to initialize vt estimator for Sensor[" << name
529                        << "] with ret code : " << ret;
530             return false;
531         }
532 
533         LOG(INFO) << "Successfully created vt_estimator for Sensor[" << name
534                   << "] with input samples: " << linked_sensors.size();
535     }
536 
537     virtual_sensor_info->reset(
538             new VirtualSensorInfo{linked_sensors, linked_sensors_type, coefficients,
539                                   coefficients_type, offset, trigger_sensors, formula,
540                                   vt_estimator_model_file, std::move(vt_estimator), backup_sensor});
541     return true;
542 }
543 
ParsePredictorInfo(const std::string_view name,const Json::Value & sensor,std::unique_ptr<PredictorInfo> * predictor_info)544 bool ParsePredictorInfo(const std::string_view name, const Json::Value &sensor,
545                         std::unique_ptr<PredictorInfo> *predictor_info) {
546     Json::Value predictor = sensor["PredictorInfo"];
547     if (predictor.empty()) {
548         return true;
549     }
550 
551     LOG(INFO) << "Start to parse Sensor[" << name << "]'s PredictorInfo";
552     if (predictor["Sensor"].empty()) {
553         LOG(ERROR) << "Failed to parse Sensor [" << name << "]'s PredictorInfo";
554         return false;
555     }
556 
557     std::string predict_sensor;
558     bool support_pid_compensation = false;
559     std::vector<float> prediction_weights;
560     ThrottlingArray k_p_compensate;
561     predict_sensor = predictor["Sensor"].asString();
562     LOG(INFO) << "Sensor [" << name << "]'s predictor name is " << predict_sensor;
563     // parse pid compensation configuration
564     if ((!predictor["PredictionWeight"].empty()) && (!predictor["KPCompensate"].empty())) {
565         support_pid_compensation = true;
566         if (!predictor["PredictionWeight"].size()) {
567             LOG(ERROR) << "Failed to parse PredictionWeight";
568             return false;
569         }
570         prediction_weights.reserve(predictor["PredictionWeight"].size());
571         for (Json::Value::ArrayIndex i = 0; i < predictor["PredictionWeight"].size(); ++i) {
572             float weight = predictor["PredictionWeight"][i].asFloat();
573             if (std::isnan(weight)) {
574                 LOG(ERROR) << "Unexpected NAN prediction weight for sensor [" << name << "]";
575             }
576             prediction_weights.emplace_back(weight);
577             LOG(INFO) << "Sensor[" << name << "]'s prediction weights [" << i << "]: " << weight;
578         }
579         if (!getFloatFromJsonValues(predictor["KPCompensate"], &k_p_compensate, false, false)) {
580             LOG(ERROR) << "Failed to parse KPCompensate";
581             return false;
582         }
583     }
584 
585     LOG(INFO) << "Successfully created PredictorInfo for Sensor[" << name << "]";
586     predictor_info->reset(new PredictorInfo{predict_sensor, support_pid_compensation,
587                                             prediction_weights, k_p_compensate});
588 
589     return true;
590 }
591 
ParseBindedCdevInfo(const Json::Value & values,std::unordered_map<std::string,BindedCdevInfo> * binded_cdev_info_map,const bool support_pid,bool * support_hard_limit,const std::unordered_map<std::string,std::vector<int>> & scaling_frequency_map)592 bool ParseBindedCdevInfo(
593         const Json::Value &values,
594         std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map,
595         const bool support_pid, bool *support_hard_limit,
596         const std::unordered_map<std::string, std::vector<int>> &scaling_frequency_map) {
597     for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
598         Json::Value sub_values;
599         const std::string &cdev_name = values[j]["CdevRequest"].asString();
600         ThrottlingArray cdev_weight_for_pid;
601         cdev_weight_for_pid.fill(NAN);
602         CdevArray cdev_ceiling;
603         cdev_ceiling.fill(std::numeric_limits<int>::max());
604         int max_release_step = std::numeric_limits<int>::max();
605         int max_throttle_step = std::numeric_limits<int>::max();
606         if (support_pid) {
607             if (!values[j]["CdevWeightForPID"].empty()) {
608                 LOG(INFO) << "Star to parse " << cdev_name << "'s CdevWeightForPID";
609                 if (!getFloatFromJsonValues(values[j]["CdevWeightForPID"], &cdev_weight_for_pid,
610                                             false, false)) {
611                     LOG(ERROR) << "Failed to parse CdevWeightForPID";
612                     binded_cdev_info_map->clear();
613                     return false;
614                 }
615             }
616 
617             if (!values[j]["CdevCeiling"].empty() && !values[j]["CdevCeilingFrequency"].empty()) {
618                 LOG(ERROR) << "Both CdevCeiling and CdevCeilingFrequency are configured for "
619                            << cdev_name << ", please remove one of them";
620                 binded_cdev_info_map->clear();
621                 return false;
622             }
623 
624             if (!values[j]["CdevCeiling"].empty()) {
625                 LOG(INFO) << "Start to parse CdevCeiling: " << cdev_name;
626                 if (!getIntFromJsonValues(values[j]["CdevCeiling"], &cdev_ceiling, false, false)) {
627                     LOG(ERROR) << "Failed to parse CdevCeiling for " << cdev_name;
628                     binded_cdev_info_map->clear();
629                     return false;
630                 }
631             }
632 
633             if (!values[j]["CdevCeilingFrequency"].empty()) {
634                 LOG(INFO) << "Start to parse CdevCeilingFrequency: " << cdev_name;
635                 CdevArray cdev_ceiling_frequency;
636                 if (scaling_frequency_map.find(cdev_name) == scaling_frequency_map.end()) {
637                     LOG(ERROR) << "Scaling frequency path is not found in config for " << cdev_name;
638                     binded_cdev_info_map->clear();
639                     return false;
640                 }
641                 const std::vector<int> &cdev_scaling_frequency =
642                         scaling_frequency_map.find(cdev_name)->second;
643                 if (!getIntFromJsonValues(values[j]["CdevCeilingFrequency"],
644                                           &cdev_ceiling_frequency, false, true)) {
645                     LOG(ERROR) << "Failed to parse CdevCeilingFrequency";
646                     binded_cdev_info_map->clear();
647                     return false;
648                 }
649 
650                 LOG(INFO) << "Start to search CdevCeiling based on frequency: " << cdev_name;
651                 // Find the max frequency level that is lower than or equal to CdevCeilingFrequency
652                 // value
653                 for (size_t cdev_scaling_idx = 0, cdev_ceiling_idx = 0;
654                      cdev_scaling_idx < cdev_scaling_frequency.size() &&
655                      cdev_ceiling_idx < cdev_ceiling.size();) {
656                     if (cdev_scaling_frequency.at(cdev_scaling_idx) <=
657                         cdev_ceiling_frequency.at(cdev_ceiling_idx)) {
658                         cdev_ceiling[cdev_ceiling_idx] = cdev_scaling_idx;
659                         LOG(INFO) << "[" << cdev_ceiling_idx
660                                   << "]: " << cdev_ceiling[cdev_ceiling_idx];
661                         cdev_ceiling_idx += 1;
662                     } else {
663                         cdev_scaling_idx += 1;
664                     }
665                 }
666             }
667 
668             if (!values[j]["MaxReleaseStep"].empty()) {
669                 max_release_step = getIntFromValue(values[j]["MaxReleaseStep"]);
670                 if (max_release_step < 0) {
671                     LOG(ERROR) << cdev_name << " MaxReleaseStep: " << max_release_step;
672                     binded_cdev_info_map->clear();
673                     return false;
674                 } else {
675                     LOG(INFO) << cdev_name << " MaxReleaseStep: " << max_release_step;
676                 }
677             }
678             if (!values[j]["MaxThrottleStep"].empty()) {
679                 max_throttle_step = getIntFromValue(values[j]["MaxThrottleStep"]);
680                 if (max_throttle_step < 0) {
681                     LOG(ERROR) << cdev_name << " MaxThrottleStep: " << max_throttle_step;
682                     binded_cdev_info_map->clear();
683                     return false;
684                 } else {
685                     LOG(INFO) << cdev_name << " MaxThrottleStep: " << max_throttle_step;
686                 }
687             }
688         }
689         CdevArray limit_info;
690         limit_info.fill(0);
691         ThrottlingArray power_thresholds;
692         power_thresholds.fill(NAN);
693         ReleaseLogic release_logic = ReleaseLogic::NONE;
694 
695         if (!values[j]["LimitInfo"].empty() && !values[j]["LimitInfoFrequency"].empty()) {
696             LOG(ERROR) << "Both LimitInfo and LimitInfoFrequency are configured for " << cdev_name
697                        << ", please remove one of them";
698             binded_cdev_info_map->clear();
699             return false;
700         }
701 
702         if (!values[j]["LimitInfo"].empty()) {
703             LOG(INFO) << "Start to parse LimitInfo: " << cdev_name;
704             if (!getIntFromJsonValues(values[j]["LimitInfo"], &limit_info, false, false)) {
705                 LOG(ERROR) << "Failed to parse LimitInfo";
706                 binded_cdev_info_map->clear();
707                 return false;
708             }
709             *support_hard_limit = true;
710         }
711 
712         if (!values[j]["LimitInfoFrequency"].empty()) {
713             LOG(INFO) << "Start to parse LimitInfoFrequency: " << cdev_name;
714             CdevArray limit_info_frequency;
715             if (scaling_frequency_map.find(cdev_name) == scaling_frequency_map.end()) {
716                 LOG(ERROR) << "Scaling frequency path is not found for " << cdev_name;
717                 binded_cdev_info_map->clear();
718                 return false;
719             }
720 
721             const std::vector<int> &cdev_scaling_frequency =
722                     scaling_frequency_map.find(cdev_name)->second;
723             if (!getIntFromJsonValues(values[j]["LimitInfoFrequency"], &limit_info_frequency, false,
724                                       true)) {
725                 LOG(ERROR) << "Failed to parse LimitInfoFrequency for " << cdev_name;
726                 binded_cdev_info_map->clear();
727                 return false;
728             }
729 
730             LOG(INFO) << "Start to search LimitInfo based on frequency: " << cdev_name;
731             // Find the max frequency level that is lower than or equal to imitInfoFrequency value
732             for (size_t cdev_scaling_idx = 0, limit_info_idx = 0;
733                  cdev_scaling_idx < cdev_scaling_frequency.size() &&
734                  limit_info_idx < limit_info.size();) {
735                 if (cdev_scaling_frequency.at(cdev_scaling_idx) <=
736                     limit_info_frequency.at(limit_info_idx)) {
737                     limit_info[limit_info_idx] = cdev_scaling_idx;
738                     LOG(INFO) << "[" << limit_info_idx << "]: " << limit_info[limit_info_idx];
739                     limit_info_idx += 1;
740                 } else {
741                     cdev_scaling_idx += 1;
742                 }
743             }
744             *support_hard_limit = true;
745         }
746         // Parse linked power info
747         std::string power_rail;
748         bool high_power_check = false;
749         bool throttling_with_power_link = false;
750         bool enabled = true;
751         CdevArray cdev_floor_with_power_link;
752         cdev_floor_with_power_link.fill(0);
753 
754         const bool power_link_disabled =
755                 ::android::base::GetBoolProperty(kPowerLinkDisabledProperty.data(), false);
756         if (!power_link_disabled) {
757             power_rail = values[j]["BindedPowerRail"].asString();
758 
759             if (values[j]["HighPowerCheck"].asBool()) {
760                 high_power_check = true;
761             }
762             LOG(INFO) << "Highpowercheck: " << std::boolalpha << high_power_check;
763 
764             if (values[j]["ThrottlingWithPowerLink"].asBool()) {
765                 throttling_with_power_link = true;
766             }
767             LOG(INFO) << "ThrottlingwithPowerLink: " << std::boolalpha
768                       << throttling_with_power_link;
769 
770             sub_values = values[j]["CdevFloorWithPowerLink"];
771             if (sub_values.size()) {
772                 LOG(INFO) << "Start to parse " << cdev_name << "'s CdevFloorWithPowerLink";
773                 if (!getIntFromJsonValues(sub_values, &cdev_floor_with_power_link, false, false)) {
774                     LOG(ERROR) << "Failed to parse CdevFloor";
775                     binded_cdev_info_map->clear();
776                     return false;
777                 }
778             }
779             sub_values = values[j]["PowerThreshold"];
780             if (sub_values.size()) {
781                 LOG(INFO) << "Start to parse " << cdev_name << "'s PowerThreshold";
782                 if (!getFloatFromJsonValues(sub_values, &power_thresholds, false, false)) {
783                     LOG(ERROR) << "Failed to parse power thresholds";
784                     binded_cdev_info_map->clear();
785                     return false;
786                 }
787                 if (values[j]["ReleaseLogic"].asString() == "INCREASE") {
788                     release_logic = ReleaseLogic::INCREASE;
789                     LOG(INFO) << "Release logic: INCREASE";
790                 } else if (values[j]["ReleaseLogic"].asString() == "DECREASE") {
791                     release_logic = ReleaseLogic::DECREASE;
792                     LOG(INFO) << "Release logic: DECREASE";
793                 } else if (values[j]["ReleaseLogic"].asString() == "STEPWISE") {
794                     release_logic = ReleaseLogic::STEPWISE;
795                     LOG(INFO) << "Release logic: STEPWISE";
796                 } else if (values[j]["ReleaseLogic"].asString() == "RELEASE_TO_FLOOR") {
797                     release_logic = ReleaseLogic::RELEASE_TO_FLOOR;
798                     LOG(INFO) << "Release logic: RELEASE_TO_FLOOR";
799                 } else {
800                     LOG(ERROR) << "Release logic is invalid";
801                     binded_cdev_info_map->clear();
802                     return false;
803                 }
804             }
805         }
806         if (values[j]["Disabled"].asBool()) {
807             enabled = false;
808         }
809 
810         (*binded_cdev_info_map)[cdev_name] = {
811                 .limit_info = limit_info,
812                 .power_thresholds = power_thresholds,
813                 .release_logic = release_logic,
814                 .cdev_weight_for_pid = cdev_weight_for_pid,
815                 .cdev_ceiling = cdev_ceiling,
816                 .max_release_step = max_release_step,
817                 .max_throttle_step = max_throttle_step,
818                 .cdev_floor_with_power_link = cdev_floor_with_power_link,
819                 .power_rail = power_rail,
820                 .high_power_check = high_power_check,
821                 .throttling_with_power_link = throttling_with_power_link,
822                 .enabled = enabled,
823         };
824     }
825     return true;
826 }
827 
ParseSensorThrottlingInfo(const std::string_view name,const Json::Value & sensor,bool * support_throttling,std::shared_ptr<ThrottlingInfo> * throttling_info,const std::unordered_map<std::string,std::vector<int>> & scaling_frequency_map)828 bool ParseSensorThrottlingInfo(
829         const std::string_view name, const Json::Value &sensor, bool *support_throttling,
830         std::shared_ptr<ThrottlingInfo> *throttling_info,
831         const std::unordered_map<std::string, std::vector<int>> &scaling_frequency_map) {
832     std::array<float, kThrottlingSeverityCount> k_po;
833     k_po.fill(0.0);
834     std::array<float, kThrottlingSeverityCount> k_pu;
835     k_pu.fill(0.0);
836     std::array<float, kThrottlingSeverityCount> k_i;
837     k_i.fill(0.0);
838     std::array<float, kThrottlingSeverityCount> k_d;
839     k_d.fill(0.0);
840     std::array<float, kThrottlingSeverityCount> i_max;
841     i_max.fill(NAN);
842     std::array<float, kThrottlingSeverityCount> max_alloc_power;
843     max_alloc_power.fill(NAN);
844     std::array<float, kThrottlingSeverityCount> min_alloc_power;
845     min_alloc_power.fill(NAN);
846     std::array<float, kThrottlingSeverityCount> s_power;
847     s_power.fill(NAN);
848     std::array<float, kThrottlingSeverityCount> i_cutoff;
849     i_cutoff.fill(NAN);
850     float i_default = 0.0;
851     float i_default_pct = NAN;
852     int tran_cycle = 0;
853     bool support_pid = false;
854     bool support_hard_limit = false;
855 
856     // Parse PID parameters
857     if (!sensor["PIDInfo"].empty()) {
858         LOG(INFO) << "Start to parse"
859                   << " Sensor[" << name << "]'s K_Po";
860         if (sensor["PIDInfo"]["K_Po"].empty() ||
861             !getFloatFromJsonValues(sensor["PIDInfo"]["K_Po"], &k_po, false, false)) {
862             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Po";
863             return false;
864         }
865         LOG(INFO) << "Start to parse"
866                   << " Sensor[" << name << "]'s  K_Pu";
867         if (sensor["PIDInfo"]["K_Pu"].empty() ||
868             !getFloatFromJsonValues(sensor["PIDInfo"]["K_Pu"], &k_pu, false, false)) {
869             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Pu";
870             return false;
871         }
872         LOG(INFO) << "Start to parse"
873                   << " Sensor[" << name << "]'s K_I";
874         if (sensor["PIDInfo"]["K_I"].empty() ||
875             !getFloatFromJsonValues(sensor["PIDInfo"]["K_I"], &k_i, false, false)) {
876             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_I";
877             return false;
878         }
879         LOG(INFO) << "Start to parse"
880                   << " Sensor[" << name << "]'s K_D";
881         if (sensor["PIDInfo"]["K_D"].empty() ||
882             !getFloatFromJsonValues(sensor["PIDInfo"]["K_D"], &k_d, false, false)) {
883             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_D";
884             return false;
885         }
886         LOG(INFO) << "Start to parse"
887                   << " Sensor[" << name << "]'s I_Max";
888         if (sensor["PIDInfo"]["I_Max"].empty() ||
889             !getFloatFromJsonValues(sensor["PIDInfo"]["I_Max"], &i_max, false, false)) {
890             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Max";
891             return false;
892         }
893         LOG(INFO) << "Start to parse"
894                   << " Sensor[" << name << "]'s MaxAllocPower";
895         if (sensor["PIDInfo"]["MaxAllocPower"].empty() ||
896             !getFloatFromJsonValues(sensor["PIDInfo"]["MaxAllocPower"], &max_alloc_power, false,
897                                     true)) {
898             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MaxAllocPower";
899             return false;
900         }
901         LOG(INFO) << "Start to parse"
902                   << " Sensor[" << name << "]'s MinAllocPower";
903         if (sensor["PIDInfo"]["MinAllocPower"].empty() ||
904             !getFloatFromJsonValues(sensor["PIDInfo"]["MinAllocPower"], &min_alloc_power, false,
905                                     true)) {
906             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MinAllocPower";
907             return false;
908         }
909         LOG(INFO) << "Start to parse Sensor[" << name << "]'s S_Power";
910         if (sensor["PIDInfo"]["S_Power"].empty() ||
911             !getFloatFromJsonValues(sensor["PIDInfo"]["S_Power"], &s_power, false, true)) {
912             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse S_Power";
913             return false;
914         }
915         LOG(INFO) << "Start to parse Sensor[" << name << "]'s I_Cutoff";
916         if (sensor["PIDInfo"]["I_Cutoff"].empty() ||
917             !getFloatFromJsonValues(sensor["PIDInfo"]["I_Cutoff"], &i_cutoff, false, false)) {
918             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Cutoff";
919             return false;
920         }
921 
922         if (!sensor["PIDInfo"]["I_Default"].empty() &&
923             !sensor["PIDInfo"]["I_Default_Pct"].empty()) {
924             LOG(ERROR) << "I_Default and I_Default_P cannot be applied together";
925             return false;
926         }
927 
928         if (!sensor["PIDInfo"]["I_Default"].empty()) {
929             i_default = getFloatFromValue(sensor["PIDInfo"]["I_Default"]);
930             LOG(INFO) << "Sensor[" << name << "]'s I_Default: " << i_default;
931         } else if (!sensor["PIDInfo"]["I_Default_Pct"].empty()) {
932             i_default_pct = getFloatFromValue(sensor["PIDInfo"]["I_Default_Pct"]);
933             LOG(INFO) << "Sensor[" << name << "]'s I_Default_Pct: " << i_default_pct;
934         }
935         tran_cycle = getFloatFromValue(sensor["PIDInfo"]["TranCycle"]);
936         LOG(INFO) << "Sensor[" << name << "]'s TranCycle: " << tran_cycle;
937 
938         // Confirm we have at least one valid PID combination
939         bool valid_pid_combination = false;
940         for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
941             if (!std::isnan(s_power[j])) {
942                 if (std::isnan(k_po[j]) || std::isnan(k_pu[j]) || std::isnan(k_i[j]) ||
943                     std::isnan(k_d[j]) || std::isnan(i_max[j]) || std::isnan(max_alloc_power[j]) ||
944                     std::isnan(min_alloc_power[j]) || std::isnan(i_cutoff[j])) {
945                     valid_pid_combination = false;
946                     break;
947                 } else {
948                     valid_pid_combination = true;
949                 }
950             }
951         }
952         if (!valid_pid_combination) {
953             LOG(ERROR) << "Sensor[" << name << "]: Invalid PID parameters combinations";
954             return false;
955         } else {
956             support_pid = true;
957         }
958     }
959 
960     // Parse binded cooling device
961     std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
962     if (!ParseBindedCdevInfo(sensor["BindedCdevInfo"], &binded_cdev_info_map, support_pid,
963                              &support_hard_limit, scaling_frequency_map)) {
964         LOG(ERROR) << "Sensor[" << name << "]: failed to parse BindedCdevInfo";
965         return false;
966     }
967 
968     Json::Value values;
969     ProfileMap profile_map;
970     values = sensor["Profile"];
971     for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
972         Json::Value sub_values;
973         const std::string &mode = values[j]["Mode"].asString();
974         std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map_profile;
975         if (!ParseBindedCdevInfo(values[j]["BindedCdevInfo"], &binded_cdev_info_map_profile,
976                                  support_pid, &support_hard_limit, scaling_frequency_map)) {
977             LOG(ERROR) << "Sensor[" << name << " failed to parse BindedCdevInfo profile";
978         }
979         // Check if the binded_cdev_info_map_profile is valid
980         if (binded_cdev_info_map.size() != binded_cdev_info_map_profile.size()) {
981             LOG(ERROR) << "Sensor[" << name << "]:'s profile map size should not be changed";
982             return false;
983         } else {
984             for (const auto &binded_cdev_info_pair : binded_cdev_info_map_profile) {
985                 if (binded_cdev_info_map.count(binded_cdev_info_pair.first)) {
986                     if (binded_cdev_info_pair.second.power_rail !=
987                         binded_cdev_info_map.at(binded_cdev_info_pair.first).power_rail) {
988                         LOG(ERROR) << "Sensor[" << name << "]:'s profile " << mode << " binded "
989                                    << binded_cdev_info_pair.first
990                                    << "'s power rail is not included in default rules";
991                         return false;
992                     } else {
993                         LOG(INFO) << "Sensor[" << name << "]:'s profile " << mode
994                                   << " is parsed successfully";
995                     }
996                 } else {
997                     LOG(ERROR) << "Sensor[" << name << "]'s profile " << mode << " binded "
998                                << binded_cdev_info_pair.first
999                                << " is not included in default rules";
1000                     return false;
1001                 }
1002             }
1003         }
1004         profile_map[mode] = binded_cdev_info_map_profile;
1005     }
1006 
1007     std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
1008     values = sensor["ExcludedPowerInfo"];
1009     for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1010         Json::Value sub_values;
1011         const std::string &power_rail = values[j]["PowerRail"].asString();
1012         if (power_rail.empty()) {
1013             LOG(ERROR) << "Sensor[" << name << "] failed to parse excluded PowerRail";
1014             return false;
1015         }
1016         ThrottlingArray power_weight;
1017         power_weight.fill(1);
1018         if (!values[j]["PowerWeight"].empty()) {
1019             LOG(INFO) << "Sensor[" << name << "]: Start to parse " << power_rail
1020                       << "'s PowerWeight";
1021             if (!getFloatFromJsonValues(values[j]["PowerWeight"], &power_weight, false, false)) {
1022                 LOG(ERROR) << "Failed to parse PowerWeight";
1023                 return false;
1024             }
1025         }
1026         excluded_power_info_map[power_rail] = power_weight;
1027     }
1028     throttling_info->reset(new ThrottlingInfo{k_po, k_pu, k_i, k_d, i_max, max_alloc_power,
1029                                               min_alloc_power, s_power, i_cutoff, i_default,
1030                                               i_default_pct, tran_cycle, excluded_power_info_map,
1031                                               binded_cdev_info_map, profile_map});
1032     *support_throttling = support_pid | support_hard_limit;
1033     return true;
1034 }
1035 
ParseSensorInfo(const Json::Value & config,std::unordered_map<std::string,SensorInfo> * sensors_parsed)1036 bool ParseSensorInfo(const Json::Value &config,
1037                      std::unordered_map<std::string, SensorInfo> *sensors_parsed) {
1038     Json::Value sensors = config["Sensors"];
1039     Json::Value cdevs = config["CoolingDevices"];
1040     std::unordered_map<std::string, std::vector<int>> scaling_frequency_map;
1041 
1042     LOG(INFO) << "Start reading ScalingAvailableFrequenciesPath from config";
1043     for (Json::Value::ArrayIndex i = 0; i < cdevs.size(); ++i) {
1044         if (cdevs[i]["ScalingAvailableFrequenciesPath"].empty()) {
1045             continue;
1046         }
1047 
1048         const std::string &path = cdevs[i]["ScalingAvailableFrequenciesPath"].asString();
1049         const std::string &name = cdevs[i]["Name"].asString();
1050         LOG(INFO) << "Cdev[" << name << "]'s scaling frequency path: " << path;
1051         std::string scaling_frequency_str;
1052         if (::android::base::ReadFileToString(path, &scaling_frequency_str)) {
1053             std::istringstream frequencies(scaling_frequency_str);
1054             int frequency;
1055             while (frequencies >> frequency) {
1056                 LOG(INFO) << "Cdev[" << name << "]'s available frequency: " << frequency;
1057                 scaling_frequency_map[name].push_back(frequency);
1058             }
1059 
1060             // Reverse the vector if it starts from small value
1061             if (scaling_frequency_map[name].front() < scaling_frequency_map[name].back()) {
1062                 std::reverse(scaling_frequency_map[name].begin(),
1063                              scaling_frequency_map[name].end());
1064             }
1065 
1066             // Make sure the scaling frequencies strictly decreasing
1067             if (std::adjacent_find(scaling_frequency_map[name].begin(),
1068                                    scaling_frequency_map[name].end(),
1069                                    std::less_equal<int>()) != scaling_frequency_map[name].end()) {
1070                 LOG(ERROR) << "Cdev[" << name << "]'s scaling frequencies is not monotonic";
1071                 sensors_parsed->clear();
1072                 return false;
1073             }
1074         } else {
1075             LOG(ERROR) << "Cdev[" << name << "]'s scaling frequency path is invalid.";
1076             sensors_parsed->clear();
1077             return false;
1078         }
1079     }
1080 
1081     std::size_t total_parsed = 0;
1082     std::unordered_set<std::string> sensors_name_parsed;
1083 
1084     for (Json::Value::ArrayIndex i = 0; i < sensors.size(); ++i) {
1085         const std::string &name = sensors[i]["Name"].asString();
1086         LOG(INFO) << "Sensor[" << i << "]'s Name: " << name;
1087         if (name.empty()) {
1088             LOG(ERROR) << "Failed to read Sensor[" << i << "]'s Name";
1089             sensors_parsed->clear();
1090             return false;
1091         }
1092 
1093         auto result = sensors_name_parsed.insert(name);
1094         if (!result.second) {
1095             LOG(ERROR) << "Duplicate Sensor[" << i << "]'s Name";
1096             sensors_parsed->clear();
1097             return false;
1098         }
1099 
1100         std::string sensor_type_str = sensors[i]["Type"].asString();
1101         LOG(INFO) << "Sensor[" << name << "]'s Type: " << sensor_type_str;
1102         TemperatureType sensor_type;
1103 
1104         if (!getTypeFromString(sensor_type_str, &sensor_type)) {
1105             LOG(ERROR) << "Invalid Sensor[" << name << "]'s Type: " << sensor_type_str;
1106             sensors_parsed->clear();
1107             return false;
1108         }
1109 
1110         bool send_cb = false;
1111         if (!sensors[i]["Monitor"].empty() && sensors[i]["Monitor"].isBool()) {
1112             send_cb = sensors[i]["Monitor"].asBool();
1113         } else if (!sensors[i]["SendCallback"].empty() && sensors[i]["SendCallback"].isBool()) {
1114             send_cb = sensors[i]["SendCallback"].asBool();
1115         }
1116         LOG(INFO) << "Sensor[" << name << "]'s SendCallback: " << std::boolalpha << send_cb
1117                   << std::noboolalpha;
1118 
1119         bool send_powerhint = false;
1120         if (sensors[i]["SendPowerHint"].empty() || !sensors[i]["SendPowerHint"].isBool()) {
1121             LOG(INFO) << "Failed to read Sensor[" << name << "]'s SendPowerHint, set to 'false'";
1122         } else if (sensors[i]["SendPowerHint"].asBool()) {
1123             send_powerhint = true;
1124         }
1125         LOG(INFO) << "Sensor[" << name << "]'s SendPowerHint: " << std::boolalpha << send_powerhint
1126                   << std::noboolalpha;
1127 
1128         bool is_hidden = false;
1129         if (sensors[i]["Hidden"].empty() || !sensors[i]["Hidden"].isBool()) {
1130             LOG(INFO) << "Failed to read Sensor[" << name << "]'s Hidden, set to 'false'";
1131         } else if (sensors[i]["Hidden"].asBool()) {
1132             is_hidden = true;
1133         }
1134         LOG(INFO) << "Sensor[" << name << "]'s Hidden: " << std::boolalpha << is_hidden
1135                   << std::noboolalpha;
1136 
1137         std::array<float, kThrottlingSeverityCount> hot_thresholds;
1138         hot_thresholds.fill(NAN);
1139         std::array<float, kThrottlingSeverityCount> cold_thresholds;
1140         cold_thresholds.fill(NAN);
1141         std::array<float, kThrottlingSeverityCount> hot_hysteresis;
1142         hot_hysteresis.fill(0.0);
1143         std::array<float, kThrottlingSeverityCount> cold_hysteresis;
1144         cold_hysteresis.fill(0.0);
1145 
1146         Json::Value values = sensors[i]["HotThreshold"];
1147         if (!values.size()) {
1148             LOG(INFO) << "Sensor[" << name << "]'s HotThreshold, default all to NAN";
1149         } else if (values.size() != kThrottlingSeverityCount) {
1150             LOG(ERROR) << "Invalid Sensor[" << name << "]'s HotThreshold count:" << values.size();
1151             sensors_parsed->clear();
1152             return false;
1153         } else {
1154             float min = std::numeric_limits<float>::min();
1155             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1156                 hot_thresholds[j] = getFloatFromValue(values[j]);
1157                 if (!std::isnan(hot_thresholds[j])) {
1158                     if (hot_thresholds[j] < min) {
1159                         LOG(ERROR) << "Invalid "
1160                                    << "Sensor[" << name << "]'s HotThreshold[j" << j
1161                                    << "]: " << hot_thresholds[j] << " < " << min;
1162                         sensors_parsed->clear();
1163                         return false;
1164                     }
1165                     min = hot_thresholds[j];
1166                 }
1167                 LOG(INFO) << "Sensor[" << name << "]'s HotThreshold[" << j
1168                           << "]: " << hot_thresholds[j];
1169             }
1170         }
1171 
1172         values = sensors[i]["HotHysteresis"];
1173         if (!values.size()) {
1174             LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis, default all to 0.0";
1175         } else if (values.size() != kThrottlingSeverityCount) {
1176             LOG(ERROR) << "Invalid Sensor[" << name << "]'s HotHysteresis, count:" << values.size();
1177             sensors_parsed->clear();
1178             return false;
1179         } else {
1180             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1181                 hot_hysteresis[j] = getFloatFromValue(values[j]);
1182                 if (std::isnan(hot_hysteresis[j])) {
1183                     LOG(ERROR) << "Invalid Sensor[" << name
1184                                << "]'s HotHysteresis: " << hot_hysteresis[j];
1185                     sensors_parsed->clear();
1186                     return false;
1187                 }
1188                 LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis[" << j
1189                           << "]: " << hot_hysteresis[j];
1190             }
1191         }
1192 
1193         for (Json::Value::ArrayIndex j = 0; j < (kThrottlingSeverityCount - 1); ++j) {
1194             if (std::isnan(hot_thresholds[j])) {
1195                 continue;
1196             }
1197             for (auto k = j + 1; k < kThrottlingSeverityCount; ++k) {
1198                 if (std::isnan(hot_thresholds[k])) {
1199                     continue;
1200                 } else if (hot_thresholds[j] > (hot_thresholds[k] - hot_hysteresis[k])) {
1201                     LOG(ERROR) << "Sensor[" << name << "]'s hot threshold " << j
1202                                << " is overlapped";
1203                     sensors_parsed->clear();
1204                     return false;
1205                 } else {
1206                     break;
1207                 }
1208             }
1209         }
1210 
1211         values = sensors[i]["ColdThreshold"];
1212         if (!values.size()) {
1213             LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold, default all to NAN";
1214         } else if (values.size() != kThrottlingSeverityCount) {
1215             LOG(ERROR) << "Invalid Sensor[" << name << "]'s ColdThreshold count:" << values.size();
1216             sensors_parsed->clear();
1217             return false;
1218         } else {
1219             float max = std::numeric_limits<float>::max();
1220             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1221                 cold_thresholds[j] = getFloatFromValue(values[j]);
1222                 if (!std::isnan(cold_thresholds[j])) {
1223                     if (cold_thresholds[j] > max) {
1224                         LOG(ERROR) << "Invalid "
1225                                    << "Sensor[" << name << "]'s ColdThreshold[j" << j
1226                                    << "]: " << cold_thresholds[j] << " > " << max;
1227                         sensors_parsed->clear();
1228                         return false;
1229                     }
1230                     max = cold_thresholds[j];
1231                 }
1232                 LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold[" << j
1233                           << "]: " << cold_thresholds[j];
1234             }
1235         }
1236 
1237         values = sensors[i]["ColdHysteresis"];
1238         if (!values.size()) {
1239             LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis, default all to 0.0";
1240         } else if (values.size() != kThrottlingSeverityCount) {
1241             LOG(ERROR) << "Invalid Sensor[" << name << "]'s ColdHysteresis count:" << values.size();
1242             sensors_parsed->clear();
1243             return false;
1244         } else {
1245             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1246                 cold_hysteresis[j] = getFloatFromValue(values[j]);
1247                 if (std::isnan(cold_hysteresis[j])) {
1248                     LOG(ERROR) << "Invalid Sensor[" << name
1249                                << "]'s ColdHysteresis: " << cold_hysteresis[j];
1250                     sensors_parsed->clear();
1251                     return false;
1252                 }
1253                 LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis[" << j
1254                           << "]: " << cold_hysteresis[j];
1255             }
1256         }
1257 
1258         for (Json::Value::ArrayIndex j = 0; j < (kThrottlingSeverityCount - 1); ++j) {
1259             if (std::isnan(cold_thresholds[j])) {
1260                 continue;
1261             }
1262             for (auto k = j + 1; k < kThrottlingSeverityCount; ++k) {
1263                 if (std::isnan(cold_thresholds[k])) {
1264                     continue;
1265                 } else if (cold_thresholds[j] < (cold_thresholds[k] + cold_hysteresis[k])) {
1266                     LOG(ERROR) << "Sensor[" << name << "]'s cold threshold " << j
1267                                << " is overlapped";
1268                     sensors_parsed->clear();
1269                     return false;
1270                 } else {
1271                     break;
1272                 }
1273             }
1274         }
1275 
1276         std::string temp_path;
1277         if (!sensors[i]["TempPath"].empty()) {
1278             temp_path = sensors[i]["TempPath"].asString();
1279             LOG(INFO) << "Sensor[" << name << "]'s TempPath: " << temp_path;
1280         }
1281 
1282         float vr_threshold = NAN;
1283         if (!sensors[i]["VrThreshold"].empty()) {
1284             vr_threshold = getFloatFromValue(sensors[i]["VrThreshold"]);
1285             LOG(INFO) << "Sensor[" << name << "]'s VrThreshold: " << vr_threshold;
1286         }
1287 
1288         float multiplier = 1.0;
1289         if (!sensors[i]["Multiplier"].empty()) {
1290             multiplier = sensors[i]["Multiplier"].asFloat();
1291         }
1292         LOG(INFO) << "Sensor[" << name << "]'s Multiplier: " << multiplier;
1293 
1294         std::chrono::milliseconds polling_delay = kUeventPollTimeoutMs;
1295         if (!sensors[i]["PollingDelay"].empty()) {
1296             const auto value = getIntFromValue(sensors[i]["PollingDelay"]);
1297             polling_delay = (value > 0) ? std::chrono::milliseconds(value)
1298                                         : std::chrono::milliseconds::max();
1299         }
1300         LOG(INFO) << "Sensor[" << name << "]'s Polling delay: " << polling_delay.count();
1301 
1302         std::chrono::milliseconds passive_delay = kMinPollIntervalMs;
1303         if (!sensors[i]["PassiveDelay"].empty()) {
1304             const auto value = getIntFromValue(sensors[i]["PassiveDelay"]);
1305             passive_delay = (value > 0) ? std::chrono::milliseconds(value)
1306                                         : std::chrono::milliseconds::max();
1307         }
1308         LOG(INFO) << "Sensor[" << name << "]'s Passive delay: " << passive_delay.count();
1309 
1310         std::chrono::milliseconds time_resolution;
1311         if (sensors[i]["TimeResolution"].empty()) {
1312             time_resolution = kMinPollIntervalMs;
1313         } else {
1314             time_resolution =
1315                     std::chrono::milliseconds(getIntFromValue(sensors[i]["TimeResolution"]));
1316         }
1317         LOG(INFO) << "Sensor[" << name << "]'s Time resolution: " << time_resolution.count();
1318 
1319         float step_ratio = NAN;
1320         if (!sensors[i]["StepRatio"].empty()) {
1321             step_ratio = sensors[i]["StepRatio"].asFloat();
1322             if (step_ratio < 0 || step_ratio > 1) {
1323                 LOG(ERROR) << "Sensor[" << name << "]'s StepRatio should be set 0 ~ 1";
1324                 sensors_parsed->clear();
1325                 return false;
1326             }
1327 
1328             if (sensors[i]["PassiveDelay"].empty()) {
1329                 LOG(ERROR) << "Sensor[" << name << "] has StepRatio but no explicit PassiveDelay";
1330                 sensors_parsed->clear();
1331                 return false;
1332             }
1333         }
1334 
1335         if (is_hidden && send_cb) {
1336             LOG(ERROR) << "is_hidden and send_cb cannot be enabled together";
1337             sensors_parsed->clear();
1338             return false;
1339         }
1340 
1341         std::unique_ptr<VirtualSensorInfo> virtual_sensor_info;
1342         if (!ParseVirtualSensorInfo(name, sensors[i], &virtual_sensor_info)) {
1343             LOG(ERROR) << "Sensor[" << name << "]: failed to parse virtual sensor info";
1344             sensors_parsed->clear();
1345             return false;
1346         }
1347 
1348         std::unique_ptr<PredictorInfo> predictor_info;
1349         if (!ParsePredictorInfo(name, sensors[i], &predictor_info)) {
1350             LOG(ERROR) << "Sensor[" << name << "]: failed to parse virtual sensor info";
1351             sensors_parsed->clear();
1352             return false;
1353         }
1354 
1355         bool support_throttling = false;  // support pid or hard limit
1356         std::shared_ptr<ThrottlingInfo> throttling_info;
1357         if (!ParseSensorThrottlingInfo(name, sensors[i], &support_throttling, &throttling_info,
1358                                        scaling_frequency_map)) {
1359             LOG(ERROR) << "Sensor[" << name << "]: failed to parse throttling info";
1360             sensors_parsed->clear();
1361             return false;
1362         }
1363 
1364         bool is_watch = (send_cb | send_powerhint | support_throttling);
1365         LOG(INFO) << "Sensor[" << name << "]'s is_watch: " << std::boolalpha << is_watch;
1366 
1367         (*sensors_parsed)[name] = {
1368                 .type = sensor_type,
1369                 .hot_thresholds = hot_thresholds,
1370                 .cold_thresholds = cold_thresholds,
1371                 .hot_hysteresis = hot_hysteresis,
1372                 .cold_hysteresis = cold_hysteresis,
1373                 .temp_path = temp_path,
1374                 .vr_threshold = vr_threshold,
1375                 .multiplier = multiplier,
1376                 .polling_delay = polling_delay,
1377                 .passive_delay = passive_delay,
1378                 .time_resolution = time_resolution,
1379                 .step_ratio = step_ratio,
1380                 .send_cb = send_cb,
1381                 .send_powerhint = send_powerhint,
1382                 .is_watch = is_watch,
1383                 .is_hidden = is_hidden,
1384                 .virtual_sensor_info = std::move(virtual_sensor_info),
1385                 .throttling_info = std::move(throttling_info),
1386                 .predictor_info = std::move(predictor_info),
1387         };
1388 
1389         ++total_parsed;
1390     }
1391     LOG(INFO) << total_parsed << " Sensors parsed successfully";
1392     return true;
1393 }
1394 
ParseCoolingDevice(const Json::Value & config,std::unordered_map<std::string,CdevInfo> * cooling_devices_parsed)1395 bool ParseCoolingDevice(const Json::Value &config,
1396                         std::unordered_map<std::string, CdevInfo> *cooling_devices_parsed) {
1397     Json::Value cooling_devices = config["CoolingDevices"];
1398     std::size_t total_parsed = 0;
1399     std::unordered_set<std::string> cooling_devices_name_parsed;
1400 
1401     for (Json::Value::ArrayIndex i = 0; i < cooling_devices.size(); ++i) {
1402         const std::string &name = cooling_devices[i]["Name"].asString();
1403         LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name;
1404         if (name.empty()) {
1405             LOG(ERROR) << "Failed to read CoolingDevice[" << i << "]'s Name";
1406             cooling_devices_parsed->clear();
1407             return false;
1408         }
1409 
1410         auto result = cooling_devices_name_parsed.insert(name.data());
1411         if (!result.second) {
1412             LOG(ERROR) << "Duplicate CoolingDevice[" << i << "]'s Name";
1413             cooling_devices_parsed->clear();
1414             return false;
1415         }
1416 
1417         std::string cooling_device_type_str = cooling_devices[i]["Type"].asString();
1418         LOG(INFO) << "CoolingDevice[" << name << "]'s Type: " << cooling_device_type_str;
1419         CoolingType cooling_device_type;
1420 
1421         if (!getTypeFromString(cooling_device_type_str, &cooling_device_type)) {
1422             LOG(ERROR) << "Invalid CoolingDevice[" << name
1423                        << "]'s Type: " << cooling_device_type_str;
1424             cooling_devices_parsed->clear();
1425             return false;
1426         }
1427 
1428         const std::string &read_path = cooling_devices[i]["ReadPath"].asString();
1429         LOG(INFO) << "Cdev Read Path: " << (read_path.empty() ? "default" : read_path);
1430 
1431         const std::string &write_path = cooling_devices[i]["WritePath"].asString();
1432         LOG(INFO) << "Cdev Write Path: " << (write_path.empty() ? "default" : write_path);
1433 
1434         std::vector<float> state2power;
1435         Json::Value values = cooling_devices[i]["State2Power"];
1436         if (values.size()) {
1437             state2power.reserve(values.size());
1438             for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1439                 state2power.emplace_back(getFloatFromValue(values[j]));
1440                 LOG(INFO) << "Cooling device[" << name << "]'s Power2State[" << j
1441                           << "]: " << state2power[j];
1442                 if (j > 0 && state2power[j] < state2power[j - 1]) {
1443                     LOG(ERROR) << "Higher power with higher state on cooling device " << name
1444                                << "'s state" << j;
1445                 }
1446             }
1447         } else {
1448             LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name
1449                       << " does not support State2Power";
1450         }
1451 
1452         const std::string &power_rail = cooling_devices[i]["PowerRail"].asString();
1453         LOG(INFO) << "Cooling device power rail : " << power_rail;
1454 
1455         (*cooling_devices_parsed)[name] = {
1456                 .type = cooling_device_type,
1457                 .read_path = read_path,
1458                 .write_path = write_path,
1459                 .state2power = state2power,
1460         };
1461         ++total_parsed;
1462     }
1463     LOG(INFO) << total_parsed << " CoolingDevices parsed successfully";
1464     return true;
1465 }
1466 
ParsePowerRailInfo(const Json::Value & config,std::unordered_map<std::string,PowerRailInfo> * power_rails_parsed)1467 bool ParsePowerRailInfo(const Json::Value &config,
1468                         std::unordered_map<std::string, PowerRailInfo> *power_rails_parsed) {
1469     Json::Value power_rails = config["PowerRails"];
1470     std::size_t total_parsed = 0;
1471     std::unordered_set<std::string> power_rails_name_parsed;
1472 
1473     for (Json::Value::ArrayIndex i = 0; i < power_rails.size(); ++i) {
1474         const std::string &name = power_rails[i]["Name"].asString();
1475         LOG(INFO) << "PowerRail[" << i << "]'s Name: " << name;
1476         if (name.empty()) {
1477             LOG(ERROR) << "Failed to read PowerRail[" << i << "]'s Name";
1478             power_rails_parsed->clear();
1479             return false;
1480         }
1481 
1482         std::vector<std::string> linked_power_rails;
1483         std::vector<float> coefficient;
1484         float offset = 0;
1485         FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
1486         bool is_virtual_power_rail = false;
1487         Json::Value values;
1488         int power_sample_count = 0;
1489         std::chrono::milliseconds power_sample_delay;
1490 
1491         if (!power_rails[i]["VirtualRails"].empty() && power_rails[i]["VirtualRails"].isBool()) {
1492             is_virtual_power_rail = power_rails[i]["VirtualRails"].asBool();
1493             LOG(INFO) << "PowerRails[" << name << "]'s VirtualRail, set to 'true'";
1494         }
1495 
1496         if (is_virtual_power_rail) {
1497             values = power_rails[i]["Combination"];
1498             if (values.size()) {
1499                 linked_power_rails.reserve(values.size());
1500                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1501                     linked_power_rails.emplace_back(values[j].asString());
1502                     LOG(INFO) << "PowerRail[" << name << "]'s combination[" << j
1503                               << "]: " << linked_power_rails[j];
1504                 }
1505             } else {
1506                 LOG(ERROR) << "PowerRails[" << name << "] has no combination for VirtualRail";
1507                 power_rails_parsed->clear();
1508                 return false;
1509             }
1510 
1511             values = power_rails[i]["Coefficient"];
1512             if (values.size()) {
1513                 coefficient.reserve(values.size());
1514                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1515                     coefficient.emplace_back(getFloatFromValue(values[j]));
1516                     LOG(INFO) << "PowerRail[" << name << "]'s coefficient[" << j
1517                               << "]: " << coefficient[j];
1518                 }
1519             } else {
1520                 LOG(ERROR) << "PowerRails[" << name << "] has no coefficient for VirtualRail";
1521                 power_rails_parsed->clear();
1522                 return false;
1523             }
1524 
1525             if (linked_power_rails.size() != coefficient.size()) {
1526                 LOG(ERROR) << "PowerRails[" << name
1527                            << "]'s combination size is not matched with coefficient size";
1528                 power_rails_parsed->clear();
1529                 return false;
1530             }
1531 
1532             if (!power_rails[i]["Offset"].empty()) {
1533                 offset = power_rails[i]["Offset"].asFloat();
1534             }
1535 
1536             if (linked_power_rails.size() != coefficient.size()) {
1537                 LOG(ERROR) << "PowerRails[" << name
1538                            << "]'s combination size is not matched with coefficient size";
1539                 power_rails_parsed->clear();
1540                 return false;
1541             }
1542 
1543             if (power_rails[i]["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
1544                 formula = FormulaOption::COUNT_THRESHOLD;
1545             } else if (power_rails[i]["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
1546                 formula = FormulaOption::WEIGHTED_AVG;
1547             } else if (power_rails[i]["Formula"].asString().compare("MAXIMUM") == 0) {
1548                 formula = FormulaOption::MAXIMUM;
1549             } else if (power_rails[i]["Formula"].asString().compare("MINIMUM") == 0) {
1550                 formula = FormulaOption::MINIMUM;
1551             } else {
1552                 LOG(ERROR) << "PowerRails[" << name << "]'s Formula is invalid";
1553                 power_rails_parsed->clear();
1554                 return false;
1555             }
1556         }
1557 
1558         std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
1559         if (is_virtual_power_rail) {
1560             virtual_power_rail_info.reset(
1561                     new VirtualPowerRailInfo{linked_power_rails, coefficient, offset, formula});
1562         }
1563 
1564         power_sample_count = power_rails[i]["PowerSampleCount"].asInt();
1565         LOG(INFO) << "Power sample Count: " << power_sample_count;
1566 
1567         if (!power_rails[i]["PowerSampleDelay"]) {
1568             power_sample_delay = std::chrono::milliseconds::max();
1569         } else {
1570             power_sample_delay =
1571                     std::chrono::milliseconds(getIntFromValue(power_rails[i]["PowerSampleDelay"]));
1572         }
1573 
1574         (*power_rails_parsed)[name] = {
1575                 .power_sample_count = power_sample_count,
1576                 .power_sample_delay = power_sample_delay,
1577                 .virtual_power_rail_info = std::move(virtual_power_rail_info),
1578         };
1579         ++total_parsed;
1580     }
1581     LOG(INFO) << total_parsed << " PowerRails parsed successfully";
1582     return true;
1583 }
1584 
1585 template <typename T, typename U>
ParseStatsInfo(const Json::Value & stats_config,const std::unordered_map<std::string,U> & entity_info,StatsInfo<T> * stats_info,T min_value)1586 bool ParseStatsInfo(const Json::Value &stats_config,
1587                     const std::unordered_map<std::string, U> &entity_info, StatsInfo<T> *stats_info,
1588                     T min_value) {
1589     if (stats_config.empty()) {
1590         LOG(INFO) << "No stats config";
1591         return true;
1592     }
1593     std::variant<bool, std::unordered_set<std::string>>
1594             record_by_default_threshold_all_or_name_set_ = false;
1595     if (stats_config["DefaultThresholdEnableAll"].empty() ||
1596         !stats_config["DefaultThresholdEnableAll"].isBool()) {
1597         LOG(INFO) << "Failed to read stats DefaultThresholdEnableAll, set to 'false'";
1598     } else if (stats_config["DefaultThresholdEnableAll"].asBool()) {
1599         record_by_default_threshold_all_or_name_set_ = true;
1600     }
1601     LOG(INFO) << "DefaultThresholdEnableAll " << std::boolalpha
1602               << std::get<bool>(record_by_default_threshold_all_or_name_set_) << std::noboolalpha;
1603 
1604     Json::Value values = stats_config["RecordWithDefaultThreshold"];
1605     if (values.size()) {
1606         if (std::get<bool>(record_by_default_threshold_all_or_name_set_)) {
1607             LOG(ERROR) << "Cannot enable record with default threshold when "
1608                           "DefaultThresholdEnableAll true.";
1609             return false;
1610         }
1611         record_by_default_threshold_all_or_name_set_ = std::unordered_set<std::string>();
1612         for (Json::Value::ArrayIndex i = 0; i < values.size(); ++i) {
1613             std::string name = values[i].asString();
1614             if (!entity_info.count(name)) {
1615                 LOG(ERROR) << "Unknown name [" << name << "] not present in entity_info.";
1616                 return false;
1617             }
1618             std::get<std::unordered_set<std::string>>(record_by_default_threshold_all_or_name_set_)
1619                     .insert(name);
1620         }
1621     } else {
1622         LOG(INFO) << "No stat by default threshold enabled.";
1623     }
1624 
1625     std::unordered_map<std::string, std::vector<ThresholdList<T>>> record_by_threshold;
1626     values = stats_config["RecordWithThreshold"];
1627     if (values.size()) {
1628         Json::Value threshold_values;
1629         for (Json::Value::ArrayIndex i = 0; i < values.size(); i++) {
1630             const std::string &name = values[i]["Name"].asString();
1631             if (!entity_info.count(name)) {
1632                 LOG(ERROR) << "Unknown name [" << name << "] not present in entity_info.";
1633                 return false;
1634             }
1635 
1636             std::optional<std::string> logging_name;
1637             if (!values[i]["LoggingName"].empty()) {
1638                 logging_name = values[i]["LoggingName"].asString();
1639                 LOG(INFO) << "For [" << name << "]"
1640                           << ", stats logging name is [" << logging_name.value() << "]";
1641             }
1642 
1643             LOG(INFO) << "Start to parse stats threshold for [" << name << "]";
1644             threshold_values = values[i]["Thresholds"];
1645             if (threshold_values.empty()) {
1646                 LOG(ERROR) << "Empty stats threshold not valid.";
1647                 return false;
1648             }
1649             const auto &threshold_values_count = threshold_values.size();
1650             if (threshold_values_count > kMaxStatsThresholdCount) {
1651                 LOG(ERROR) << "Number of stats threshold " << threshold_values_count
1652                            << " greater than max " << kMaxStatsThresholdCount;
1653                 return false;
1654             }
1655             std::vector<T> stats_threshold(threshold_values_count);
1656             T prev_value = min_value;
1657             LOG(INFO) << "Thresholds:";
1658             for (Json::Value::ArrayIndex i = 0; i < threshold_values_count; ++i) {
1659                 stats_threshold[i] = std::is_floating_point_v<T>
1660                                              ? getFloatFromValue(threshold_values[i])
1661                                              : getIntFromValue(threshold_values[i]);
1662                 if (stats_threshold[i] <= prev_value) {
1663                     LOG(ERROR) << "Invalid array[" << i << "]" << stats_threshold[i]
1664                                << " is <=" << prev_value;
1665                     return false;
1666                 }
1667                 prev_value = stats_threshold[i];
1668                 LOG(INFO) << "[" << i << "]: " << stats_threshold[i];
1669             }
1670             record_by_threshold[name].emplace_back(logging_name, stats_threshold);
1671         }
1672     } else {
1673         LOG(INFO) << "No stat by threshold enabled.";
1674     }
1675 
1676     (*stats_info) = {.record_by_default_threshold_all_or_name_set_ =
1677                              record_by_default_threshold_all_or_name_set_,
1678                      .record_by_threshold = record_by_threshold};
1679     return true;
1680 }
1681 
ParseSensorAbnormalStatsConfig(const Json::Value & abnormal_stats_config,const std::unordered_map<std::string,SensorInfo> & sensor_info_map_,AbnormalStatsInfo * abnormal_stats_info_parsed)1682 bool ParseSensorAbnormalStatsConfig(
1683         const Json::Value &abnormal_stats_config,
1684         const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
1685         AbnormalStatsInfo *abnormal_stats_info_parsed) {
1686     if (abnormal_stats_config.empty()) {
1687         LOG(INFO) << "No sensors abnormality monitoring info present.";
1688         return true;
1689     }
1690 
1691     Json::Value values;
1692 
1693     std::optional<TempRangeInfo> default_temp_range_info;
1694     std::vector<AbnormalStatsInfo::SensorsTempRangeInfo> sensors_temp_range_infos;
1695     Json::Value outlier_temp_config = abnormal_stats_config["Outlier"];
1696     if (outlier_temp_config) {
1697         LOG(INFO) << "Start to parse outlier temp config.";
1698 
1699         if (outlier_temp_config["Default"]) {
1700             LOG(INFO) << "Start to parse defaultTempRange.";
1701             if (!getTempRangeInfoFromJsonValues(outlier_temp_config["Default"],
1702                                                 &default_temp_range_info.value())) {
1703                 LOG(ERROR) << "Failed to parse default temp range config.";
1704                 return false;
1705             }
1706         }
1707 
1708         Json::Value configs = outlier_temp_config["Configs"];
1709         if (configs) {
1710             std::unordered_set<std::string> sensors_parsed;
1711             for (Json::Value::ArrayIndex i = 0; i < configs.size(); i++) {
1712                 LOG(INFO) << "Start to parse temp range config[" << i << "]";
1713                 AbnormalStatsInfo::SensorsTempRangeInfo sensors_temp_range_info;
1714                 values = configs[i]["Monitor"];
1715                 if (!values.size()) {
1716                     LOG(ERROR) << "Invalid config no sensor list present for outlier temp "
1717                                   "config.";
1718                     return false;
1719                 }
1720                 for (Json::Value::ArrayIndex j = 0; j < values.size(); j++) {
1721                     const std::string &sensor = values[j].asString();
1722                     if (!sensor_info_map_.count(sensor)) {
1723                         LOG(ERROR) << "Unknown sensor " << sensor;
1724                         return false;
1725                     }
1726                     auto result = sensors_parsed.insert(sensor);
1727                     if (!result.second) {
1728                         LOG(ERROR) << "Duplicate Sensor Temp Range Config: " << sensor;
1729                         return false;
1730                     }
1731                     LOG(INFO) << "Monitored sensor [" << j << "]: " << sensor;
1732                     sensors_temp_range_info.sensors.push_back(sensor);
1733                 }
1734                 if (!getTempRangeInfoFromJsonValues(configs[i]["TempRange"],
1735                                                     &sensors_temp_range_info.temp_range_info)) {
1736                     LOG(ERROR) << "Failed to parse temp range config.";
1737                     return false;
1738                 }
1739                 sensors_temp_range_infos.push_back(sensors_temp_range_info);
1740             }
1741         }
1742     }
1743     std::optional<TempStuckInfo> default_temp_stuck_info;
1744     std::vector<AbnormalStatsInfo::SensorsTempStuckInfo> sensors_temp_stuck_infos;
1745     Json::Value stuck_temp_config = abnormal_stats_config["Stuck"];
1746     if (stuck_temp_config) {
1747         LOG(INFO) << "Start to parse stuck temp config.";
1748 
1749         if (stuck_temp_config["Default"]) {
1750             LOG(INFO) << "Start to parse defaultTempStuck.";
1751             if (!getTempStuckInfoFromJsonValue(stuck_temp_config["Default"],
1752                                                &default_temp_stuck_info.value())) {
1753                 LOG(ERROR) << "Failed to parse default temp stuck config.";
1754                 return false;
1755             }
1756         }
1757 
1758         Json::Value configs = stuck_temp_config["Configs"];
1759         if (configs) {
1760             std::unordered_set<std::string> sensors_parsed;
1761             for (Json::Value::ArrayIndex i = 0; i < configs.size(); i++) {
1762                 LOG(INFO) << "Start to parse temp stuck config[" << i << "]";
1763                 AbnormalStatsInfo::SensorsTempStuckInfo sensor_temp_stuck_info;
1764                 values = configs[i]["Monitor"];
1765                 if (!values.size()) {
1766                     LOG(ERROR) << "Invalid config no sensor list present for stuck temp "
1767                                   "config.";
1768                     return false;
1769                 }
1770                 for (Json::Value::ArrayIndex j = 0; j < values.size(); j++) {
1771                     const std::string &sensor = values[j].asString();
1772                     if (!sensor_info_map_.count(sensor)) {
1773                         LOG(ERROR) << "Unknown sensor " << sensor;
1774                         return false;
1775                     }
1776                     auto result = sensors_parsed.insert(sensor);
1777                     if (!result.second) {
1778                         LOG(ERROR) << "Duplicate Sensor Temp Stuck Config: " << sensor;
1779                         return false;
1780                     }
1781                     LOG(INFO) << "Monitored sensor [" << j << "]: " << sensor;
1782                     sensor_temp_stuck_info.sensors.push_back(sensor);
1783                 }
1784                 if (!getTempStuckInfoFromJsonValue(configs[i]["TempStuck"],
1785                                                    &sensor_temp_stuck_info.temp_stuck_info)) {
1786                     LOG(ERROR) << "Failed to parse temp stuck config.";
1787                     return false;
1788                 }
1789                 sensors_temp_stuck_infos.push_back(sensor_temp_stuck_info);
1790             }
1791         }
1792     }
1793     *abnormal_stats_info_parsed = {
1794             .default_temp_range_info = default_temp_range_info,
1795             .sensors_temp_range_infos = sensors_temp_range_infos,
1796             .default_temp_stuck_info = default_temp_stuck_info,
1797             .sensors_temp_stuck_infos = sensors_temp_stuck_infos,
1798     };
1799     return true;
1800 }
1801 
ParseSensorStatsConfig(const Json::Value & config,const std::unordered_map<std::string,SensorInfo> & sensor_info_map_,StatsInfo<float> * sensor_stats_info_parsed,AbnormalStatsInfo * abnormal_stats_info_parsed)1802 bool ParseSensorStatsConfig(const Json::Value &config,
1803                             const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
1804                             StatsInfo<float> *sensor_stats_info_parsed,
1805                             AbnormalStatsInfo *abnormal_stats_info_parsed) {
1806     Json::Value stats_config = config["Stats"];
1807     if (stats_config.empty()) {
1808         LOG(INFO) << "No Stats Config present.";
1809         return true;
1810     }
1811     // Parse cooling device user vote
1812     Json::Value sensor_config = stats_config["Sensors"];
1813     if (sensor_config.empty()) {
1814         LOG(INFO) << "No Sensor Stats Config present.";
1815         return true;
1816     }
1817     LOG(INFO) << "Parse Stats Config for Sensor Temp.";
1818     // Parse sensor stats config
1819     if (!ParseStatsInfo(stats_config["Sensors"], sensor_info_map_, sensor_stats_info_parsed,
1820                         std::numeric_limits<float>::lowest())) {
1821         LOG(ERROR) << "Failed to parse sensor temp stats info.";
1822         sensor_stats_info_parsed->clear();
1823         return false;
1824     }
1825     if (!ParseSensorAbnormalStatsConfig(sensor_config["Abnormality"], sensor_info_map_,
1826                                         abnormal_stats_info_parsed)) {
1827         LOG(ERROR) << "Failed to parse sensor abnormal stats config.";
1828         return false;
1829     }
1830     return true;
1831 }
1832 
ParseCoolingDeviceStatsConfig(const Json::Value & config,const std::unordered_map<std::string,CdevInfo> & cooling_device_info_map_,StatsInfo<int> * cooling_device_request_info_parsed)1833 bool ParseCoolingDeviceStatsConfig(
1834         const Json::Value &config,
1835         const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_,
1836         StatsInfo<int> *cooling_device_request_info_parsed) {
1837     Json::Value stats_config = config["Stats"];
1838     if (stats_config.empty()) {
1839         LOG(INFO) << "No Stats Config present.";
1840         return true;
1841     }
1842     // Parse cooling device user vote
1843     if (stats_config["CoolingDevices"].empty()) {
1844         LOG(INFO) << "No cooling device stats present.";
1845         return true;
1846     }
1847     LOG(INFO) << "Parse Stats Config for Sensor CDev Request.";
1848     if (!ParseStatsInfo(stats_config["CoolingDevices"]["RecordVotePerSensor"],
1849                         cooling_device_info_map_, cooling_device_request_info_parsed, -1)) {
1850         LOG(ERROR) << "Failed to parse cooling device user vote stats info.";
1851         cooling_device_request_info_parsed->clear();
1852         return false;
1853     }
1854     return true;
1855 }
1856 }  // namespace implementation
1857 }  // namespace thermal
1858 }  // namespace hardware
1859 }  // namespace android
1860 }  // namespace aidl
1861