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