• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::atof(value.asString().c_str());
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         case SensorFusionType::CDEV:
197             return stream << "CDEV";
198         default:
199             return stream << "UNDEFINED";
200     }
201 }
202 
LoadThermalConfig(std::string_view config_path,Json::Value * config)203 bool LoadThermalConfig(std::string_view config_path, Json::Value *config) {
204     std::string json_doc;
205     if (!::android::base::ReadFileToString(config_path.data(), &json_doc)) {
206         LOG(ERROR) << "Failed to read JSON config from " << config_path;
207         return false;
208     }
209     Json::CharReaderBuilder builder;
210     std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
211     std::string errorMessage;
212     if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), config, &errorMessage)) {
213         LOG(ERROR) << "Failed to parse JSON config: " << errorMessage;
214         return false;
215     }
216     return true;
217 }
218 
MergeConfigEntries(Json::Value * config,Json::Value * sub_config,std::string_view member_name)219 void MergeConfigEntries(Json::Value *config, Json::Value *sub_config,
220                         std::string_view member_name) {
221     Json::Value &config_entries = (*config)[member_name.data()];
222     Json::Value &sub_config_entries = (*sub_config)[member_name.data()];
223     std::unordered_set<std::string> config_entries_set;
224 
225     if (sub_config_entries.size() == 0) {
226         return;
227     }
228 
229     for (Json::Value::ArrayIndex i = 0; i < config_entries.size(); i++) {
230         config_entries_set.insert(config_entries[i]["Name"].asString());
231     }
232 
233     // Iterate through subconfig and add entries not found in main config
234     for (Json::Value::ArrayIndex i = 0; i < sub_config_entries.size(); ++i) {
235         if (config_entries_set.count(sub_config_entries[i]["Name"].asString()) == 0) {
236             config_entries.append(sub_config_entries[i]);
237         } else {
238             LOG(INFO) << "Base config entry " << sub_config_entries[i]["Name"].asString()
239                       << " is overwritten in main config";
240         }
241     }
242 }
243 
ParseThermalConfig(std::string_view config_path,Json::Value * config,std::unordered_set<std::string> * loaded_config_paths)244 bool ParseThermalConfig(std::string_view config_path, Json::Value *config,
245                         std::unordered_set<std::string> *loaded_config_paths) {
246     if (loaded_config_paths->count(config_path.data())) {
247         LOG(ERROR) << "Circular dependency detected in config " << config_path;
248         return false;
249     }
250 
251     if (!LoadThermalConfig(config_path, config)) {
252         LOG(ERROR) << "Failed to read JSON config at " << config_path;
253         return false;
254     }
255 
256     loaded_config_paths->insert(config_path.data());
257 
258     Json::Value sub_configs_paths = (*config)["Include"];
259     for (Json::Value::ArrayIndex i = 0; i < sub_configs_paths.size(); ++i) {
260         const std::string sub_configs_path = "/vendor/etc/" + sub_configs_paths[i].asString();
261         Json::Value sub_config;
262 
263         if (!ParseThermalConfig(sub_configs_path, &sub_config, loaded_config_paths)) {
264             return false;
265         }
266 
267         MergeConfigEntries(config, &sub_config, "Sensors");
268         MergeConfigEntries(config, &sub_config, "CoolingDevices");
269         MergeConfigEntries(config, &sub_config, "PowerRails");
270 
271         if (!sub_config["Stats"].empty()) {
272             if ((*config)["Stats"].empty()) {
273                 (*config)["Stats"] = sub_config["Stats"];
274             } else {
275                 MergeConfigEntries(&(*config)["Stats"]["Sensors"], &sub_config["Stats"]["Sensors"],
276                                    "RecordWithThreshold");
277             }
278         }
279     }
280 
281     return true;
282 }
283 
ParseOffsetThresholds(const std::string_view name,const Json::Value & sensor,std::vector<float> * offset_thresholds,std::vector<float> * offset_values)284 bool ParseOffsetThresholds(const std::string_view name, const Json::Value &sensor,
285                            std::vector<float> *offset_thresholds,
286                            std::vector<float> *offset_values) {
287     Json::Value config_offset_thresholds = sensor["OffsetThresholds"];
288     Json::Value config_offset_values = sensor["OffsetValues"];
289 
290     if (config_offset_thresholds.empty()) {
291         return true;
292     }
293 
294     if (config_offset_thresholds.size() != config_offset_values.size()) {
295         LOG(ERROR) << "Sensor[" << name
296                    << "]'s offset_thresholds size does not match with offset_values size";
297         return false;
298     }
299 
300     for (Json::Value::ArrayIndex i = 0; i < config_offset_thresholds.size(); ++i) {
301         float offset_threshold = config_offset_thresholds[i].asFloat();
302         float offset_value = config_offset_values[i].asFloat();
303         if (std::isnan(offset_threshold) || std::isnan(offset_value)) {
304             LOG(ERROR) << "Nan offset_threshold or offset_value unexpected for sensor " << name;
305             return false;
306         }
307 
308         if ((i != 0) && (offset_threshold < (*offset_thresholds).back())) {
309             LOG(ERROR) << "offset_thresholds are not in increasing order for sensor " << name;
310             return false;
311         }
312 
313         (*offset_thresholds).emplace_back(offset_threshold);
314         (*offset_values).emplace_back(offset_value);
315 
316         LOG(INFO) << "Sensor[" << name << "]'s offset_thresholds[" << i
317                   << "]: " << (*offset_thresholds)[i] << " offset_values[" << i
318                   << "]: " << (*offset_values)[i];
319     }
320 
321     return true;
322 }
323 
ParseVirtualSensorInfo(const std::string_view name,const Json::Value & sensor,std::unique_ptr<VirtualSensorInfo> * virtual_sensor_info)324 bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sensor,
325                             std::unique_ptr<VirtualSensorInfo> *virtual_sensor_info) {
326     if (sensor["VirtualSensor"].empty() || !sensor["VirtualSensor"].isBool()) {
327         LOG(INFO) << "Failed to read Sensor[" << name << "]'s VirtualSensor";
328         return true;
329     }
330     bool is_virtual_sensor = sensor["VirtualSensor"].asBool();
331     LOG(INFO) << "Sensor[" << name << "]'s' VirtualSensor: " << is_virtual_sensor;
332     if (!is_virtual_sensor) {
333         return true;
334     }
335     float offset = 0;
336     std::vector<std::string> linked_sensors;
337     std::vector<SensorFusionType> linked_sensors_type;
338     std::vector<std::string> trigger_sensors;
339     std::vector<std::string> coefficients;
340     std::vector<SensorFusionType> coefficients_type;
341     FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
342     std::string vt_estimator_model_file;
343     std::unique_ptr<::thermal::vtestimator::VirtualTempEstimator> vt_estimator;
344     std::string backup_sensor;
345 
346     Json::Value values = sensor["Combination"];
347     if (values.size()) {
348         linked_sensors.reserve(values.size());
349         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
350             linked_sensors.emplace_back(values[j].asString());
351             LOG(INFO) << "Sensor[" << name << "]'s Combination[" << j << "]: " << linked_sensors[j];
352         }
353     } else {
354         LOG(ERROR) << "Sensor[" << name << "] has no Combination setting";
355         return false;
356     }
357 
358     if (sensor["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
359         formula = FormulaOption::COUNT_THRESHOLD;
360     } else if (sensor["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
361         formula = FormulaOption::WEIGHTED_AVG;
362     } else if (sensor["Formula"].asString().compare("MAXIMUM") == 0) {
363         formula = FormulaOption::MAXIMUM;
364     } else if (sensor["Formula"].asString().compare("MINIMUM") == 0) {
365         formula = FormulaOption::MINIMUM;
366     } else if (sensor["Formula"].asString().compare("USE_ML_MODEL") == 0) {
367         formula = FormulaOption::USE_ML_MODEL;
368     } else if (sensor["Formula"].asString().compare("USE_LINEAR_MODEL") == 0) {
369         formula = FormulaOption::USE_LINEAR_MODEL;
370     } else if (sensor["Formula"].asString().compare("PREVIOUSLY_PREDICTED") == 0) {
371         formula = FormulaOption::PREVIOUSLY_PREDICTED;
372     } else {
373         LOG(ERROR) << "Sensor[" << name << "]'s Formula: " << sensor["Formula"].asString()
374                    << " is invalid";
375         return false;
376     }
377 
378     values = sensor["CombinationType"];
379     if (!values.size()) {
380         linked_sensors_type.reserve(linked_sensors.size());
381         for (size_t j = 0; j < linked_sensors.size(); ++j) {
382             linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
383         }
384     } else if (values.size() != linked_sensors.size()) {
385         LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType size";
386         return false;
387     } else {
388         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
389             if (values[j].asString().compare("SENSOR") == 0) {
390                 linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
391             } else if (values[j].asString().compare("ODPM") == 0) {
392                 linked_sensors_type.emplace_back(SensorFusionType::ODPM);
393             } else if (values[j].asString().compare("CONSTANT") == 0) {
394                 linked_sensors_type.emplace_back(SensorFusionType::CONSTANT);
395             } else if (values[j].asString().compare("CDEV") == 0) {
396                 linked_sensors_type.emplace_back(SensorFusionType::CDEV);
397             } else {
398                 LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType settings "
399                            << values[j].asString();
400                 return false;
401             }
402             LOG(INFO) << "Sensor[" << name << "]'s CombinationType[" << j
403                       << "]: " << linked_sensors_type[j];
404         }
405     }
406 
407     values = sensor["Coefficient"];
408     if (values.size()) {
409         coefficients.reserve(values.size());
410         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
411             coefficients.emplace_back(values[j].asString());
412             LOG(INFO) << "Sensor[" << name << "]'s coefficient[" << j << "]: " << coefficients[j];
413         }
414     } else if ((formula != FormulaOption::USE_ML_MODEL) &&
415                (formula != FormulaOption::PREVIOUSLY_PREDICTED)) {
416         LOG(ERROR) << "Sensor[" << name << "] has no Coefficient setting";
417         return false;
418     }
419     if ((linked_sensors.size() != coefficients.size()) &&
420         (formula != FormulaOption::USE_ML_MODEL) && (formula != FormulaOption::USE_LINEAR_MODEL) &&
421         (formula != FormulaOption::PREVIOUSLY_PREDICTED)) {
422         LOG(ERROR) << "Sensor[" << name << "] has invalid Coefficient size";
423         return false;
424     }
425 
426     values = sensor["CoefficientType"];
427     if (!values.size()) {
428         coefficients_type.reserve(linked_sensors.size());
429         for (size_t j = 0; j < linked_sensors.size(); ++j) {
430             coefficients_type.emplace_back(SensorFusionType::CONSTANT);
431         }
432     } else if (values.size() != coefficients.size()) {
433         LOG(ERROR) << "Sensor[" << name << "] has invalid coefficient type size";
434         return false;
435     } else {
436         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
437             if (values[j].asString().compare("CONSTANT") == 0) {
438                 coefficients_type.emplace_back(SensorFusionType::CONSTANT);
439             } else if (values[j].asString().compare("SENSOR") == 0) {
440                 coefficients_type.emplace_back(SensorFusionType::SENSOR);
441             } else if (values[j].asString().compare("ODPM") == 0) {
442                 coefficients_type.emplace_back(SensorFusionType::ODPM);
443             } else {
444                 LOG(ERROR) << "Sensor[" << name << "] has invalid coefficient options "
445                            << values[j].asString();
446                 return false;
447             }
448             LOG(INFO) << "Sensor[" << name << "]'s coefficient type[" << j
449                       << "]: " << coefficients_type[j];
450         }
451     }
452 
453     if (linked_sensors.size() != coefficients_type.size()) {
454         LOG(ERROR) << "Sensor[" << name
455                    << "]'s combination size is not matched with coefficient type size";
456         return false;
457     }
458 
459     if (!sensor["Offset"].empty()) {
460         offset = sensor["Offset"].asFloat();
461     }
462 
463     if (!sensor["BackupSensor"].empty()) {
464         backup_sensor = sensor["BackupSensor"].asString();
465     }
466 
467     values = sensor["TriggerSensor"];
468     if (!values.empty()) {
469         if (values.isString()) {
470             trigger_sensors.emplace_back(values.asString());
471             LOG(INFO) << "Sensor[" << name << "]'s TriggerSensor: " << values.asString();
472         } else if (values.size()) {
473             trigger_sensors.reserve(values.size());
474             for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
475                 if (!values[j].isString()) {
476                     LOG(ERROR) << name << " TriggerSensor should be an array of string";
477                     return false;
478                 }
479                 trigger_sensors.emplace_back(values[j].asString());
480                 LOG(INFO) << "Sensor[" << name << "]'s TriggerSensor[" << j
481                           << "]: " << trigger_sensors[j];
482             }
483         } else {
484             LOG(ERROR) << "Sensor[" << name << "]'s TriggerSensor should be a string";
485             return false;
486         }
487     }
488 
489     if (formula == FormulaOption::USE_ML_MODEL) {
490         ::thermal::vtestimator::VtEstimationInitData init_data(::thermal::vtestimator::kUseMLModel);
491         if (sensor["ModelPath"].empty()) {
492             LOG(ERROR) << "Sensor[" << name << "] has no ModelPath";
493             return false;
494         }
495 
496         if (!linked_sensors.size()) {
497             LOG(ERROR) << "Sensor[" << name << "] uses USE_ML_MODEL and has zero linked_sensors";
498             return false;
499         }
500 
501         vt_estimator = std::make_unique<::thermal::vtestimator::VirtualTempEstimator>(
502                 name, ::thermal::vtestimator::kUseMLModel, linked_sensors.size());
503         if (!vt_estimator) {
504             LOG(ERROR) << "Failed to create vt estimator for Sensor[" << name
505                        << "] with linked sensor size : " << linked_sensors.size();
506             return false;
507         }
508 
509         vt_estimator_model_file = "vendor/etc/" + sensor["ModelPath"].asString();
510         init_data.ml_model_init_data.model_path = vt_estimator_model_file;
511 
512         if (!ParseOffsetThresholds(name, sensor, &init_data.ml_model_init_data.offset_thresholds,
513                                    &init_data.ml_model_init_data.offset_values)) {
514             LOG(ERROR) << "Failed to parse offset thresholds and values for Sensor[" << name << "]";
515             return false;
516         }
517 
518         if (!sensor["PreviousSampleCount"].empty()) {
519             init_data.ml_model_init_data.use_prev_samples = true;
520             init_data.ml_model_init_data.prev_samples_order = sensor["PreviousSampleCount"].asInt();
521             LOG(INFO) << "Sensor[" << name << "] takes "
522                       << init_data.ml_model_init_data.prev_samples_order << " historic samples";
523         }
524 
525         if (!sensor["OutputLabelCount"].empty()) {
526             init_data.ml_model_init_data.output_label_count = sensor["OutputLabelCount"].asInt();
527             LOG(INFO) << "Sensor[" << name << "] outputs "
528                       << init_data.ml_model_init_data.output_label_count << " labels";
529         }
530 
531         if (!sensor["PredictHotSpotCount"].empty()) {
532             init_data.ml_model_init_data.num_hot_spots = sensor["PredictHotSpotCount"].asInt();
533             LOG(INFO) << "Sensor[" << name << "] predicts temperature at "
534                       << init_data.ml_model_init_data.num_hot_spots << " hot spots";
535         }
536 
537         if (sensor["ValidateInput"].asBool()) {
538             init_data.ml_model_init_data.enable_input_validation = true;
539             LOG(INFO) << "Sensor[" << name << "] enable input validation.";
540         }
541 
542         if (sensor["SupportUnderSampling"].asBool()) {
543             init_data.ml_model_init_data.support_under_sampling = true;
544             LOG(INFO) << "Sensor[" << name << "] supports under sampling estimation.";
545         }
546 
547         ::thermal::vtestimator::VtEstimatorStatus ret = vt_estimator->Initialize(init_data);
548         if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
549             LOG(ERROR) << "Failed to initialize vt estimator for Sensor[" << name
550                        << "] with ModelPath: " << vt_estimator_model_file
551                        << " with ret code : " << ret;
552             return false;
553         }
554 
555         LOG(INFO) << "Successfully created vt_estimator for Sensor[" << name
556                   << "] with input samples: " << linked_sensors.size();
557 
558     } else if (formula == FormulaOption::USE_LINEAR_MODEL) {
559         ::thermal::vtestimator::VtEstimationInitData init_data(
560                 ::thermal::vtestimator::kUseLinearModel);
561 
562         if ((!linked_sensors.size()) || (linked_sensors.size() > coefficients.size())) {
563             LOG(ERROR) << "Sensor[" << name
564                        << "] uses USE_LINEAR_MODEL and has invalid linked_sensors size["
565                        << linked_sensors.size() << "] or coefficients size[" << coefficients.size()
566                        << "]";
567             return false;
568         }
569 
570         vt_estimator = std::make_unique<::thermal::vtestimator::VirtualTempEstimator>(
571                 name, ::thermal::vtestimator::kUseLinearModel, linked_sensors.size());
572         if (!vt_estimator) {
573             LOG(ERROR) << "Failed to create vt estimator for Sensor[" << name
574                        << "] with linked sensor size : " << linked_sensors.size();
575             return false;
576         }
577 
578         init_data.linear_model_init_data.prev_samples_order =
579                 coefficients.size() / linked_sensors.size();
580 
581         if (!ParseOffsetThresholds(name, sensor,
582                                    &init_data.linear_model_init_data.offset_thresholds,
583                                    &init_data.linear_model_init_data.offset_values)) {
584             LOG(ERROR) << "Failed to parse offset thresholds and values for Sensor[" << name << "]";
585             return false;
586         }
587 
588         for (size_t i = 0; i < coefficients.size(); ++i) {
589             float coefficient = getFloatFromValue(coefficients[i]);
590             if (std::isnan(coefficient)) {
591                 LOG(ERROR) << "Nan coefficient unexpected for sensor " << name;
592                 return false;
593             }
594             init_data.linear_model_init_data.coefficients.emplace_back(coefficient);
595         }
596         if (coefficients.size() > linked_sensors.size()) {
597             init_data.linear_model_init_data.use_prev_samples = true;
598         }
599 
600         ::thermal::vtestimator::VtEstimatorStatus ret = vt_estimator->Initialize(init_data);
601         if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
602             LOG(ERROR) << "Failed to initialize vt estimator for Sensor[" << name
603                        << "] with ret code : " << ret;
604             return false;
605         }
606 
607         LOG(INFO) << "Successfully created vt_estimator for Sensor[" << name
608                   << "] with input samples: " << linked_sensors.size();
609     }
610 
611     virtual_sensor_info->reset(
612             new VirtualSensorInfo{linked_sensors, linked_sensors_type, coefficients,
613                                   coefficients_type, offset, trigger_sensors, formula,
614                                   vt_estimator_model_file, std::move(vt_estimator), backup_sensor});
615     return true;
616 }
617 
ParsePredictorInfo(const std::string_view name,const Json::Value & sensor,std::unique_ptr<PredictorInfo> * predictor_info)618 bool ParsePredictorInfo(const std::string_view name, const Json::Value &sensor,
619                         std::unique_ptr<PredictorInfo> *predictor_info) {
620     Json::Value predictor = sensor["PredictorInfo"];
621     std::string predict_sensor;
622     bool support_pid_compensation = false;
623     std::vector<float> prediction_weights;
624     ThrottlingArray k_p_compensate;
625 
626     bool supports_predictions = false;
627     int prediction_sample_interval = 0;
628     int num_prediction_samples = 0;
629     int prediction_duration = 0;
630     bool set_predictor_info = false;
631 
632     if (!predictor.empty()) {
633         set_predictor_info = true;
634         LOG(INFO) << "Start to parse Sensor[" << name << "]'s PredictorInfo";
635         if (predictor["Sensor"].empty()) {
636             LOG(ERROR) << "Failed to parse Sensor [" << name << "]'s PredictorInfo";
637             return false;
638         }
639 
640         predict_sensor = predictor["Sensor"].asString();
641         LOG(INFO) << "Sensor [" << name << "]'s predictor name is " << predict_sensor;
642         // parse pid compensation configuration
643         if ((!predictor["PredictionWeight"].empty()) && (!predictor["KPCompensate"].empty())) {
644             support_pid_compensation = true;
645             if (!predictor["PredictionWeight"].size()) {
646                 LOG(ERROR) << "Failed to parse PredictionWeight";
647                 return false;
648             }
649             prediction_weights.reserve(predictor["PredictionWeight"].size());
650             for (Json::Value::ArrayIndex i = 0; i < predictor["PredictionWeight"].size(); ++i) {
651                 float weight = predictor["PredictionWeight"][i].asFloat();
652                 if (std::isnan(weight)) {
653                     LOG(ERROR) << "Unexpected NAN prediction weight for sensor [" << name << "]";
654                 }
655                 prediction_weights.emplace_back(weight);
656                 LOG(INFO) << "Sensor[" << name << "]'s prediction weights [" << i
657                           << "]: " << weight;
658             }
659             if (!getFloatFromJsonValues(predictor["KPCompensate"], &k_p_compensate, false, false)) {
660                 LOG(ERROR) << "Failed to parse KPCompensate";
661                 return false;
662             }
663         }
664     }
665 
666     if (sensor["SupportPrediction"].asBool()) {
667         set_predictor_info = true;
668         supports_predictions = true;
669         LOG(INFO) << "Sensor[" << name << "] supports predictions.";
670 
671         if (sensor["SampleDuration"].empty()) {
672             LOG(ERROR) << "SampleDuration is empty for predictor sensor: " << name;
673             return false;
674         }
675 
676         if (sensor["OutputLabelCount"].empty()) {
677             LOG(ERROR) << "OutputLabelCount is empty for predictor sensor: " << name;
678             return false;
679         }
680 
681         prediction_sample_interval = sensor["SampleDuration"].asInt();
682         num_prediction_samples = sensor["OutputLabelCount"].asInt();
683     }
684 
685     if (sensor["Formula"].asString().compare("PREVIOUSLY_PREDICTED") == 0) {
686         set_predictor_info = true;
687         if (sensor["PredictionDuration"].empty()) {
688             LOG(ERROR) << "Sensor[" << name
689                        << "] is a PREVIOUSLY_PREDICTED sensor and has no PredictionDuration";
690             return false;
691         }
692 
693         prediction_duration = sensor["PredictionDuration"].asInt();
694     }
695 
696     if (set_predictor_info) {
697         LOG(INFO) << "Successfully created PredictorInfo for Sensor[" << name << "]";
698         predictor_info->reset(new PredictorInfo{predict_sensor, support_pid_compensation,
699                                                 prediction_weights, k_p_compensate,
700                                                 supports_predictions, prediction_sample_interval,
701                                                 num_prediction_samples, prediction_duration});
702     }
703 
704     return true;
705 }
706 
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,const std::unordered_map<std::string,CdevInfo> & cooling_device_info_map_)707 bool ParseBindedCdevInfo(
708         const Json::Value &values,
709         std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map,
710         const bool support_pid, bool *support_hard_limit,
711         const std::unordered_map<std::string, std::vector<int>> &scaling_frequency_map,
712         const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_) {
713     for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
714         Json::Value sub_values;
715         const std::string &cdev_name = values[j]["CdevRequest"].asString();
716 
717         if (cooling_device_info_map_.find(cdev_name) == cooling_device_info_map_.end()) {
718             LOG(ERROR) << "Binded cdev " << cdev_name << " is not defined in cooling devices";
719             return false;
720         }
721 
722         ThrottlingArray cdev_weight_for_pid;
723         cdev_weight_for_pid.fill(NAN);
724         CdevArray cdev_ceiling;
725         cdev_ceiling.fill(std::numeric_limits<int>::max());
726         int max_release_step = std::numeric_limits<int>::max();
727         int max_throttle_step = std::numeric_limits<int>::max();
728         if (support_pid) {
729             if (!values[j]["CdevWeightForPID"].empty()) {
730                 LOG(INFO) << "Star to parse " << cdev_name << "'s CdevWeightForPID";
731                 if (!getFloatFromJsonValues(values[j]["CdevWeightForPID"], &cdev_weight_for_pid,
732                                             false, false)) {
733                     LOG(ERROR) << "Failed to parse CdevWeightForPID";
734                     binded_cdev_info_map->clear();
735                     return false;
736                 }
737             }
738 
739             if (!values[j]["CdevCeiling"].empty() && !values[j]["CdevCeilingFrequency"].empty()) {
740                 LOG(ERROR) << "Both CdevCeiling and CdevCeilingFrequency are configured for "
741                            << cdev_name << ", please remove one of them";
742                 binded_cdev_info_map->clear();
743                 return false;
744             }
745 
746             if (!values[j]["CdevCeiling"].empty()) {
747                 LOG(INFO) << "Start to parse CdevCeiling: " << cdev_name;
748                 if (!getIntFromJsonValues(values[j]["CdevCeiling"], &cdev_ceiling, false, false)) {
749                     LOG(ERROR) << "Failed to parse CdevCeiling for " << cdev_name;
750                     binded_cdev_info_map->clear();
751                     return false;
752                 }
753             }
754 
755             if (!values[j]["CdevCeilingFrequency"].empty()) {
756                 LOG(INFO) << "Start to parse CdevCeilingFrequency: " << cdev_name;
757                 CdevArray cdev_ceiling_frequency;
758                 if (scaling_frequency_map.find(cdev_name) == scaling_frequency_map.end()) {
759                     LOG(ERROR) << "Scaling frequency path is not found in config for " << cdev_name;
760                     binded_cdev_info_map->clear();
761                     return false;
762                 }
763                 const std::vector<int> &cdev_scaling_frequency =
764                         scaling_frequency_map.find(cdev_name)->second;
765                 if (!getIntFromJsonValues(values[j]["CdevCeilingFrequency"],
766                                           &cdev_ceiling_frequency, false, true)) {
767                     LOG(ERROR) << "Failed to parse CdevCeilingFrequency";
768                     binded_cdev_info_map->clear();
769                     return false;
770                 }
771 
772                 LOG(INFO) << "Start to search CdevCeiling based on frequency: " << cdev_name;
773                 // Find the max frequency level that is lower than or equal to CdevCeilingFrequency
774                 // value
775                 for (size_t cdev_scaling_idx = 0, cdev_ceiling_idx = 0;
776                      cdev_scaling_idx < cdev_scaling_frequency.size() &&
777                      cdev_ceiling_idx < cdev_ceiling.size();) {
778                     if (cdev_scaling_frequency.at(cdev_scaling_idx) <=
779                         cdev_ceiling_frequency.at(cdev_ceiling_idx)) {
780                         cdev_ceiling[cdev_ceiling_idx] = cdev_scaling_idx;
781                         LOG(INFO) << "[" << cdev_ceiling_idx
782                                   << "]: " << cdev_ceiling[cdev_ceiling_idx];
783                         cdev_ceiling_idx += 1;
784                     } else {
785                         cdev_scaling_idx += 1;
786                     }
787                 }
788             }
789 
790             if (!values[j]["MaxReleaseStep"].empty()) {
791                 max_release_step = getIntFromValue(values[j]["MaxReleaseStep"]);
792                 if (max_release_step < 0) {
793                     LOG(ERROR) << cdev_name << " MaxReleaseStep: " << max_release_step;
794                     binded_cdev_info_map->clear();
795                     return false;
796                 } else {
797                     LOG(INFO) << cdev_name << " MaxReleaseStep: " << max_release_step;
798                 }
799             }
800             if (!values[j]["MaxThrottleStep"].empty()) {
801                 max_throttle_step = getIntFromValue(values[j]["MaxThrottleStep"]);
802                 if (max_throttle_step < 0) {
803                     LOG(ERROR) << cdev_name << " MaxThrottleStep: " << max_throttle_step;
804                     binded_cdev_info_map->clear();
805                     return false;
806                 } else {
807                     LOG(INFO) << cdev_name << " MaxThrottleStep: " << max_throttle_step;
808                 }
809             }
810         }
811         CdevArray limit_info;
812         limit_info.fill(0);
813         ThrottlingArray power_thresholds;
814         power_thresholds.fill(NAN);
815         ReleaseLogic release_logic = ReleaseLogic::NONE;
816 
817         if (!values[j]["LimitInfo"].empty() && !values[j]["LimitInfoFrequency"].empty()) {
818             LOG(ERROR) << "Both LimitInfo and LimitInfoFrequency are configured for " << cdev_name
819                        << ", please remove one of them";
820             binded_cdev_info_map->clear();
821             return false;
822         }
823 
824         if (!values[j]["LimitInfo"].empty()) {
825             LOG(INFO) << "Start to parse LimitInfo: " << cdev_name;
826             if (!getIntFromJsonValues(values[j]["LimitInfo"], &limit_info, false, false)) {
827                 LOG(ERROR) << "Failed to parse LimitInfo";
828                 binded_cdev_info_map->clear();
829                 return false;
830             }
831             *support_hard_limit = true;
832         }
833 
834         if (!values[j]["LimitInfoFrequency"].empty()) {
835             LOG(INFO) << "Start to parse LimitInfoFrequency: " << cdev_name;
836             CdevArray limit_info_frequency;
837             if (scaling_frequency_map.find(cdev_name) == scaling_frequency_map.end()) {
838                 LOG(ERROR) << "Scaling frequency path is not found for " << cdev_name;
839                 binded_cdev_info_map->clear();
840                 return false;
841             }
842 
843             const std::vector<int> &cdev_scaling_frequency =
844                     scaling_frequency_map.find(cdev_name)->second;
845             if (!getIntFromJsonValues(values[j]["LimitInfoFrequency"], &limit_info_frequency, false,
846                                       true)) {
847                 LOG(ERROR) << "Failed to parse LimitInfoFrequency for " << cdev_name;
848                 binded_cdev_info_map->clear();
849                 return false;
850             }
851 
852             LOG(INFO) << "Start to search LimitInfo based on frequency: " << cdev_name;
853             // Find the max frequency level that is lower than or equal to imitInfoFrequency value
854             for (size_t cdev_scaling_idx = 0, limit_info_idx = 0;
855                  cdev_scaling_idx < cdev_scaling_frequency.size() &&
856                  limit_info_idx < limit_info.size();) {
857                 if (cdev_scaling_frequency.at(cdev_scaling_idx) <=
858                     limit_info_frequency.at(limit_info_idx)) {
859                     limit_info[limit_info_idx] = cdev_scaling_idx;
860                     LOG(INFO) << "[" << limit_info_idx << "]: " << limit_info[limit_info_idx];
861                     limit_info_idx += 1;
862                 } else {
863                     cdev_scaling_idx += 1;
864                 }
865             }
866             *support_hard_limit = true;
867         }
868         // Parse linked power info
869         std::string power_rail;
870         bool high_power_check = false;
871         bool throttling_with_power_link = false;
872         bool enabled = true;
873         CdevArray cdev_floor_with_power_link;
874         cdev_floor_with_power_link.fill(0);
875 
876         const bool power_link_disabled =
877                 ::android::base::GetBoolProperty(kPowerLinkDisabledProperty.data(), false);
878         if (!power_link_disabled) {
879             power_rail = values[j]["BindedPowerRail"].asString();
880 
881             if (values[j]["HighPowerCheck"].asBool()) {
882                 high_power_check = true;
883             }
884             LOG(INFO) << "Highpowercheck: " << std::boolalpha << high_power_check;
885 
886             if (values[j]["ThrottlingWithPowerLink"].asBool()) {
887                 throttling_with_power_link = true;
888             }
889             LOG(INFO) << "ThrottlingwithPowerLink: " << std::boolalpha
890                       << throttling_with_power_link;
891 
892             sub_values = values[j]["CdevFloorWithPowerLink"];
893             if (sub_values.size()) {
894                 LOG(INFO) << "Start to parse " << cdev_name << "'s CdevFloorWithPowerLink";
895                 if (!getIntFromJsonValues(sub_values, &cdev_floor_with_power_link, false, false)) {
896                     LOG(ERROR) << "Failed to parse CdevFloor";
897                     binded_cdev_info_map->clear();
898                     return false;
899                 }
900             }
901             sub_values = values[j]["PowerThreshold"];
902             if (sub_values.size()) {
903                 LOG(INFO) << "Start to parse " << cdev_name << "'s PowerThreshold";
904                 if (!getFloatFromJsonValues(sub_values, &power_thresholds, false, false)) {
905                     LOG(ERROR) << "Failed to parse power thresholds";
906                     binded_cdev_info_map->clear();
907                     return false;
908                 }
909                 if (values[j]["ReleaseLogic"].asString() == "INCREASE") {
910                     release_logic = ReleaseLogic::INCREASE;
911                     LOG(INFO) << "Release logic: INCREASE";
912                 } else if (values[j]["ReleaseLogic"].asString() == "DECREASE") {
913                     release_logic = ReleaseLogic::DECREASE;
914                     LOG(INFO) << "Release logic: DECREASE";
915                 } else if (values[j]["ReleaseLogic"].asString() == "STEPWISE") {
916                     release_logic = ReleaseLogic::STEPWISE;
917                     LOG(INFO) << "Release logic: STEPWISE";
918                 } else if (values[j]["ReleaseLogic"].asString() == "RELEASE_TO_FLOOR") {
919                     release_logic = ReleaseLogic::RELEASE_TO_FLOOR;
920                     LOG(INFO) << "Release logic: RELEASE_TO_FLOOR";
921                 } else {
922                     LOG(ERROR) << "Release logic is invalid";
923                     binded_cdev_info_map->clear();
924                     return false;
925                 }
926             }
927         }
928         if (values[j]["Disabled"].asBool()) {
929             enabled = false;
930         }
931 
932         (*binded_cdev_info_map)[cdev_name] = {
933                 .limit_info = limit_info,
934                 .power_thresholds = power_thresholds,
935                 .release_logic = release_logic,
936                 .cdev_weight_for_pid = cdev_weight_for_pid,
937                 .cdev_ceiling = cdev_ceiling,
938                 .max_release_step = max_release_step,
939                 .max_throttle_step = max_throttle_step,
940                 .cdev_floor_with_power_link = cdev_floor_with_power_link,
941                 .power_rail = power_rail,
942                 .high_power_check = high_power_check,
943                 .throttling_with_power_link = throttling_with_power_link,
944                 .enabled = enabled,
945         };
946     }
947     return true;
948 }
949 
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,const std::unordered_map<std::string,CdevInfo> & cooling_device_info_map_)950 bool ParseSensorThrottlingInfo(
951         const std::string_view name, const Json::Value &sensor, bool *support_throttling,
952         std::shared_ptr<ThrottlingInfo> *throttling_info,
953         const std::unordered_map<std::string, std::vector<int>> &scaling_frequency_map,
954         const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_) {
955     std::array<float, kThrottlingSeverityCount> k_po;
956     k_po.fill(0.0);
957     std::array<float, kThrottlingSeverityCount> k_pu;
958     k_pu.fill(0.0);
959     std::array<float, kThrottlingSeverityCount> k_io;
960     k_io.fill(0.0);
961     std::array<float, kThrottlingSeverityCount> k_iu;
962     k_iu.fill(0.0);
963     std::array<float, kThrottlingSeverityCount> k_d;
964     k_d.fill(0.0);
965     std::array<float, kThrottlingSeverityCount> i_max;
966     i_max.fill(NAN);
967     std::array<float, kThrottlingSeverityCount> max_alloc_power;
968     max_alloc_power.fill(NAN);
969     std::array<float, kThrottlingSeverityCount> min_alloc_power;
970     min_alloc_power.fill(NAN);
971     std::array<float, kThrottlingSeverityCount> s_power;
972     s_power.fill(NAN);
973     std::array<float, kThrottlingSeverityCount> i_cutoff;
974     i_cutoff.fill(NAN);
975     float i_default = 0.0;
976     float i_default_pct = NAN;
977     int tran_cycle = 0;
978     bool support_pid = false;
979     bool support_hard_limit = false;
980 
981     // Parse PID parameters
982     if (!sensor["PIDInfo"].empty()) {
983         LOG(INFO) << "Start to parse"
984                   << " Sensor[" << name << "]'s K_Po";
985         if (sensor["PIDInfo"]["K_Po"].empty() ||
986             !getFloatFromJsonValues(sensor["PIDInfo"]["K_Po"], &k_po, false, false)) {
987             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Po";
988             return false;
989         }
990         LOG(INFO) << "Start to parse"
991                   << " Sensor[" << name << "]'s  K_Pu";
992         if (sensor["PIDInfo"]["K_Pu"].empty() ||
993             !getFloatFromJsonValues(sensor["PIDInfo"]["K_Pu"], &k_pu, false, false)) {
994             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Pu";
995             return false;
996         }
997         if (!sensor["PIDInfo"]["K_I"].empty()) {
998             if (!sensor["PIDInfo"]["K_Io"].empty() || !sensor["PIDInfo"]["K_Iu"].empty()) {
999                 LOG(ERROR) << "Sensor[" << name << "]: K_Io or K_Iu cannot coexist with K_I";
1000                 return false;
1001             }
1002             LOG(INFO) << "Start to parse" << " Sensor[" << name << "]'s K_I";
1003             if (!getFloatFromJsonValues(sensor["PIDInfo"]["K_I"], &k_io, false, false) ||
1004                 !getFloatFromJsonValues(sensor["PIDInfo"]["K_I"], &k_iu, false, false)) {
1005                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_I";
1006                 return false;
1007             }
1008         } else if (!sensor["PIDInfo"]["K_Io"].empty() && !sensor["PIDInfo"]["K_Iu"].empty()) {
1009             LOG(INFO) << "Start to parse" << " Sensor[" << name << "]'s K_Io";
1010             if (!getFloatFromJsonValues(sensor["PIDInfo"]["K_Io"], &k_io, false, false)) {
1011                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Io";
1012                 return false;
1013             }
1014             LOG(INFO) << "Start to parse" << " Sensor[" << name << "]'s K_Iu";
1015             if (!getFloatFromJsonValues(sensor["PIDInfo"]["K_Iu"], &k_iu, false, false)) {
1016                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Iu";
1017                 return false;
1018             }
1019         } else {
1020             LOG(ERROR) << "Sensor[" << name << "]: No K_I related settings";
1021             return false;
1022         }
1023 
1024         LOG(INFO) << "Start to parse"
1025                   << " Sensor[" << name << "]'s K_D";
1026         if (sensor["PIDInfo"]["K_D"].empty() ||
1027             !getFloatFromJsonValues(sensor["PIDInfo"]["K_D"], &k_d, false, false)) {
1028             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_D";
1029             return false;
1030         }
1031         LOG(INFO) << "Start to parse"
1032                   << " Sensor[" << name << "]'s I_Max";
1033         if (sensor["PIDInfo"]["I_Max"].empty() ||
1034             !getFloatFromJsonValues(sensor["PIDInfo"]["I_Max"], &i_max, false, false)) {
1035             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Max";
1036             return false;
1037         }
1038         LOG(INFO) << "Start to parse"
1039                   << " Sensor[" << name << "]'s MaxAllocPower";
1040         if (sensor["PIDInfo"]["MaxAllocPower"].empty() ||
1041             !getFloatFromJsonValues(sensor["PIDInfo"]["MaxAllocPower"], &max_alloc_power, false,
1042                                     true)) {
1043             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MaxAllocPower";
1044             return false;
1045         }
1046         LOG(INFO) << "Start to parse"
1047                   << " Sensor[" << name << "]'s MinAllocPower";
1048         if (sensor["PIDInfo"]["MinAllocPower"].empty() ||
1049             !getFloatFromJsonValues(sensor["PIDInfo"]["MinAllocPower"], &min_alloc_power, false,
1050                                     true)) {
1051             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MinAllocPower";
1052             return false;
1053         }
1054         LOG(INFO) << "Start to parse Sensor[" << name << "]'s S_Power";
1055         if (sensor["PIDInfo"]["S_Power"].empty() ||
1056             !getFloatFromJsonValues(sensor["PIDInfo"]["S_Power"], &s_power, false, true)) {
1057             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse S_Power";
1058             return false;
1059         }
1060         LOG(INFO) << "Start to parse Sensor[" << name << "]'s I_Cutoff";
1061         if (sensor["PIDInfo"]["I_Cutoff"].empty() ||
1062             !getFloatFromJsonValues(sensor["PIDInfo"]["I_Cutoff"], &i_cutoff, false, false)) {
1063             LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Cutoff";
1064             return false;
1065         }
1066 
1067         if (!sensor["PIDInfo"]["I_Default"].empty() &&
1068             !sensor["PIDInfo"]["I_Default_Pct"].empty()) {
1069             LOG(ERROR) << "I_Default and I_Default_P cannot be applied together";
1070             return false;
1071         }
1072 
1073         if (!sensor["PIDInfo"]["I_Default"].empty()) {
1074             i_default = getFloatFromValue(sensor["PIDInfo"]["I_Default"]);
1075             LOG(INFO) << "Sensor[" << name << "]'s I_Default: " << i_default;
1076         } else if (!sensor["PIDInfo"]["I_Default_Pct"].empty()) {
1077             i_default_pct = getFloatFromValue(sensor["PIDInfo"]["I_Default_Pct"]);
1078             LOG(INFO) << "Sensor[" << name << "]'s I_Default_Pct: " << i_default_pct;
1079         }
1080         tran_cycle = getFloatFromValue(sensor["PIDInfo"]["TranCycle"]);
1081         LOG(INFO) << "Sensor[" << name << "]'s TranCycle: " << tran_cycle;
1082 
1083         // Confirm we have at least one valid PID combination
1084         bool valid_pid_combination = false;
1085         for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1086             if (!std::isnan(s_power[j])) {
1087                 if (std::isnan(k_po[j]) || std::isnan(k_pu[j]) || std::isnan(k_io[j]) ||
1088                     std::isnan(k_iu[j]) || std::isnan(k_d[j]) || std::isnan(i_max[j]) ||
1089                     std::isnan(max_alloc_power[j]) || std::isnan(min_alloc_power[j]) ||
1090                     std::isnan(i_cutoff[j])) {
1091                     valid_pid_combination = false;
1092                     break;
1093                 } else {
1094                     valid_pid_combination = true;
1095                 }
1096             }
1097         }
1098         if (!valid_pid_combination) {
1099             LOG(ERROR) << "Sensor[" << name << "]: Invalid PID parameters combinations";
1100             return false;
1101         } else {
1102             support_pid = true;
1103         }
1104     }
1105 
1106     // Parse binded cooling device
1107     std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
1108     if (!ParseBindedCdevInfo(sensor["BindedCdevInfo"], &binded_cdev_info_map, support_pid,
1109                              &support_hard_limit, scaling_frequency_map,
1110                              cooling_device_info_map_)) {
1111         LOG(ERROR) << "Sensor[" << name << "]: failed to parse BindedCdevInfo";
1112         return false;
1113     }
1114 
1115     Json::Value values;
1116     ProfileMap profile_map;
1117     values = sensor["Profile"];
1118     for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1119         Json::Value sub_values;
1120         const std::string &mode = values[j]["Mode"].asString();
1121         std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map_profile;
1122         if (!ParseBindedCdevInfo(values[j]["BindedCdevInfo"], &binded_cdev_info_map_profile,
1123                                  support_pid, &support_hard_limit, scaling_frequency_map,
1124                                  cooling_device_info_map_)) {
1125             LOG(ERROR) << "Sensor[" << name << " failed to parse BindedCdevInfo profile";
1126         }
1127         // Check if the binded_cdev_info_map_profile is valid
1128         if (binded_cdev_info_map.size() != binded_cdev_info_map_profile.size()) {
1129             LOG(ERROR) << "Sensor[" << name << "]:'s profile map size should not be changed";
1130             return false;
1131         } else {
1132             for (const auto &binded_cdev_info_pair : binded_cdev_info_map_profile) {
1133                 if (binded_cdev_info_map.count(binded_cdev_info_pair.first)) {
1134                     if (binded_cdev_info_pair.second.power_rail !=
1135                         binded_cdev_info_map.at(binded_cdev_info_pair.first).power_rail) {
1136                         LOG(ERROR) << "Sensor[" << name << "]:'s profile " << mode << " binded "
1137                                    << binded_cdev_info_pair.first
1138                                    << "'s power rail is not included in default rules";
1139                         return false;
1140                     } else {
1141                         LOG(INFO) << "Sensor[" << name << "]:'s profile " << mode
1142                                   << " is parsed successfully";
1143                     }
1144                 } else {
1145                     LOG(ERROR) << "Sensor[" << name << "]'s profile " << mode << " binded "
1146                                << binded_cdev_info_pair.first
1147                                << " is not included in default rules";
1148                     return false;
1149                 }
1150             }
1151         }
1152         profile_map[mode] = binded_cdev_info_map_profile;
1153     }
1154 
1155     std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
1156     values = sensor["ExcludedPowerInfo"];
1157     for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1158         Json::Value sub_values;
1159         const std::string &power_rail = values[j]["PowerRail"].asString();
1160         if (power_rail.empty()) {
1161             LOG(ERROR) << "Sensor[" << name << "] failed to parse excluded PowerRail";
1162             return false;
1163         }
1164         ThrottlingArray power_weight;
1165         power_weight.fill(1);
1166         if (!values[j]["PowerWeight"].empty()) {
1167             LOG(INFO) << "Sensor[" << name << "]: Start to parse " << power_rail
1168                       << "'s PowerWeight";
1169             if (!getFloatFromJsonValues(values[j]["PowerWeight"], &power_weight, false, false)) {
1170                 LOG(ERROR) << "Failed to parse PowerWeight";
1171                 return false;
1172             }
1173         }
1174         excluded_power_info_map[power_rail] = power_weight;
1175     }
1176     throttling_info->reset(new ThrottlingInfo{k_po, k_pu, k_io, k_iu, k_d, i_max, max_alloc_power,
1177                                               min_alloc_power, s_power, i_cutoff, i_default,
1178                                               i_default_pct, tran_cycle, excluded_power_info_map,
1179                                               binded_cdev_info_map, profile_map});
1180     *support_throttling = support_pid | support_hard_limit;
1181     return true;
1182 }
1183 
ParseSensorInfo(const Json::Value & config,std::unordered_map<std::string,SensorInfo> * sensors_parsed,const std::unordered_map<std::string,CdevInfo> & cooling_device_info_map_)1184 bool ParseSensorInfo(const Json::Value &config,
1185                      std::unordered_map<std::string, SensorInfo> *sensors_parsed,
1186                      const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_) {
1187     Json::Value sensors = config["Sensors"];
1188     Json::Value cdevs = config["CoolingDevices"];
1189     std::unordered_map<std::string, std::vector<int>> scaling_frequency_map;
1190 
1191     LOG(INFO) << "Start reading ScalingAvailableFrequenciesPath from config";
1192     for (Json::Value::ArrayIndex i = 0; i < cdevs.size(); ++i) {
1193         if (cdevs[i]["ScalingAvailableFrequenciesPath"].empty() ||
1194             cdevs[i]["isDisabled"].asBool()) {
1195             continue;
1196         }
1197 
1198         const std::string &path = cdevs[i]["ScalingAvailableFrequenciesPath"].asString();
1199         const std::string &name = cdevs[i]["Name"].asString();
1200 
1201         LOG(INFO) << "Cdev[" << name << "]'s scaling frequency path: " << path;
1202         std::string scaling_frequency_str;
1203         if (::android::base::ReadFileToString(path, &scaling_frequency_str)) {
1204             std::istringstream frequencies(scaling_frequency_str);
1205             int frequency;
1206             while (frequencies >> frequency) {
1207                 LOG(INFO) << "Cdev[" << name << "]'s available frequency: " << frequency;
1208                 scaling_frequency_map[name].push_back(frequency);
1209             }
1210 
1211             // Reverse the vector if it starts from small value
1212             if (scaling_frequency_map[name].front() < scaling_frequency_map[name].back()) {
1213                 std::reverse(scaling_frequency_map[name].begin(),
1214                              scaling_frequency_map[name].end());
1215             }
1216 
1217             // Make sure the scaling frequencies strictly decreasing
1218             if (std::adjacent_find(scaling_frequency_map[name].begin(),
1219                                    scaling_frequency_map[name].end(),
1220                                    std::less_equal<int>()) != scaling_frequency_map[name].end()) {
1221                 LOG(ERROR) << "Cdev[" << name << "]'s scaling frequencies is not monotonic";
1222                 sensors_parsed->clear();
1223                 return false;
1224             }
1225         } else {
1226             LOG(ERROR) << "Cdev[" << name << "]'s scaling frequency path is invalid.";
1227             sensors_parsed->clear();
1228             return false;
1229         }
1230     }
1231 
1232     std::size_t total_parsed = 0;
1233     std::unordered_set<std::string> sensors_name_parsed;
1234 
1235     for (Json::Value::ArrayIndex i = 0; i < sensors.size(); ++i) {
1236         const std::string &name = sensors[i]["Name"].asString();
1237         LOG(INFO) << "Sensor[" << i << "]'s Name: " << name;
1238         if (name.empty()) {
1239             LOG(ERROR) << "Failed to read Sensor[" << i << "]'s Name";
1240             sensors_parsed->clear();
1241             return false;
1242         }
1243 
1244         if (sensors[i]["isDisabled"].asBool()) {
1245             LOG(INFO) << "sensors[" << name << "] is disabled. Skipping parsing";
1246             continue;
1247         }
1248 
1249         auto result = sensors_name_parsed.insert(name);
1250         if (!result.second) {
1251             LOG(ERROR) << "Duplicate Sensor[" << i << "]'s Name";
1252             sensors_parsed->clear();
1253             return false;
1254         }
1255 
1256         std::string sensor_type_str = sensors[i]["Type"].asString();
1257         LOG(INFO) << "Sensor[" << name << "]'s Type: " << sensor_type_str;
1258         TemperatureType sensor_type;
1259 
1260         if (!getTypeFromString(sensor_type_str, &sensor_type)) {
1261             LOG(ERROR) << "Invalid Sensor[" << name << "]'s Type: " << sensor_type_str;
1262             sensors_parsed->clear();
1263             return false;
1264         }
1265 
1266         bool send_cb = false;
1267         if (!sensors[i]["Monitor"].empty() && sensors[i]["Monitor"].isBool()) {
1268             send_cb = sensors[i]["Monitor"].asBool();
1269         } else if (!sensors[i]["SendCallback"].empty() && sensors[i]["SendCallback"].isBool()) {
1270             send_cb = sensors[i]["SendCallback"].asBool();
1271         }
1272         LOG(INFO) << "Sensor[" << name << "]'s SendCallback: " << std::boolalpha << send_cb
1273                   << std::noboolalpha;
1274 
1275         bool send_powerhint = false;
1276         if (sensors[i]["SendPowerHint"].empty() || !sensors[i]["SendPowerHint"].isBool()) {
1277             LOG(INFO) << "Failed to read Sensor[" << name << "]'s SendPowerHint, set to 'false'";
1278         } else if (sensors[i]["SendPowerHint"].asBool()) {
1279             send_powerhint = true;
1280         }
1281         LOG(INFO) << "Sensor[" << name << "]'s SendPowerHint: " << std::boolalpha << send_powerhint
1282                   << std::noboolalpha;
1283 
1284         bool is_trip_point_ignorable = false;
1285         if (sensors[i]["TripPointIgnorable"].empty() ||
1286             !sensors[i]["TripPointIgnorable"].isBool()) {
1287             LOG(INFO) << "Failed to read Sensor[" << name
1288                       << "]'s TripPointIgnorable, set to 'false'";
1289         } else if (sensors[i]["TripPointIgnorable"].asBool()) {
1290             is_trip_point_ignorable = true;
1291         }
1292         LOG(INFO) << "Sensor[" << name << "]'s TripPointIgnorable: " << std::boolalpha
1293                   << is_trip_point_ignorable << std::noboolalpha;
1294 
1295         bool is_hidden = false;
1296         if (sensors[i]["Hidden"].empty() || !sensors[i]["Hidden"].isBool()) {
1297             LOG(INFO) << "Failed to read Sensor[" << name << "]'s Hidden, set to 'false'";
1298         } else if (sensors[i]["Hidden"].asBool()) {
1299             is_hidden = true;
1300         }
1301         LOG(INFO) << "Sensor[" << name << "]'s Hidden: " << std::boolalpha << is_hidden
1302                   << std::noboolalpha;
1303 
1304         ThrottlingSeverity log_level = ThrottlingSeverity::NONE;
1305         if (!sensors[i]["LogLevel"].empty()) {
1306             const auto level = sensors[i]["LogLevel"].asInt();
1307             if (level > static_cast<int>(ThrottlingSeverity::SHUTDOWN)) {
1308                 LOG(ERROR) << "Sensor[" << name << "]'s LogLevel is invalid";
1309             } else {
1310                 log_level = static_cast<ThrottlingSeverity>(level);
1311             }
1312         }
1313         LOG(INFO) << "Sensor[" << name << "]'s LogLevel: " << toString(log_level);
1314 
1315         std::array<float, kThrottlingSeverityCount> hot_thresholds;
1316         hot_thresholds.fill(NAN);
1317         std::array<float, kThrottlingSeverityCount> cold_thresholds;
1318         cold_thresholds.fill(NAN);
1319         std::array<float, kThrottlingSeverityCount> hot_hysteresis;
1320         hot_hysteresis.fill(0.0);
1321         std::array<float, kThrottlingSeverityCount> cold_hysteresis;
1322         cold_hysteresis.fill(0.0);
1323 
1324         Json::Value values = sensors[i]["HotThreshold"];
1325         if (!values.size()) {
1326             LOG(INFO) << "Sensor[" << name << "]'s HotThreshold, default all to NAN";
1327         } else if (values.size() != kThrottlingSeverityCount) {
1328             LOG(ERROR) << "Invalid Sensor[" << name << "]'s HotThreshold count:" << values.size();
1329             sensors_parsed->clear();
1330             return false;
1331         } else {
1332             float min = std::numeric_limits<float>::min();
1333             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1334                 hot_thresholds[j] = getFloatFromValue(values[j]);
1335                 if (!std::isnan(hot_thresholds[j])) {
1336                     if (hot_thresholds[j] < min) {
1337                         LOG(ERROR) << "Invalid "
1338                                    << "Sensor[" << name << "]'s HotThreshold[j" << j
1339                                    << "]: " << hot_thresholds[j] << " < " << min;
1340                         sensors_parsed->clear();
1341                         return false;
1342                     }
1343                     min = hot_thresholds[j];
1344                 }
1345                 LOG(INFO) << "Sensor[" << name << "]'s HotThreshold[" << j
1346                           << "]: " << hot_thresholds[j];
1347             }
1348         }
1349 
1350         values = sensors[i]["HotHysteresis"];
1351         if (!values.size()) {
1352             LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis, default all to 0.0";
1353         } else if (values.size() != kThrottlingSeverityCount) {
1354             LOG(ERROR) << "Invalid Sensor[" << name << "]'s HotHysteresis, count:" << values.size();
1355             sensors_parsed->clear();
1356             return false;
1357         } else {
1358             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1359                 hot_hysteresis[j] = getFloatFromValue(values[j]);
1360                 if (std::isnan(hot_hysteresis[j])) {
1361                     LOG(ERROR) << "Invalid Sensor[" << name
1362                                << "]'s HotHysteresis: " << hot_hysteresis[j];
1363                     sensors_parsed->clear();
1364                     return false;
1365                 }
1366                 LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis[" << j
1367                           << "]: " << hot_hysteresis[j];
1368             }
1369         }
1370 
1371         for (Json::Value::ArrayIndex j = 0; j < (kThrottlingSeverityCount - 1); ++j) {
1372             if (std::isnan(hot_thresholds[j])) {
1373                 continue;
1374             }
1375             for (auto k = j + 1; k < kThrottlingSeverityCount; ++k) {
1376                 if (std::isnan(hot_thresholds[k])) {
1377                     continue;
1378                 } else if (hot_thresholds[j] > (hot_thresholds[k] - hot_hysteresis[k])) {
1379                     LOG(ERROR) << "Sensor[" << name << "]'s hot threshold " << j
1380                                << " is overlapped";
1381                     sensors_parsed->clear();
1382                     return false;
1383                 } else {
1384                     break;
1385                 }
1386             }
1387         }
1388 
1389         values = sensors[i]["ColdThreshold"];
1390         if (!values.size()) {
1391             LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold, default all to NAN";
1392         } else if (values.size() != kThrottlingSeverityCount) {
1393             LOG(ERROR) << "Invalid Sensor[" << name << "]'s ColdThreshold count:" << values.size();
1394             sensors_parsed->clear();
1395             return false;
1396         } else {
1397             float max = std::numeric_limits<float>::max();
1398             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1399                 cold_thresholds[j] = getFloatFromValue(values[j]);
1400                 if (!std::isnan(cold_thresholds[j])) {
1401                     if (cold_thresholds[j] > max) {
1402                         LOG(ERROR) << "Invalid "
1403                                    << "Sensor[" << name << "]'s ColdThreshold[j" << j
1404                                    << "]: " << cold_thresholds[j] << " > " << max;
1405                         sensors_parsed->clear();
1406                         return false;
1407                     }
1408                     max = cold_thresholds[j];
1409                 }
1410                 LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold[" << j
1411                           << "]: " << cold_thresholds[j];
1412             }
1413         }
1414 
1415         values = sensors[i]["ColdHysteresis"];
1416         if (!values.size()) {
1417             LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis, default all to 0.0";
1418         } else if (values.size() != kThrottlingSeverityCount) {
1419             LOG(ERROR) << "Invalid Sensor[" << name << "]'s ColdHysteresis count:" << values.size();
1420             sensors_parsed->clear();
1421             return false;
1422         } else {
1423             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
1424                 cold_hysteresis[j] = getFloatFromValue(values[j]);
1425                 if (std::isnan(cold_hysteresis[j])) {
1426                     LOG(ERROR) << "Invalid Sensor[" << name
1427                                << "]'s ColdHysteresis: " << cold_hysteresis[j];
1428                     sensors_parsed->clear();
1429                     return false;
1430                 }
1431                 LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis[" << j
1432                           << "]: " << cold_hysteresis[j];
1433             }
1434         }
1435 
1436         for (Json::Value::ArrayIndex j = 0; j < (kThrottlingSeverityCount - 1); ++j) {
1437             if (std::isnan(cold_thresholds[j])) {
1438                 continue;
1439             }
1440             for (auto k = j + 1; k < kThrottlingSeverityCount; ++k) {
1441                 if (std::isnan(cold_thresholds[k])) {
1442                     continue;
1443                 } else if (cold_thresholds[j] < (cold_thresholds[k] + cold_hysteresis[k])) {
1444                     LOG(ERROR) << "Sensor[" << name << "]'s cold threshold " << j
1445                                << " is overlapped";
1446                     sensors_parsed->clear();
1447                     return false;
1448                 } else {
1449                     break;
1450                 }
1451             }
1452         }
1453 
1454         std::string temp_path;
1455         if (!sensors[i]["TempPath"].empty()) {
1456             temp_path = sensors[i]["TempPath"].asString();
1457             LOG(INFO) << "Sensor[" << name << "]'s TempPath: " << temp_path;
1458         }
1459 
1460         std::vector<std::string> severity_reference;
1461 
1462         values = sensors[i]["SeverityReference"];
1463         if (values.isString()) {
1464             severity_reference.emplace_back(values.asString());
1465             LOG(INFO) << "Sensor[" << name << "]'s SeverityReference:" << values.asString();
1466         } else if (values.size()) {
1467             severity_reference.reserve(values.size());
1468             for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1469                 severity_reference.emplace_back(values[j].asString());
1470                 LOG(INFO) << "Sensor[" << name << "]'s SeverityReference[" << j
1471                           << "]: " << severity_reference[j];
1472             }
1473         }
1474 
1475         float vr_threshold = NAN;
1476         if (!sensors[i]["VrThreshold"].empty()) {
1477             vr_threshold = getFloatFromValue(sensors[i]["VrThreshold"]);
1478             LOG(INFO) << "Sensor[" << name << "]'s VrThreshold: " << vr_threshold;
1479         }
1480 
1481         float multiplier = 1.0;
1482         if (!sensors[i]["Multiplier"].empty()) {
1483             multiplier = sensors[i]["Multiplier"].asFloat();
1484         }
1485         LOG(INFO) << "Sensor[" << name << "]'s Multiplier: " << multiplier;
1486 
1487         std::chrono::milliseconds polling_delay = kUeventPollTimeoutMs;
1488         if (!sensors[i]["PollingDelay"].empty()) {
1489             const auto value = getIntFromValue(sensors[i]["PollingDelay"]);
1490             polling_delay = (value > 0) ? std::chrono::milliseconds(value)
1491                                         : std::chrono::milliseconds::max();
1492         }
1493         LOG(INFO) << "Sensor[" << name << "]'s Polling delay: " << polling_delay.count();
1494 
1495         std::chrono::milliseconds passive_delay = kMinPollIntervalMs;
1496         if (!sensors[i]["PassiveDelay"].empty()) {
1497             const auto value = getIntFromValue(sensors[i]["PassiveDelay"]);
1498             passive_delay = (value > 0) ? std::chrono::milliseconds(value)
1499                                         : std::chrono::milliseconds::max();
1500         }
1501         LOG(INFO) << "Sensor[" << name << "]'s Passive delay: " << passive_delay.count();
1502 
1503         std::chrono::milliseconds time_resolution;
1504         if (sensors[i]["TimeResolution"].empty()) {
1505             time_resolution = kMinPollIntervalMs;
1506         } else {
1507             time_resolution =
1508                     std::chrono::milliseconds(getIntFromValue(sensors[i]["TimeResolution"]));
1509         }
1510         LOG(INFO) << "Sensor[" << name << "]'s Time resolution: " << time_resolution.count();
1511 
1512         float step_ratio = NAN;
1513         if (!sensors[i]["StepRatio"].empty()) {
1514             step_ratio = sensors[i]["StepRatio"].asFloat();
1515             if (step_ratio < 0 || step_ratio > 1) {
1516                 LOG(ERROR) << "Sensor[" << name << "]'s StepRatio should be set 0 ~ 1";
1517                 sensors_parsed->clear();
1518                 return false;
1519             }
1520 
1521             if (sensors[i]["PassiveDelay"].empty()) {
1522                 LOG(ERROR) << "Sensor[" << name << "] has StepRatio but no explicit PassiveDelay";
1523                 sensors_parsed->clear();
1524                 return false;
1525             }
1526         }
1527 
1528         if (is_hidden && send_cb) {
1529             LOG(ERROR) << "is_hidden and send_cb cannot be enabled together";
1530             sensors_parsed->clear();
1531             return false;
1532         }
1533 
1534         std::unique_ptr<VirtualSensorInfo> virtual_sensor_info;
1535         if (!ParseVirtualSensorInfo(name, sensors[i], &virtual_sensor_info)) {
1536             LOG(ERROR) << "Sensor[" << name << "]: failed to parse virtual sensor info";
1537             sensors_parsed->clear();
1538             return false;
1539         }
1540 
1541         std::unique_ptr<PredictorInfo> predictor_info;
1542         if (!ParsePredictorInfo(name, sensors[i], &predictor_info)) {
1543             LOG(ERROR) << "Sensor[" << name << "]: failed to parse virtual sensor info";
1544             sensors_parsed->clear();
1545             return false;
1546         }
1547 
1548         bool support_throttling = false;  // support pid or hard limit
1549         std::shared_ptr<ThrottlingInfo> throttling_info;
1550         if (!ParseSensorThrottlingInfo(name, sensors[i], &support_throttling, &throttling_info,
1551                                        scaling_frequency_map, cooling_device_info_map_)) {
1552             LOG(ERROR) << "Sensor[" << name << "]: failed to parse throttling info";
1553             sensors_parsed->clear();
1554             return false;
1555         }
1556 
1557         bool is_watch = (send_cb | send_powerhint | support_throttling);
1558         LOG(INFO) << "Sensor[" << name << "]'s is_watch: " << std::boolalpha << is_watch;
1559 
1560         (*sensors_parsed)[name] = {
1561                 .type = sensor_type,
1562                 .hot_thresholds = hot_thresholds,
1563                 .cold_thresholds = cold_thresholds,
1564                 .hot_hysteresis = hot_hysteresis,
1565                 .cold_hysteresis = cold_hysteresis,
1566                 .temp_path = temp_path,
1567                 .severity_reference = severity_reference,
1568                 .vr_threshold = vr_threshold,
1569                 .multiplier = multiplier,
1570                 .polling_delay = polling_delay,
1571                 .passive_delay = passive_delay,
1572                 .time_resolution = time_resolution,
1573                 .step_ratio = step_ratio,
1574                 .send_cb = send_cb,
1575                 .send_powerhint = send_powerhint,
1576                 .is_watch = is_watch,
1577                 .is_hidden = is_hidden,
1578                 .is_trip_point_ignorable = is_trip_point_ignorable,
1579                 .log_level = log_level,
1580                 .virtual_sensor_info = std::move(virtual_sensor_info),
1581                 .throttling_info = std::move(throttling_info),
1582                 .predictor_info = std::move(predictor_info),
1583         };
1584 
1585         ++total_parsed;
1586     }
1587     LOG(INFO) << total_parsed << " Sensors parsed successfully";
1588     return true;
1589 }
1590 
ParseCoolingDevice(const Json::Value & config,std::unordered_map<std::string,CdevInfo> * cooling_devices_parsed)1591 bool ParseCoolingDevice(const Json::Value &config,
1592                         std::unordered_map<std::string, CdevInfo> *cooling_devices_parsed) {
1593     Json::Value cooling_devices = config["CoolingDevices"];
1594     std::size_t total_parsed = 0;
1595     std::unordered_set<std::string> cooling_devices_name_parsed;
1596 
1597     for (Json::Value::ArrayIndex i = 0; i < cooling_devices.size(); ++i) {
1598         bool apply_powercap = false;
1599         float multiplier = 1.0;
1600         const std::string &name = cooling_devices[i]["Name"].asString();
1601         LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name;
1602         if (name.empty()) {
1603             LOG(ERROR) << "Failed to read CoolingDevice[" << i << "]'s Name";
1604             cooling_devices_parsed->clear();
1605             return false;
1606         }
1607 
1608         if (cooling_devices[i]["isDisabled"].asBool()) {
1609             LOG(INFO) << "CoolingDevice[" << name << "] is disabled. Skipping parsing";
1610             continue;
1611         }
1612 
1613         if (cooling_devices[i]["PowerCap"].asBool() && cooling_devices[i]["PowerCap"].isBool()) {
1614             LOG(INFO) << "CoolingDevice[" << name << "] apply powercap";
1615             apply_powercap = true;
1616         }
1617 
1618         if (!cooling_devices[i]["Multiplier"].empty()) {
1619             multiplier = cooling_devices[i]["Multiplier"].asFloat();
1620             if (multiplier <= 0) {
1621                 cooling_devices_parsed->clear();
1622                 LOG(INFO) << "CoolingDevice[" << name << "]'s Multiplier: " << multiplier
1623                           << " is invalid";
1624                 return false;
1625             }
1626         }
1627         LOG(INFO) << "CoolingDevice[" << name << "]'s Multiplier: " << multiplier;
1628 
1629         auto result = cooling_devices_name_parsed.insert(name.data());
1630         if (!result.second) {
1631             LOG(ERROR) << "Duplicate CoolingDevice[" << i << "]'s Name";
1632             cooling_devices_parsed->clear();
1633             return false;
1634         }
1635 
1636         std::string cooling_device_type_str = cooling_devices[i]["Type"].asString();
1637         LOG(INFO) << "CoolingDevice[" << name << "]'s Type: " << cooling_device_type_str;
1638         CoolingType cooling_device_type;
1639 
1640         if (!getTypeFromString(cooling_device_type_str, &cooling_device_type)) {
1641             LOG(ERROR) << "Invalid CoolingDevice[" << name
1642                        << "]'s Type: " << cooling_device_type_str;
1643             cooling_devices_parsed->clear();
1644             return false;
1645         }
1646 
1647         const std::string &read_path = cooling_devices[i]["ReadPath"].asString();
1648         LOG(INFO) << "Cdev Read Path: " << (read_path.empty() ? "default" : read_path);
1649 
1650         const std::string &write_path = cooling_devices[i]["WritePath"].asString();
1651         LOG(INFO) << "Cdev Write Path: " << (write_path.empty() ? "default" : write_path);
1652 
1653         std::vector<float> state2power;
1654         Json::Value values = cooling_devices[i]["State2Power"];
1655         if (values.size()) {
1656             LOG(INFO) << "Cooling device " << name << " use State2power read from config";
1657             state2power.reserve(values.size());
1658             for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1659                 state2power.emplace_back(getFloatFromValue(values[j]));
1660             }
1661         } else {
1662             LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name
1663                       << " does not support State2Power in thermal config";
1664         }
1665 
1666         (*cooling_devices_parsed)[name] = {
1667                 .type = cooling_device_type,
1668                 .read_path = read_path,
1669                 .write_path = write_path,
1670                 .state2power = state2power,
1671                 .apply_powercap = apply_powercap,
1672                 .multiplier = multiplier,
1673         };
1674         ++total_parsed;
1675     }
1676     LOG(INFO) << total_parsed << " CoolingDevices parsed successfully";
1677     return true;
1678 }
1679 
ParsePowerRailInfo(const Json::Value & config,std::unordered_map<std::string,PowerRailInfo> * power_rails_parsed,std::unordered_map<std::string,std::vector<std::string>> * power_rail_switch_map)1680 bool ParsePowerRailInfo(
1681         const Json::Value &config,
1682         std::unordered_map<std::string, PowerRailInfo> *power_rails_parsed,
1683         std::unordered_map<std::string, std::vector<std::string>> *power_rail_switch_map) {
1684     Json::Value power_rails = config["PowerRails"];
1685     std::size_t total_parsed = 0;
1686     std::unordered_set<std::string> power_rails_name_parsed;
1687 
1688     for (Json::Value::ArrayIndex i = 0; i < power_rails.size(); ++i) {
1689         const std::string &name = power_rails[i]["Name"].asString();
1690         LOG(INFO) << "PowerRail[" << i << "]'s Name: " << name;
1691         if (name.empty()) {
1692             LOG(ERROR) << "Failed to read PowerRail[" << i << "]'s Name";
1693             power_rails_parsed->clear();
1694             return false;
1695         }
1696 
1697         std::vector<std::string> linked_power_rails;
1698         std::vector<float> coefficient;
1699         float offset = 0;
1700         FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
1701         bool is_virtual_power_rail = false;
1702         Json::Value values;
1703         int power_sample_count = 0;
1704         std::chrono::milliseconds power_sample_delay;
1705 
1706         if (!power_rails[i]["VirtualRails"].empty() && power_rails[i]["VirtualRails"].isBool()) {
1707             is_virtual_power_rail = power_rails[i]["VirtualRails"].asBool();
1708             LOG(INFO) << "PowerRails[" << name << "]'s VirtualRail, set to 'true'";
1709         }
1710 
1711         if (is_virtual_power_rail) {
1712             values = power_rails[i]["Combination"];
1713             if (values.size()) {
1714                 linked_power_rails.reserve(values.size());
1715                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1716                     linked_power_rails.emplace_back(values[j].asString());
1717                     LOG(INFO) << "PowerRail[" << name << "]'s combination[" << j
1718                               << "]: " << linked_power_rails[j];
1719                 }
1720             } else {
1721                 LOG(ERROR) << "PowerRails[" << name << "] has no combination for VirtualRail";
1722                 power_rails_parsed->clear();
1723                 return false;
1724             }
1725 
1726             values = power_rails[i]["Coefficient"];
1727             if (values.size()) {
1728                 coefficient.reserve(values.size());
1729                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
1730                     coefficient.emplace_back(getFloatFromValue(values[j]));
1731                     LOG(INFO) << "PowerRail[" << name << "]'s coefficient[" << j
1732                               << "]: " << coefficient[j];
1733                 }
1734             } else {
1735                 LOG(ERROR) << "PowerRails[" << name << "] has no coefficient for VirtualRail";
1736                 power_rails_parsed->clear();
1737                 return false;
1738             }
1739 
1740             if (linked_power_rails.size() != coefficient.size()) {
1741                 LOG(ERROR) << "PowerRails[" << name
1742                            << "]'s combination size is not matched with coefficient size";
1743                 power_rails_parsed->clear();
1744                 return false;
1745             }
1746 
1747             if (!power_rails[i]["Offset"].empty()) {
1748                 offset = power_rails[i]["Offset"].asFloat();
1749             }
1750 
1751             if (linked_power_rails.size() != coefficient.size()) {
1752                 LOG(ERROR) << "PowerRails[" << name
1753                            << "]'s combination size is not matched with coefficient size";
1754                 power_rails_parsed->clear();
1755                 return false;
1756             }
1757 
1758             if (power_rails[i]["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
1759                 formula = FormulaOption::COUNT_THRESHOLD;
1760             } else if (power_rails[i]["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
1761                 formula = FormulaOption::WEIGHTED_AVG;
1762             } else if (power_rails[i]["Formula"].asString().compare("MAXIMUM") == 0) {
1763                 formula = FormulaOption::MAXIMUM;
1764             } else if (power_rails[i]["Formula"].asString().compare("MINIMUM") == 0) {
1765                 formula = FormulaOption::MINIMUM;
1766             } else {
1767                 LOG(ERROR) << "PowerRails[" << name << "]'s Formula is invalid";
1768                 power_rails_parsed->clear();
1769                 return false;
1770             }
1771         }
1772 
1773         std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
1774         if (is_virtual_power_rail) {
1775             virtual_power_rail_info.reset(
1776                     new VirtualPowerRailInfo{linked_power_rails, coefficient, offset, formula});
1777         }
1778 
1779         power_sample_count = power_rails[i]["PowerSampleCount"].asInt();
1780         LOG(INFO) << "Power sample Count: " << power_sample_count;
1781 
1782         if (!power_rails[i]["PowerSampleDelay"]) {
1783             power_sample_delay = std::chrono::milliseconds::max();
1784         } else {
1785             power_sample_delay =
1786                     std::chrono::milliseconds(getIntFromValue(power_rails[i]["PowerSampleDelay"]));
1787         }
1788 
1789         std::string trigger_sensor;
1790         values = power_rails[i]["TriggerSensor"];
1791         if (!values.empty()) {
1792             if (values.isString()) {
1793                 (*power_rail_switch_map)[values.asString()].emplace_back(name);
1794                 LOG(INFO) << "Power rail[" << name << "]'s TriggerSensor: " << values.asString();
1795             }
1796         }
1797 
1798         (*power_rails_parsed)[name] = {
1799                 .power_sample_count = power_sample_count,
1800                 .power_sample_delay = power_sample_delay,
1801                 .virtual_power_rail_info = std::move(virtual_power_rail_info),
1802         };
1803         ++total_parsed;
1804     }
1805     LOG(INFO) << total_parsed << " PowerRails parsed successfully";
1806     return true;
1807 }
1808 
1809 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)1810 bool ParseStatsInfo(const Json::Value &stats_config,
1811                     const std::unordered_map<std::string, U> &entity_info, StatsInfo<T> *stats_info,
1812                     T min_value) {
1813     if (stats_config.empty()) {
1814         LOG(INFO) << "No stats config";
1815         return true;
1816     }
1817     std::variant<bool, std::unordered_set<std::string>>
1818             record_by_default_threshold_all_or_name_set_ = false;
1819     if (stats_config["DefaultThresholdEnableAll"].empty() ||
1820         !stats_config["DefaultThresholdEnableAll"].isBool()) {
1821         LOG(INFO) << "Failed to read stats DefaultThresholdEnableAll, set to 'false'";
1822     } else if (stats_config["DefaultThresholdEnableAll"].asBool()) {
1823         record_by_default_threshold_all_or_name_set_ = true;
1824     }
1825     LOG(INFO) << "DefaultThresholdEnableAll " << std::boolalpha
1826               << std::get<bool>(record_by_default_threshold_all_or_name_set_) << std::noboolalpha;
1827 
1828     Json::Value values = stats_config["RecordWithDefaultThreshold"];
1829     if (values.size()) {
1830         if (std::get<bool>(record_by_default_threshold_all_or_name_set_)) {
1831             LOG(ERROR) << "Cannot enable record with default threshold when "
1832                           "DefaultThresholdEnableAll true.";
1833             return false;
1834         }
1835         record_by_default_threshold_all_or_name_set_ = std::unordered_set<std::string>();
1836         for (Json::Value::ArrayIndex i = 0; i < values.size(); ++i) {
1837             std::string name = values[i].asString();
1838             if (!entity_info.count(name)) {
1839                 LOG(ERROR) << "Unknown name [" << name << "] not present in entity_info.";
1840                 return false;
1841             }
1842             std::get<std::unordered_set<std::string>>(record_by_default_threshold_all_or_name_set_)
1843                     .insert(name);
1844         }
1845     } else {
1846         LOG(INFO) << "No stat by default threshold enabled.";
1847     }
1848 
1849     std::unordered_map<std::string, std::vector<ThresholdList<T>>> record_by_threshold;
1850     values = stats_config["RecordWithThreshold"];
1851     if (values.size()) {
1852         Json::Value threshold_values;
1853         for (Json::Value::ArrayIndex i = 0; i < values.size(); i++) {
1854             const std::string &name = values[i]["Name"].asString();
1855             if (!entity_info.count(name)) {
1856                 LOG(ERROR) << "Unknown name [" << name << "] not present in entity_info.";
1857                 return false;
1858             }
1859 
1860             std::optional<std::string> logging_name;
1861             if (!values[i]["LoggingName"].empty()) {
1862                 logging_name = values[i]["LoggingName"].asString();
1863                 LOG(INFO) << "For [" << name << "]"
1864                           << ", stats logging name is [" << logging_name.value() << "]";
1865             }
1866 
1867             LOG(INFO) << "Start to parse stats threshold for [" << name << "]";
1868             threshold_values = values[i]["Thresholds"];
1869             if (threshold_values.empty()) {
1870                 LOG(ERROR) << "Empty stats threshold not valid.";
1871                 return false;
1872             }
1873             const auto &threshold_values_count = threshold_values.size();
1874             if (threshold_values_count > kMaxStatsThresholdCount) {
1875                 LOG(ERROR) << "Number of stats threshold " << threshold_values_count
1876                            << " greater than max " << kMaxStatsThresholdCount;
1877                 return false;
1878             }
1879             std::vector<T> stats_threshold(threshold_values_count);
1880             T prev_value = min_value;
1881             LOG(INFO) << "Thresholds:";
1882             for (Json::Value::ArrayIndex i = 0; i < threshold_values_count; ++i) {
1883                 stats_threshold[i] = std::is_floating_point_v<T>
1884                                              ? getFloatFromValue(threshold_values[i])
1885                                              : getIntFromValue(threshold_values[i]);
1886                 if (stats_threshold[i] <= prev_value) {
1887                     LOG(ERROR) << "Invalid array[" << i << "]" << stats_threshold[i]
1888                                << " is <=" << prev_value;
1889                     return false;
1890                 }
1891                 prev_value = stats_threshold[i];
1892                 LOG(INFO) << "[" << i << "]: " << stats_threshold[i];
1893             }
1894             record_by_threshold[name].emplace_back(logging_name, stats_threshold);
1895         }
1896     } else {
1897         LOG(INFO) << "No stat by threshold enabled.";
1898     }
1899 
1900     (*stats_info) = {.record_by_default_threshold_all_or_name_set_ =
1901                              record_by_default_threshold_all_or_name_set_,
1902                      .record_by_threshold = record_by_threshold};
1903     return true;
1904 }
1905 
ParseSensorAbnormalStatsConfig(const Json::Value & abnormal_stats_config,const std::unordered_map<std::string,SensorInfo> & sensor_info_map_,AbnormalStatsInfo * abnormal_stats_info_parsed)1906 bool ParseSensorAbnormalStatsConfig(
1907         const Json::Value &abnormal_stats_config,
1908         const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
1909         AbnormalStatsInfo *abnormal_stats_info_parsed) {
1910     if (abnormal_stats_config.empty()) {
1911         LOG(INFO) << "No sensors abnormality monitoring info present.";
1912         return true;
1913     }
1914 
1915     Json::Value values;
1916 
1917     std::optional<TempRangeInfo> default_temp_range_info;
1918     std::vector<AbnormalStatsInfo::SensorsTempRangeInfo> sensors_temp_range_infos;
1919     Json::Value outlier_temp_config = abnormal_stats_config["Outlier"];
1920     if (outlier_temp_config) {
1921         LOG(INFO) << "Start to parse outlier temp config.";
1922 
1923         if (outlier_temp_config["Default"]) {
1924             LOG(INFO) << "Start to parse defaultTempRange.";
1925             if (!getTempRangeInfoFromJsonValues(outlier_temp_config["Default"],
1926                                                 &default_temp_range_info.value())) {
1927                 LOG(ERROR) << "Failed to parse default temp range config.";
1928                 return false;
1929             }
1930         }
1931 
1932         Json::Value configs = outlier_temp_config["Configs"];
1933         if (configs) {
1934             std::unordered_set<std::string> sensors_parsed;
1935             for (Json::Value::ArrayIndex i = 0; i < configs.size(); i++) {
1936                 LOG(INFO) << "Start to parse temp range config[" << i << "]";
1937                 AbnormalStatsInfo::SensorsTempRangeInfo sensors_temp_range_info;
1938                 values = configs[i]["Monitor"];
1939                 if (!values.size()) {
1940                     LOG(ERROR) << "Invalid config no sensor list present for outlier temp "
1941                                   "config.";
1942                     return false;
1943                 }
1944                 for (Json::Value::ArrayIndex j = 0; j < values.size(); j++) {
1945                     const std::string &sensor = values[j].asString();
1946                     if (!sensor_info_map_.count(sensor)) {
1947                         LOG(ERROR) << "Unknown sensor " << sensor;
1948                         return false;
1949                     }
1950                     auto result = sensors_parsed.insert(sensor);
1951                     if (!result.second) {
1952                         LOG(ERROR) << "Duplicate Sensor Temp Range Config: " << sensor;
1953                         return false;
1954                     }
1955                     LOG(INFO) << "Monitored sensor [" << j << "]: " << sensor;
1956                     sensors_temp_range_info.sensors.push_back(sensor);
1957                 }
1958                 if (!getTempRangeInfoFromJsonValues(configs[i]["TempRange"],
1959                                                     &sensors_temp_range_info.temp_range_info)) {
1960                     LOG(ERROR) << "Failed to parse temp range config.";
1961                     return false;
1962                 }
1963                 sensors_temp_range_infos.push_back(sensors_temp_range_info);
1964             }
1965         }
1966     }
1967     std::optional<TempStuckInfo> default_temp_stuck_info;
1968     std::vector<AbnormalStatsInfo::SensorsTempStuckInfo> sensors_temp_stuck_infos;
1969     Json::Value stuck_temp_config = abnormal_stats_config["Stuck"];
1970     if (stuck_temp_config) {
1971         LOG(INFO) << "Start to parse stuck temp config.";
1972 
1973         if (stuck_temp_config["Default"]) {
1974             LOG(INFO) << "Start to parse defaultTempStuck.";
1975             if (!getTempStuckInfoFromJsonValue(stuck_temp_config["Default"],
1976                                                &default_temp_stuck_info.value())) {
1977                 LOG(ERROR) << "Failed to parse default temp stuck config.";
1978                 return false;
1979             }
1980         }
1981 
1982         Json::Value configs = stuck_temp_config["Configs"];
1983         if (configs) {
1984             std::unordered_set<std::string> sensors_parsed;
1985             for (Json::Value::ArrayIndex i = 0; i < configs.size(); i++) {
1986                 LOG(INFO) << "Start to parse temp stuck config[" << i << "]";
1987                 AbnormalStatsInfo::SensorsTempStuckInfo sensor_temp_stuck_info;
1988                 values = configs[i]["Monitor"];
1989                 if (!values.size()) {
1990                     LOG(ERROR) << "Invalid config no sensor list present for stuck temp "
1991                                   "config.";
1992                     return false;
1993                 }
1994                 for (Json::Value::ArrayIndex j = 0; j < values.size(); j++) {
1995                     const std::string &sensor = values[j].asString();
1996                     if (!sensor_info_map_.count(sensor)) {
1997                         LOG(ERROR) << "Unknown sensor " << sensor;
1998                         return false;
1999                     }
2000                     auto result = sensors_parsed.insert(sensor);
2001                     if (!result.second) {
2002                         LOG(ERROR) << "Duplicate Sensor Temp Stuck Config: " << sensor;
2003                         return false;
2004                     }
2005                     LOG(INFO) << "Monitored sensor [" << j << "]: " << sensor;
2006                     sensor_temp_stuck_info.sensors.push_back(sensor);
2007                 }
2008                 if (!getTempStuckInfoFromJsonValue(configs[i]["TempStuck"],
2009                                                    &sensor_temp_stuck_info.temp_stuck_info)) {
2010                     LOG(ERROR) << "Failed to parse temp stuck config.";
2011                     return false;
2012                 }
2013                 sensors_temp_stuck_infos.push_back(sensor_temp_stuck_info);
2014             }
2015         }
2016     }
2017     *abnormal_stats_info_parsed = {
2018             .default_temp_range_info = default_temp_range_info,
2019             .sensors_temp_range_infos = sensors_temp_range_infos,
2020             .default_temp_stuck_info = default_temp_stuck_info,
2021             .sensors_temp_stuck_infos = sensors_temp_stuck_infos,
2022     };
2023     return true;
2024 }
2025 
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)2026 bool ParseSensorStatsConfig(const Json::Value &config,
2027                             const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
2028                             StatsInfo<float> *sensor_stats_info_parsed,
2029                             AbnormalStatsInfo *abnormal_stats_info_parsed) {
2030     Json::Value stats_config = config["Stats"];
2031     if (stats_config.empty()) {
2032         LOG(INFO) << "No Stats Config present.";
2033         return true;
2034     }
2035     // Parse cooling device user vote
2036     Json::Value sensor_config = stats_config["Sensors"];
2037     if (sensor_config.empty()) {
2038         LOG(INFO) << "No Sensor Stats Config present.";
2039         return true;
2040     }
2041     LOG(INFO) << "Parse Stats Config for Sensor Temp.";
2042     // Parse sensor stats config
2043     if (!ParseStatsInfo(stats_config["Sensors"], sensor_info_map_, sensor_stats_info_parsed,
2044                         std::numeric_limits<float>::lowest())) {
2045         LOG(ERROR) << "Failed to parse sensor temp stats info.";
2046         sensor_stats_info_parsed->clear();
2047         return false;
2048     }
2049     if (!ParseSensorAbnormalStatsConfig(sensor_config["Abnormality"], sensor_info_map_,
2050                                         abnormal_stats_info_parsed)) {
2051         LOG(ERROR) << "Failed to parse sensor abnormal stats config.";
2052         return false;
2053     }
2054     return true;
2055 }
2056 
ParseCoolingDeviceStatsConfig(const Json::Value & config,const std::unordered_map<std::string,CdevInfo> & cooling_device_info_map_,StatsInfo<int> * cooling_device_request_info_parsed)2057 bool ParseCoolingDeviceStatsConfig(
2058         const Json::Value &config,
2059         const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_,
2060         StatsInfo<int> *cooling_device_request_info_parsed) {
2061     Json::Value stats_config = config["Stats"];
2062     if (stats_config.empty()) {
2063         LOG(INFO) << "No Stats Config present.";
2064         return true;
2065     }
2066     // Parse cooling device user vote
2067     if (stats_config["CoolingDevices"].empty()) {
2068         LOG(INFO) << "No cooling device stats present.";
2069         return true;
2070     }
2071     LOG(INFO) << "Parse Stats Config for Sensor CDev Request.";
2072     if (!ParseStatsInfo(stats_config["CoolingDevices"]["RecordVotePerSensor"],
2073                         cooling_device_info_map_, cooling_device_request_info_parsed, -1)) {
2074         LOG(ERROR) << "Failed to parse cooling device user vote stats info.";
2075         cooling_device_request_info_parsed->clear();
2076         return false;
2077     }
2078     return true;
2079 }
2080 }  // namespace implementation
2081 }  // namespace thermal
2082 }  // namespace hardware
2083 }  // namespace android
2084 }  // namespace aidl
2085