1 /*
2  * Copyright (C) 2018 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 <android-base/file.h>
17 #include <android-base/logging.h>
18 #include <android-base/properties.h>
19 #include <android-base/strings.h>
20 #include <cmath>
21 #include <unordered_set>
22 
23 #include <json/reader.h>
24 #include <json/value.h>
25 
26 #include "config_parser.h"
27 
28 namespace android {
29 namespace hardware {
30 namespace thermal {
31 namespace V2_0 {
32 namespace implementation {
33 
34 constexpr std::string_view kPowerLinkDisabledProperty("vendor.disable.thermal.powerlink");
35 
36 using ::android::hardware::hidl_enum_range;
37 using ::android::hardware::thermal::V2_0::toString;
38 using TemperatureType_2_0 = ::android::hardware::thermal::V2_0::TemperatureType;
39 
40 namespace {
41 
42 template <typename T>
43 // Return false when failed parsing
getTypeFromString(std::string_view str,T * out)44 bool getTypeFromString(std::string_view str, T *out) {
45     auto types = hidl_enum_range<T>();
46     for (const auto &type : types) {
47         if (toString(type) == str) {
48             *out = type;
49             return true;
50         }
51     }
52     return false;
53 }
54 
getFloatFromValue(const Json::Value & value)55 float getFloatFromValue(const Json::Value &value) {
56     if (value.isString()) {
57         return std::stof(value.asString());
58     } else {
59         return value.asFloat();
60     }
61 }
62 
getIntFromValue(const Json::Value & value)63 int getIntFromValue(const Json::Value &value) {
64     if (value.isString()) {
65         return (value.asString() == "max") ? std::numeric_limits<int>::max()
66                                            : std::stoul(value.asString());
67     } else {
68         return value.asInt();
69     }
70 }
71 
getIntFromJsonValues(const Json::Value & values,CdevArray * out,bool inc_check,bool dec_check)72 bool getIntFromJsonValues(const Json::Value &values, CdevArray *out, bool inc_check,
73                           bool dec_check) {
74     CdevArray ret;
75 
76     if (inc_check && dec_check) {
77         LOG(ERROR) << "Cannot enable inc_check and dec_check at the same time";
78         return false;
79     }
80 
81     if (values.size() != kThrottlingSeverityCount) {
82         LOG(ERROR) << "Values size is invalid";
83         return false;
84     } else {
85         int last;
86         for (Json::Value::ArrayIndex i = 0; i < kThrottlingSeverityCount; ++i) {
87             ret[i] = getIntFromValue(values[i]);
88             if (inc_check && ret[i] < last) {
89                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " min=" << last;
90                 return false;
91             }
92             if (dec_check && ret[i] > last) {
93                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " max=" << last;
94                 return false;
95             }
96             last = ret[i];
97             LOG(INFO) << "[" << i << "]: " << ret[i];
98         }
99     }
100 
101     *out = ret;
102     return true;
103 }
104 
getFloatFromJsonValues(const Json::Value & values,ThrottlingArray * out,bool inc_check,bool dec_check)105 bool getFloatFromJsonValues(const Json::Value &values, ThrottlingArray *out, bool inc_check,
106                             bool dec_check) {
107     ThrottlingArray ret;
108 
109     if (inc_check && dec_check) {
110         LOG(ERROR) << "Cannot enable inc_check and dec_check at the same time";
111         return false;
112     }
113 
114     if (values.size() != kThrottlingSeverityCount) {
115         LOG(ERROR) << "Values size is invalid";
116         return false;
117     } else {
118         float last = std::nanf("");
119         for (Json::Value::ArrayIndex i = 0; i < kThrottlingSeverityCount; ++i) {
120             ret[i] = getFloatFromValue(values[i]);
121             if (inc_check && !std::isnan(last) && !std::isnan(ret[i]) && ret[i] < last) {
122                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " min=" << last;
123                 return false;
124             }
125             if (dec_check && !std::isnan(last) && !std::isnan(ret[i]) && ret[i] > last) {
126                 LOG(FATAL) << "Invalid array[" << i << "]" << ret[i] << " max=" << last;
127                 return false;
128             }
129             last = std::isnan(ret[i]) ? last : ret[i];
130             LOG(INFO) << "[" << i << "]: " << ret[i];
131         }
132     }
133 
134     *out = ret;
135     return true;
136 }
137 }  // namespace
138 
ParseSensorInfo(std::string_view config_path)139 std::unordered_map<std::string, SensorInfo> ParseSensorInfo(std::string_view config_path) {
140     std::string json_doc;
141     std::unordered_map<std::string, SensorInfo> sensors_parsed;
142     if (!android::base::ReadFileToString(config_path.data(), &json_doc)) {
143         LOG(ERROR) << "Failed to read JSON config from " << config_path;
144         return sensors_parsed;
145     }
146 
147     Json::Value root;
148     Json::CharReaderBuilder builder;
149     std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
150     std::string errorMessage;
151 
152     if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), &root, &errorMessage)) {
153         LOG(ERROR) << "Failed to parse JSON config: " << errorMessage;
154         return sensors_parsed;
155     }
156 
157     Json::Value sensors = root["Sensors"];
158     std::size_t total_parsed = 0;
159     std::unordered_set<std::string> sensors_name_parsed;
160 
161     for (Json::Value::ArrayIndex i = 0; i < sensors.size(); ++i) {
162         const std::string &name = sensors[i]["Name"].asString();
163         LOG(INFO) << "Sensor[" << i << "]'s Name: " << name;
164         if (name.empty()) {
165             LOG(ERROR) << "Failed to read "
166                        << "Sensor[" << i << "]'s Name";
167             sensors_parsed.clear();
168             return sensors_parsed;
169         }
170 
171         auto result = sensors_name_parsed.insert(name);
172         if (!result.second) {
173             LOG(ERROR) << "Duplicate Sensor[" << i << "]'s Name";
174             sensors_parsed.clear();
175             return sensors_parsed;
176         }
177 
178         std::string sensor_type_str = sensors[i]["Type"].asString();
179         LOG(INFO) << "Sensor[" << name << "]'s Type: " << sensor_type_str;
180         TemperatureType_2_0 sensor_type;
181 
182         if (!getTypeFromString(sensor_type_str, &sensor_type)) {
183             LOG(ERROR) << "Invalid "
184                        << "Sensor[" << name << "]'s Type: " << sensor_type_str;
185             sensors_parsed.clear();
186             return sensors_parsed;
187         }
188 
189         bool send_cb = false;
190         if (sensors[i]["Monitor"].empty() || !sensors[i]["Monitor"].isBool()) {
191             LOG(INFO) << "Failed to read Sensor[" << name << "]'s Monitor, set to 'false'";
192         } else if (sensors[i]["Monitor"].asBool()) {
193             send_cb = true;
194         }
195         LOG(INFO) << "Sensor[" << name << "]'s SendCallback: " << std::boolalpha << send_cb
196                   << std::noboolalpha;
197 
198         bool send_powerhint = false;
199         if (sensors[i]["SendPowerHint"].empty() || !sensors[i]["SendPowerHint"].isBool()) {
200             LOG(INFO) << "Failed to read Sensor[" << name << "]'s SendPowerHint, set to 'false'";
201         } else if (sensors[i]["SendPowerHint"].asBool()) {
202             send_powerhint = true;
203         }
204         LOG(INFO) << "Sensor[" << name << "]'s SendPowerHint: " << std::boolalpha << send_powerhint
205                   << std::noboolalpha;
206 
207         std::array<float, kThrottlingSeverityCount> hot_thresholds;
208         hot_thresholds.fill(NAN);
209         std::array<float, kThrottlingSeverityCount> cold_thresholds;
210         cold_thresholds.fill(NAN);
211         std::array<float, kThrottlingSeverityCount> hot_hysteresis;
212         hot_hysteresis.fill(0.0);
213         std::array<float, kThrottlingSeverityCount> cold_hysteresis;
214         cold_hysteresis.fill(0.0);
215         std::vector<std::string> linked_sensors;
216         std::vector<float> coefficients;
217         float offset = 0;
218         std::string trigger_sensor;
219 
220         FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
221         bool is_virtual_sensor = false;
222         if (sensors[i]["VirtualSensor"].empty() || !sensors[i]["VirtualSensor"].isBool()) {
223             LOG(INFO) << "Failed to read Sensor[" << name << "]'s VirtualSensor, set to 'false'";
224         } else {
225             is_virtual_sensor = sensors[i]["VirtualSensor"].asBool();
226         }
227         Json::Value values = sensors[i]["HotThreshold"];
228         if (values.size() != kThrottlingSeverityCount) {
229             LOG(ERROR) << "Invalid "
230                        << "Sensor[" << name << "]'s HotThreshold count" << values.size();
231             sensors_parsed.clear();
232             return sensors_parsed;
233         } else {
234             float min = std::numeric_limits<float>::min();
235             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
236                 hot_thresholds[j] = getFloatFromValue(values[j]);
237                 if (!std::isnan(hot_thresholds[j])) {
238                     if (hot_thresholds[j] < min) {
239                         LOG(ERROR) << "Invalid "
240                                    << "Sensor[" << name << "]'s HotThreshold[j" << j
241                                    << "]: " << hot_thresholds[j] << " < " << min;
242                         sensors_parsed.clear();
243                         return sensors_parsed;
244                     }
245                     min = hot_thresholds[j];
246                 }
247                 LOG(INFO) << "Sensor[" << name << "]'s HotThreshold[" << j
248                           << "]: " << hot_thresholds[j];
249             }
250         }
251 
252         values = sensors[i]["HotHysteresis"];
253         if (values.size() != kThrottlingSeverityCount) {
254             LOG(INFO) << "Cannot find valid "
255                       << "Sensor[" << name << "]'s HotHysteresis, default all to 0.0";
256         } else {
257             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
258                 hot_hysteresis[j] = getFloatFromValue(values[j]);
259                 if (std::isnan(hot_hysteresis[j])) {
260                     LOG(ERROR) << "Invalid "
261                                << "Sensor[" << name << "]'s HotHysteresis: " << hot_hysteresis[j];
262                     sensors_parsed.clear();
263                     return sensors_parsed;
264                 }
265                 LOG(INFO) << "Sensor[" << name << "]'s HotHysteresis[" << j
266                           << "]: " << hot_hysteresis[j];
267             }
268         }
269 
270         values = sensors[i]["ColdThreshold"];
271         if (values.size() != kThrottlingSeverityCount) {
272             LOG(INFO) << "Cannot find valid "
273                       << "Sensor[" << name << "]'s ColdThreshold, default all to NAN";
274         } else {
275             float max = std::numeric_limits<float>::max();
276             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
277                 cold_thresholds[j] = getFloatFromValue(values[j]);
278                 if (!std::isnan(cold_thresholds[j])) {
279                     if (cold_thresholds[j] > max) {
280                         LOG(ERROR) << "Invalid "
281                                    << "Sensor[" << name << "]'s ColdThreshold[j" << j
282                                    << "]: " << cold_thresholds[j] << " > " << max;
283                         sensors_parsed.clear();
284                         return sensors_parsed;
285                     }
286                     max = cold_thresholds[j];
287                 }
288                 LOG(INFO) << "Sensor[" << name << "]'s ColdThreshold[" << j
289                           << "]: " << cold_thresholds[j];
290             }
291         }
292 
293         values = sensors[i]["ColdHysteresis"];
294         if (values.size() != kThrottlingSeverityCount) {
295             LOG(INFO) << "Cannot find valid "
296                       << "Sensor[" << name << "]'s ColdHysteresis, default all to 0.0";
297         } else {
298             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
299                 cold_hysteresis[j] = getFloatFromValue(values[j]);
300                 if (std::isnan(cold_hysteresis[j])) {
301                     LOG(ERROR) << "Invalid "
302                                << "Sensor[" << name
303                                << "]'s ColdHysteresis: " << cold_hysteresis[j];
304                     sensors_parsed.clear();
305                     return sensors_parsed;
306                 }
307                 LOG(INFO) << "Sensor[" << name << "]'s ColdHysteresis[" << j
308                           << "]: " << cold_hysteresis[j];
309             }
310         }
311 
312         if (is_virtual_sensor) {
313             values = sensors[i]["Combination"];
314             if (values.size()) {
315                 linked_sensors.reserve(values.size());
316                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
317                     linked_sensors.emplace_back(values[j].asString());
318                     LOG(INFO) << "Sensor[" << name << "]'s combination[" << j
319                               << "]: " << linked_sensors[j];
320                 }
321             } else {
322                 sensors_parsed.clear();
323                 return sensors_parsed;
324             }
325 
326             values = sensors[i]["Coefficient"];
327             if (values.size()) {
328                 coefficients.reserve(values.size());
329                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
330                     coefficients.emplace_back(getFloatFromValue(values[j]));
331                     LOG(INFO) << "Sensor[" << name << "]'s coefficient[" << j
332                               << "]: " << coefficients[j];
333                 }
334             } else {
335                 sensors_parsed.clear();
336                 return sensors_parsed;
337             }
338 
339             if (!sensors[i]["Offset"].empty()) {
340                 offset = sensors[i]["Offset"].asFloat();
341             }
342 
343             if (linked_sensors.size() != coefficients.size()) {
344                 sensors_parsed.clear();
345                 return sensors_parsed;
346             }
347 
348             trigger_sensor = sensors[i]["TriggerSensor"].asString();
349             if (sensors[i]["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
350                 formula = FormulaOption::COUNT_THRESHOLD;
351             } else if (sensors[i]["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
352                 formula = FormulaOption::WEIGHTED_AVG;
353             } else if (sensors[i]["Formula"].asString().compare("MAXIMUM") == 0) {
354                 formula = FormulaOption::MAXIMUM;
355             } else if (sensors[i]["Formula"].asString().compare("MINIMUM") == 0) {
356                 formula = FormulaOption::MINIMUM;
357             } else {
358                 sensors_parsed.clear();
359                 return sensors_parsed;
360             }
361         }
362 
363         std::string temp_path;
364         if (!sensors[i]["TempPath"].empty()) {
365             temp_path = sensors[i]["TempPath"].asString();
366             LOG(INFO) << "Sensor[" << name << "]'s TempPath: " << temp_path;
367         }
368 
369         float vr_threshold = NAN;
370         vr_threshold = getFloatFromValue(sensors[i]["VrThreshold"]);
371         LOG(INFO) << "Sensor[" << name << "]'s VrThreshold: " << vr_threshold;
372 
373         float multiplier = sensors[i]["Multiplier"].asFloat();
374         LOG(INFO) << "Sensor[" << name << "]'s Multiplier: " << multiplier;
375 
376         std::chrono::milliseconds polling_delay;
377         if (sensors[i]["PollingDelay"].empty()) {
378             polling_delay = kUeventPollTimeoutMs;
379         } else {
380             polling_delay = std::chrono::milliseconds(getIntFromValue(sensors[i]["PollingDelay"]));
381         }
382         LOG(INFO) << "Sensor[" << name << "]'s Polling delay: " << polling_delay.count();
383 
384         std::chrono::milliseconds passive_delay;
385         if (sensors[i]["PassiveDelay"].empty()) {
386             passive_delay = kMinPollIntervalMs;
387         } else {
388             passive_delay = std::chrono::milliseconds(getIntFromValue(sensors[i]["PassiveDelay"]));
389         }
390         LOG(INFO) << "Sensor[" << name << "]'s Passive delay: " << passive_delay.count();
391 
392         bool support_pid = false;
393         std::array<float, kThrottlingSeverityCount> k_po;
394         k_po.fill(0.0);
395         std::array<float, kThrottlingSeverityCount> k_pu;
396         k_pu.fill(0.0);
397         std::array<float, kThrottlingSeverityCount> k_i;
398         k_i.fill(0.0);
399         std::array<float, kThrottlingSeverityCount> k_d;
400         k_d.fill(0.0);
401         std::array<float, kThrottlingSeverityCount> i_max;
402         i_max.fill(NAN);
403         std::array<float, kThrottlingSeverityCount> max_alloc_power;
404         max_alloc_power.fill(NAN);
405         std::array<float, kThrottlingSeverityCount> min_alloc_power;
406         min_alloc_power.fill(NAN);
407         std::array<float, kThrottlingSeverityCount> s_power;
408         s_power.fill(NAN);
409         std::array<float, kThrottlingSeverityCount> i_cutoff;
410         i_cutoff.fill(NAN);
411 
412         // Parse PID parameters
413         if (!sensors[i]["PIDInfo"].empty()) {
414             LOG(INFO) << "Start to parse"
415                       << " Sensor[" << name << "]'s K_Po";
416             if (sensors[i]["PIDInfo"]["K_Po"].empty() ||
417                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["K_Po"], &k_po, false, false)) {
418                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Po";
419                 sensors_parsed.clear();
420                 return sensors_parsed;
421             }
422             LOG(INFO) << "Start to parse"
423                       << " Sensor[" << name << "]'s  K_Pu";
424             if (sensors[i]["PIDInfo"]["K_Pu"].empty() ||
425                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["K_Pu"], &k_pu, false, false)) {
426                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_Pu";
427                 sensors_parsed.clear();
428                 return sensors_parsed;
429             }
430             LOG(INFO) << "Start to parse"
431                       << " Sensor[" << name << "]'s K_I";
432             if (sensors[i]["PIDInfo"]["K_I"].empty() ||
433                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["K_I"], &k_i, false, false)) {
434                 LOG(INFO) << "Sensor[" << name << "]: Failed to parse K_I";
435                 sensors_parsed.clear();
436                 return sensors_parsed;
437             }
438             LOG(INFO) << "Start to parse"
439                       << " Sensor[" << name << "]'s K_D";
440             if (sensors[i]["PIDInfo"]["K_D"].empty() ||
441                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["K_D"], &k_d, false, false)) {
442                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse K_D";
443                 sensors_parsed.clear();
444                 return sensors_parsed;
445             }
446             LOG(INFO) << "Start to parse"
447                       << " Sensor[" << name << "]'s I_Max";
448             if (sensors[i]["PIDInfo"]["I_Max"].empty() ||
449                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["I_Max"], &i_max, false, false)) {
450                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Max";
451                 sensors_parsed.clear();
452                 return sensors_parsed;
453             }
454             LOG(INFO) << "Start to parse"
455                       << " Sensor[" << name << "]'s MaxAllocPower";
456             if (sensors[i]["PIDInfo"]["MaxAllocPower"].empty() ||
457                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["MaxAllocPower"], &max_alloc_power,
458                                         false, true)) {
459                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MaxAllocPower";
460                 sensors_parsed.clear();
461                 return sensors_parsed;
462             }
463             LOG(INFO) << "Start to parse"
464                       << " Sensor[" << name << "]'s MinAllocPower";
465             if (sensors[i]["PIDInfo"]["MinAllocPower"].empty() ||
466                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["MinAllocPower"], &min_alloc_power,
467                                         false, true)) {
468                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse MinAllocPower";
469                 sensors_parsed.clear();
470                 return sensors_parsed;
471             }
472             LOG(INFO) << "Start to parse"
473                       << " Sensor[" << name << "]'s S_Power";
474             if (sensors[i]["PIDInfo"]["S_Power"].empty() ||
475                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["S_Power"], &s_power, false, true)) {
476                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse S_Power";
477                 sensors_parsed.clear();
478                 return sensors_parsed;
479             }
480             LOG(INFO) << "Start to parse"
481                       << " Sensor[" << name << "]'s I_Cutoff";
482             if (sensors[i]["PIDInfo"]["I_Cutoff"].empty() ||
483                 !getFloatFromJsonValues(sensors[i]["PIDInfo"]["I_Cutoff"], &i_cutoff, false,
484                                         false)) {
485                 LOG(ERROR) << "Sensor[" << name << "]: Failed to parse I_Cutoff";
486                 sensors_parsed.clear();
487                 return sensors_parsed;
488             }
489             // Confirm we have at least one valid PID combination
490             bool valid_pid_combination = false;
491             for (Json::Value::ArrayIndex j = 0; j < kThrottlingSeverityCount; ++j) {
492                 if (!std::isnan(s_power[j])) {
493                     if (std::isnan(k_po[j]) || std::isnan(k_pu[j]) || std::isnan(k_i[j]) ||
494                         std::isnan(k_d[j]) || std::isnan(i_max[j]) ||
495                         std::isnan(max_alloc_power[j]) || std::isnan(min_alloc_power[j]) ||
496                         std::isnan(i_cutoff[j])) {
497                         valid_pid_combination = false;
498                         break;
499                     } else {
500                         valid_pid_combination = true;
501                     }
502                 }
503             }
504             if (!valid_pid_combination) {
505                 LOG(ERROR) << "Sensor[" << name << "]: Invalid PID parameters combinations";
506                 sensors_parsed.clear();
507                 return sensors_parsed;
508             } else {
509                 support_pid = true;
510             }
511         }
512 
513         // Parse binded cooling device
514         bool support_hard_limit = false;
515         std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
516         values = sensors[i]["BindedCdevInfo"];
517         for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
518             Json::Value sub_values;
519             const std::string &cdev_name = values[j]["CdevRequest"].asString();
520             ThrottlingArray cdev_weight_for_pid;
521             cdev_weight_for_pid.fill(NAN);
522             CdevArray cdev_ceiling;
523             cdev_ceiling.fill(std::numeric_limits<int>::max());
524             if (support_pid) {
525                 if (!values[j]["CdevWeightForPID"].empty()) {
526                     LOG(INFO) << "Sensor[" << name << "]: Star to parse " << cdev_name
527                               << "'s CdevWeightForPID";
528                     if (!getFloatFromJsonValues(values[j]["CdevWeightForPID"], &cdev_weight_for_pid,
529                                                 false, false)) {
530                         LOG(ERROR) << "Failed to parse CdevWeightForPID";
531                         sensors_parsed.clear();
532                         return sensors_parsed;
533                     }
534                 }
535                 if (!values[j]["CdevCeiling"].empty()) {
536                     LOG(INFO) << "Sensor[" << name
537                               << "]: Start to parse CdevCeiling: " << cdev_name;
538                     if (!getIntFromJsonValues(values[j]["CdevCeiling"], &cdev_ceiling, false,
539                                               false)) {
540                         LOG(ERROR) << "Failed to parse CdevCeiling";
541                         sensors_parsed.clear();
542                         return sensors_parsed;
543                     }
544                 }
545             }
546             CdevArray limit_info;
547             limit_info.fill(0);
548             ThrottlingArray power_thresholds;
549             power_thresholds.fill(NAN);
550 
551             ReleaseLogic release_logic = ReleaseLogic::NONE;
552 
553             sub_values = values[j]["LimitInfo"];
554             if (sub_values.size()) {
555                 LOG(INFO) << "Sensor[" << name << "]: Start to parse LimitInfo: " << cdev_name;
556                 if (!getIntFromJsonValues(sub_values, &limit_info, false, false)) {
557                     LOG(ERROR) << "Failed to parse LimitInfo";
558                     sensors_parsed.clear();
559                     return sensors_parsed;
560                 }
561                 support_hard_limit = true;
562             }
563 
564             // Parse linked power info
565             bool is_power_data_invalid = false;
566             std::string power_rail;
567             bool high_power_check = false;
568             bool throttling_with_power_link = false;
569             CdevArray cdev_floor_with_power_link;
570             cdev_floor_with_power_link.fill(0);
571 
572             const bool power_link_disabled =
573                     android::base::GetBoolProperty(kPowerLinkDisabledProperty.data(), false);
574             if (!power_link_disabled) {
575                 power_rail = values[j]["BindedPowerRail"].asString();
576 
577                 if (values[j]["HighPowerCheck"].asBool()) {
578                     high_power_check = true;
579                 }
580                 LOG(INFO) << "Highpowercheck: " << std::boolalpha << high_power_check;
581 
582                 if (values[j]["ThrottlingWithPowerLink"].asBool()) {
583                     throttling_with_power_link = true;
584                 }
585                 LOG(INFO) << "ThrottlingwithPowerLink: " << std::boolalpha
586                           << throttling_with_power_link;
587 
588                 sub_values = values[j]["CdevFloorWithPowerLink"];
589                 if (sub_values.size()) {
590                     LOG(INFO) << "Sensor[" << name << "]: Start to parse " << cdev_name
591                               << "'s CdevFloorWithPowerLink";
592                     if (!getIntFromJsonValues(sub_values, &cdev_floor_with_power_link, false,
593                                               false)) {
594                         LOG(ERROR) << "Failed to parse CdevFloor";
595                         is_power_data_invalid = true;
596                     }
597                 }
598                 sub_values = values[j]["PowerThreshold"];
599                 if (sub_values.size()) {
600                     LOG(INFO) << "Sensor[" << name << "]: Start to parse " << cdev_name
601                               << "'s PowerThreshold";
602                     if (!getFloatFromJsonValues(sub_values, &power_thresholds, false, false)) {
603                         LOG(ERROR) << "Failed to parse power thresholds";
604                         is_power_data_invalid = true;
605                     }
606 
607                     if (values[j]["ReleaseLogic"].asString() == "INCREASE") {
608                         release_logic = ReleaseLogic::INCREASE;
609                         LOG(INFO) << "Release logic: INCREASE";
610                     } else if (values[j]["ReleaseLogic"].asString() == "DECREASE") {
611                         release_logic = ReleaseLogic::DECREASE;
612                         LOG(INFO) << "Release logic: DECREASE";
613                     } else if (values[j]["ReleaseLogic"].asString() == "STEPWISE") {
614                         release_logic = ReleaseLogic::STEPWISE;
615                         LOG(INFO) << "Release logic: STEPWISE";
616                     } else if (values[j]["ReleaseLogic"].asString() == "RELEASE_TO_FLOOR") {
617                         release_logic = ReleaseLogic::RELEASE_TO_FLOOR;
618                         LOG(INFO) << "Release logic: RELEASE_TO_FLOOR";
619                     } else {
620                         LOG(ERROR) << "Release logic is invalid";
621                         is_power_data_invalid = true;
622                     }
623 
624                     if (is_power_data_invalid) {
625                         LOG(ERROR) << cdev_name << "'s power rail " << power_rail << " is invalid";
626                         sensors_parsed.clear();
627                         return sensors_parsed;
628                     }
629                 }
630             }
631 
632             binded_cdev_info_map[cdev_name] = {
633                     .limit_info = limit_info,
634                     .power_thresholds = power_thresholds,
635                     .release_logic = release_logic,
636                     .high_power_check = high_power_check,
637                     .throttling_with_power_link = throttling_with_power_link,
638                     .cdev_weight_for_pid = cdev_weight_for_pid,
639                     .cdev_ceiling = cdev_ceiling,
640                     .cdev_floor_with_power_link = cdev_floor_with_power_link,
641                     .power_rail = power_rail,
642             };
643         }
644 
645         bool is_monitor = (send_cb | send_powerhint | support_pid | support_hard_limit);
646         LOG(INFO) << "Sensor[" << name << "]'s Monitor: " << std::boolalpha << is_monitor;
647 
648         std::unique_ptr<VirtualSensorInfo> virtual_sensor_info;
649         if (is_virtual_sensor) {
650             virtual_sensor_info.reset(new VirtualSensorInfo{linked_sensors, coefficients, offset,
651                                                             trigger_sensor, formula});
652         }
653 
654         std::unique_ptr<ThrottlingInfo> throttling_info(
655                 new ThrottlingInfo{k_po, k_pu, k_i, k_d, i_max, max_alloc_power, min_alloc_power,
656                                    s_power, i_cutoff, binded_cdev_info_map});
657 
658         sensors_parsed[name] = {
659                 .type = sensor_type,
660                 .hot_thresholds = hot_thresholds,
661                 .cold_thresholds = cold_thresholds,
662                 .hot_hysteresis = hot_hysteresis,
663                 .cold_hysteresis = cold_hysteresis,
664                 .temp_path = temp_path,
665                 .vr_threshold = vr_threshold,
666                 .multiplier = multiplier,
667                 .polling_delay = polling_delay,
668                 .passive_delay = passive_delay,
669                 .send_cb = send_cb,
670                 .send_powerhint = send_powerhint,
671                 .is_monitor = is_monitor,
672                 .virtual_sensor_info = std::move(virtual_sensor_info),
673                 .throttling_info = std::move(throttling_info),
674         };
675 
676         ++total_parsed;
677     }
678 
679     LOG(INFO) << total_parsed << " Sensors parsed successfully";
680     return sensors_parsed;
681 }
682 
ParseCoolingDevice(std::string_view config_path)683 std::unordered_map<std::string, CdevInfo> ParseCoolingDevice(std::string_view config_path) {
684     std::string json_doc;
685     std::unordered_map<std::string, CdevInfo> cooling_devices_parsed;
686     if (!android::base::ReadFileToString(config_path.data(), &json_doc)) {
687         LOG(ERROR) << "Failed to read JSON config from " << config_path;
688         return cooling_devices_parsed;
689     }
690 
691     Json::Value root;
692     Json::CharReaderBuilder builder;
693     std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
694     std::string errorMessage;
695 
696     if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), &root, &errorMessage)) {
697         LOG(ERROR) << "Failed to parse JSON config";
698         return cooling_devices_parsed;
699     }
700 
701     Json::Value cooling_devices = root["CoolingDevices"];
702     std::size_t total_parsed = 0;
703     std::unordered_set<std::string> cooling_devices_name_parsed;
704 
705     for (Json::Value::ArrayIndex i = 0; i < cooling_devices.size(); ++i) {
706         const std::string &name = cooling_devices[i]["Name"].asString();
707         LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name;
708         if (name.empty()) {
709             LOG(ERROR) << "Failed to read "
710                        << "CoolingDevice[" << i << "]'s Name";
711             cooling_devices_parsed.clear();
712             return cooling_devices_parsed;
713         }
714 
715         auto result = cooling_devices_name_parsed.insert(name.data());
716         if (!result.second) {
717             LOG(ERROR) << "Duplicate CoolingDevice[" << i << "]'s Name";
718             cooling_devices_parsed.clear();
719             return cooling_devices_parsed;
720         }
721 
722         std::string cooling_device_type_str = cooling_devices[i]["Type"].asString();
723         LOG(INFO) << "CoolingDevice[" << name << "]'s Type: " << cooling_device_type_str;
724         CoolingType cooling_device_type;
725 
726         if (!getTypeFromString(cooling_device_type_str, &cooling_device_type)) {
727             LOG(ERROR) << "Invalid "
728                        << "CoolingDevice[" << name << "]'s Type: " << cooling_device_type_str;
729             cooling_devices_parsed.clear();
730             return cooling_devices_parsed;
731         }
732 
733         const std::string &read_path = cooling_devices[i]["ReadPath"].asString();
734         LOG(INFO) << "Cdev Read Path: " << (read_path.empty() ? "default" : read_path);
735 
736         const std::string &write_path = cooling_devices[i]["WritePath"].asString();
737         LOG(INFO) << "Cdev Write Path: " << (write_path.empty() ? "default" : write_path);
738 
739         std::vector<float> state2power;
740         Json::Value values = cooling_devices[i]["State2Power"];
741         if (values.size()) {
742             state2power.reserve(values.size());
743             for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
744                 state2power.emplace_back(getFloatFromValue(values[j]));
745                 LOG(INFO) << "Cooling device[" << name << "]'s Power2State[" << j
746                           << "]: " << state2power[j];
747             }
748         } else {
749             LOG(INFO) << "CoolingDevice[" << i << "]'s Name: " << name
750                       << " does not support Power2State";
751         }
752 
753         const std::string &power_rail = cooling_devices[i]["PowerRail"].asString();
754         LOG(INFO) << "Cooling device power rail : " << power_rail;
755 
756         cooling_devices_parsed[name] = {
757                 .type = cooling_device_type,
758                 .read_path = read_path,
759                 .write_path = write_path,
760                 .state2power = state2power,
761         };
762         ++total_parsed;
763     }
764 
765     LOG(INFO) << total_parsed << " CoolingDevices parsed successfully";
766     return cooling_devices_parsed;
767 }
768 
ParsePowerRailInfo(std::string_view config_path)769 std::unordered_map<std::string, PowerRailInfo> ParsePowerRailInfo(std::string_view config_path) {
770     std::string json_doc;
771     std::unordered_map<std::string, PowerRailInfo> power_rails_parsed;
772     if (!android::base::ReadFileToString(config_path.data(), &json_doc)) {
773         LOG(ERROR) << "Failed to read JSON config from " << config_path;
774         return power_rails_parsed;
775     }
776 
777     Json::Value root;
778     Json::CharReaderBuilder builder;
779     std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
780     std::string errorMessage;
781 
782     if (!reader->parse(&*json_doc.begin(), &*json_doc.end(), &root, &errorMessage)) {
783         LOG(ERROR) << "Failed to parse JSON config";
784         return power_rails_parsed;
785     }
786 
787     Json::Value power_rails = root["PowerRails"];
788     std::size_t total_parsed = 0;
789     std::unordered_set<std::string> power_rails_name_parsed;
790 
791     for (Json::Value::ArrayIndex i = 0; i < power_rails.size(); ++i) {
792         const std::string &name = power_rails[i]["Name"].asString();
793         LOG(INFO) << "PowerRail[" << i << "]'s Name: " << name;
794         if (name.empty()) {
795             LOG(ERROR) << "Failed to read "
796                        << "PowerRail[" << i << "]'s Name";
797             power_rails_parsed.clear();
798             return power_rails_parsed;
799         }
800 
801         std::string rail;
802         if (power_rails[i]["Rail"].empty()) {
803             rail = name;
804         } else {
805             rail = power_rails[i]["Rail"].asString();
806         }
807         LOG(INFO) << "PowerRail[" << i << "]'s Rail: " << rail;
808 
809         std::vector<std::string> linked_power_rails;
810         std::vector<float> coefficients;
811         float offset = 0;
812         FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
813         bool is_virtual_power_rail = false;
814         Json::Value values;
815         int power_sample_count = 0;
816         std::chrono::milliseconds power_sample_delay;
817 
818         if (!power_rails[i]["VirtualRails"].empty() && power_rails[i]["VirtualRails"].isBool()) {
819             is_virtual_power_rail = power_rails[i]["VirtualRails"].asBool();
820             LOG(INFO) << "PowerRails[" << name << "]'s VirtualRail, set to 'true'";
821         }
822 
823         if (is_virtual_power_rail) {
824             values = power_rails[i]["Combination"];
825             if (values.size()) {
826                 linked_power_rails.reserve(values.size());
827                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
828                     linked_power_rails.emplace_back(values[j].asString());
829                     LOG(INFO) << "PowerRail[" << name << "]'s combination[" << j
830                               << "]: " << linked_power_rails[j];
831                 }
832             } else {
833                 power_rails_parsed.clear();
834                 return power_rails_parsed;
835             }
836 
837             values = power_rails[i]["Coefficient"];
838             if (values.size()) {
839                 coefficients.reserve(values.size());
840                 for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
841                     coefficients.emplace_back(getFloatFromValue(values[j]));
842                     LOG(INFO) << "PowerRail[" << name << "]'s coefficient[" << j
843                               << "]: " << coefficients[j];
844                 }
845             } else {
846                 power_rails_parsed.clear();
847                 return power_rails_parsed;
848             }
849 
850             if (!power_rails[i]["Offset"].empty()) {
851                 offset = power_rails[i]["Offset"].asFloat();
852             }
853 
854             if (linked_power_rails.size() != coefficients.size()) {
855                 power_rails_parsed.clear();
856                 return power_rails_parsed;
857             }
858 
859             if (power_rails[i]["Formula"].asString().compare("COUNT_THRESHOLD") == 0) {
860                 formula = FormulaOption::COUNT_THRESHOLD;
861             } else if (power_rails[i]["Formula"].asString().compare("WEIGHTED_AVG") == 0) {
862                 formula = FormulaOption::WEIGHTED_AVG;
863             } else if (power_rails[i]["Formula"].asString().compare("MAXIMUM") == 0) {
864                 formula = FormulaOption::MAXIMUM;
865             } else if (power_rails[i]["Formula"].asString().compare("MINIMUM") == 0) {
866                 formula = FormulaOption::MINIMUM;
867             } else {
868                 power_rails_parsed.clear();
869                 return power_rails_parsed;
870             }
871         }
872 
873         std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
874         if (is_virtual_power_rail) {
875             virtual_power_rail_info.reset(
876                     new VirtualPowerRailInfo{linked_power_rails, coefficients, offset, formula});
877         }
878 
879         power_sample_count = power_rails[i]["PowerSampleCount"].asInt();
880         LOG(INFO) << "Power sample Count: " << power_sample_count;
881 
882         if (!power_rails[i]["PowerSampleDelay"]) {
883             power_sample_delay = std::chrono::milliseconds::max();
884         } else {
885             power_sample_delay =
886                     std::chrono::milliseconds(getIntFromValue(power_rails[i]["PowerSampleDelay"]));
887         }
888 
889         power_rails_parsed[name] = {
890                 .rail = rail,
891                 .power_sample_count = power_sample_count,
892                 .power_sample_delay = power_sample_delay,
893                 .virtual_power_rail_info = std::move(virtual_power_rail_info),
894         };
895         ++total_parsed;
896     }
897 
898     LOG(INFO) << total_parsed << " PowerRails parsed successfully";
899     return power_rails_parsed;
900 }
901 
902 }  // namespace implementation
903 }  // namespace V2_0
904 }  // namespace thermal
905 }  // namespace hardware
906 }  // namespace android
907