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 
17 #pragma once
18 
19 #include <aidl/android/hardware/thermal/CoolingType.h>
20 #include <aidl/android/hardware/thermal/TemperatureType.h>
21 #include <aidl/android/hardware/thermal/ThrottlingSeverity.h>
22 #include <json/value.h>
23 
24 #include <chrono>
25 #include <string>
26 #include <unordered_map>
27 #include <unordered_set>
28 #include <variant>
29 
30 #include "virtualtemp_estimator/virtualtemp_estimator.h"
31 
32 namespace aidl {
33 namespace android {
34 namespace hardware {
35 namespace thermal {
36 namespace implementation {
37 
38 constexpr size_t kThrottlingSeverityCount =
39         std::distance(::ndk::enum_range<ThrottlingSeverity>().begin(),
40                       ::ndk::enum_range<ThrottlingSeverity>().end());
41 using ThrottlingArray = std::array<float, static_cast<size_t>(kThrottlingSeverityCount)>;
42 using CdevArray = std::array<int, static_cast<size_t>(kThrottlingSeverityCount)>;
43 constexpr std::chrono::milliseconds kMinPollIntervalMs = std::chrono::milliseconds(2000);
44 constexpr std::chrono::milliseconds kUeventPollTimeoutMs = std::chrono::milliseconds(300000);
45 // TODO(b/292044404): Add debug config to make them easily configurable
46 constexpr std::chrono::milliseconds kPowerLogIntervalMs = std::chrono::milliseconds(60000);
47 constexpr int kMaxPowerLogPerLine = 6;
48 // Max number of time_in_state buckets is 20 in atoms
49 // VendorSensorCoolingDeviceStats, VendorTempResidencyStats
50 constexpr int kMaxStatsResidencyCount = 20;
51 constexpr int kMaxStatsThresholdCount = kMaxStatsResidencyCount - 1;
52 
53 enum class FormulaOption : uint32_t {
54     COUNT_THRESHOLD = 0,
55     WEIGHTED_AVG,
56     MAXIMUM,
57     MINIMUM,
58     USE_ML_MODEL,
59     USE_LINEAR_MODEL,
60     PREVIOUSLY_PREDICTED
61 };
62 
63 template <typename T>
64 struct ThresholdList {
65     std::optional<std::string> logging_name;
66     std::vector<T> thresholds;
ThresholdListThresholdList67     explicit ThresholdList(std::optional<std::string> logging_name, std::vector<T> thresholds)
68         : logging_name(logging_name), thresholds(thresholds) {}
69 
70     ThresholdList() = default;
71     ThresholdList(const ThresholdList &) = default;
72     ThresholdList &operator=(const ThresholdList &) = default;
73     ThresholdList(ThresholdList &&) = default;
74     ThresholdList &operator=(ThresholdList &&) = default;
75     ~ThresholdList() = default;
76 };
77 
78 template <typename T>
79 struct StatsInfo {
80     // if bool, record all or none depending on flag
81     // if set, check name present in set
82     std::variant<bool, std::unordered_set<std::string> >
83             record_by_default_threshold_all_or_name_set_;
84     // map name to list of thresholds
85     std::unordered_map<std::string, std::vector<ThresholdList<T> > > record_by_threshold;
clearStatsInfo86     void clear() {
87         record_by_default_threshold_all_or_name_set_ = false;
88         record_by_threshold.clear();
89     }
90 };
91 
92 struct StatsConfig {
93     StatsInfo<float> sensor_stats_info;
94     StatsInfo<int> cooling_device_request_info;
clearStatsConfig95     void clear() {
96         sensor_stats_info.clear();
97         cooling_device_request_info.clear();
98     }
99 };
100 
101 struct TempRangeInfo {
102     int max_temp_threshold;
103     int min_temp_threshold;
104 };
105 
106 struct TempStuckInfo {
107     int min_polling_count;
108     std::chrono::milliseconds min_stuck_duration;
109 };
110 
111 struct AbnormalStatsInfo {
112     struct SensorsTempRangeInfo {
113         std::vector<std::string> sensors;
114         TempRangeInfo temp_range_info;
115     };
116     struct SensorsTempStuckInfo {
117         std::vector<std::string> sensors;
118         TempStuckInfo temp_stuck_info;
119     };
120 
121     std::optional<TempRangeInfo> default_temp_range_info;
122     std::vector<SensorsTempRangeInfo> sensors_temp_range_infos;
123     std::optional<TempStuckInfo> default_temp_stuck_info;
124     std::vector<SensorsTempStuckInfo> sensors_temp_stuck_infos;
125 };
126 
127 enum class SensorFusionType : uint32_t {
128     SENSOR = 0,
129     ODPM,
130     CONSTANT,
131     CDEV,
132 };
133 
134 enum class SensorReadStatus : uint32_t {
135     OKAY = 0,
136     UNDER_COLLECTING,
137     ERROR,
138 };
139 
140 std::ostream &operator<<(std::ostream &os, const SensorFusionType &sensor_fusion_type);
141 
142 struct VirtualSensorInfo {
143     std::vector<std::string> linked_sensors;
144     std::vector<SensorFusionType> linked_sensors_type;
145     std::vector<std::string> coefficients;
146     std::vector<SensorFusionType> coefficients_type;
147 
148     float offset;
149     std::vector<std::string> trigger_sensors;
150     FormulaOption formula;
151     std::string vt_estimator_model_file;
152     std::unique_ptr<::thermal::vtestimator::VirtualTempEstimator> vt_estimator;
153     std::string backup_sensor;
154 };
155 
156 struct PredictorInfo {
157     std::string sensor;
158     bool support_pid_compensation;
159     std::vector<float> prediction_weights;
160     ThrottlingArray k_p_compensate;
161 
162     bool supports_predictions;       // Does this sensor support predictions
163     int prediction_sample_interval;  // Interval between each predicted sample
164     int num_prediction_samples;      // How many samples are predicted for each iteration
165     int prediction_duration;         // Prediction duration for a PREDICTED sensor
166 };
167 
168 struct VirtualPowerRailInfo {
169     std::vector<std::string> linked_power_rails;
170     std::vector<float> coefficients;
171     float offset;
172     FormulaOption formula;
173 };
174 
175 // The method when the ODPM power is lower than threshold
176 enum class ReleaseLogic : uint32_t {
177     INCREASE = 0,      // Increase throttling by step
178     DECREASE,          // Decrease throttling by step
179     STEPWISE,          // Support both increase and decrease logix
180     RELEASE_TO_FLOOR,  // Release throttling to floor directly
181     NONE,
182 };
183 
184 struct BindedCdevInfo {
185     CdevArray limit_info;
186     ThrottlingArray power_thresholds;
187     ReleaseLogic release_logic;
188     ThrottlingArray cdev_weight_for_pid;
189     CdevArray cdev_ceiling;
190     int max_release_step;
191     int max_throttle_step;
192     CdevArray cdev_floor_with_power_link;
193     std::string power_rail;
194     // The flag for activate release logic when power is higher than power threshold
195     bool high_power_check;
196     // The flag for only triggering throttling until all power samples are collected
197     bool throttling_with_power_link;
198     bool enabled;
199 };
200 
201 // The map to store the CDEV throttling info for each profile
202 using ProfileMap = std::unordered_map<std::string, std::unordered_map<std::string, BindedCdevInfo>>;
203 
204 struct ThrottlingInfo {
205     ThrottlingArray k_po;
206     ThrottlingArray k_pu;
207     ThrottlingArray k_io;
208     ThrottlingArray k_iu;
209     ThrottlingArray k_d;
210     ThrottlingArray i_max;
211     ThrottlingArray max_alloc_power;
212     ThrottlingArray min_alloc_power;
213     ThrottlingArray s_power;
214     ThrottlingArray i_cutoff;
215     float i_default;
216     float i_default_pct;
217     int tran_cycle;
218     std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
219     std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
220     ProfileMap profile_map;
221 };
222 
223 struct SensorInfo {
224     TemperatureType type;
225     ThrottlingArray hot_thresholds;
226     ThrottlingArray cold_thresholds;
227     ThrottlingArray hot_hysteresis;
228     ThrottlingArray cold_hysteresis;
229     std::string temp_path;
230     std::string severity_reference;
231     float vr_threshold;
232     float multiplier;
233     std::chrono::milliseconds polling_delay;
234     std::chrono::milliseconds passive_delay;
235     std::chrono::milliseconds time_resolution;
236     // The StepRatio value which is used for smoothing transient w/ the equation:
237     // Temp = CurrentTemp * StepRatio + LastTemp * (1 - StepRatio)
238     float step_ratio;
239     bool send_cb;
240     bool send_powerhint;
241     bool is_watch;
242     bool is_hidden;
243     ThrottlingSeverity log_level;
244     std::unique_ptr<VirtualSensorInfo> virtual_sensor_info;
245     std::shared_ptr<ThrottlingInfo> throttling_info;
246     std::unique_ptr<PredictorInfo> predictor_info;
247 };
248 
249 struct CdevInfo {
250     CoolingType type;
251     std::string read_path;
252     std::string write_path;
253     std::vector<float> state2power;
254     int max_state;
255 };
256 
257 struct PowerRailInfo {
258     int power_sample_count;
259     std::chrono::milliseconds power_sample_delay;
260     std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
261 };
262 
263 bool LoadThermalConfig(std::string_view config_path, Json::Value *config);
264 bool ParseThermalConfig(std::string_view config_path, Json::Value *config,
265                         std::unordered_set<std::string> *loaded_config_paths);
266 void MergeConfigEntries(Json::Value *config, Json::Value *sub_config, std::string_view member_name);
267 bool ParseSensorInfo(const Json::Value &config,
268                      std::unordered_map<std::string, SensorInfo> *sensors_parsed);
269 bool ParseCoolingDevice(const Json::Value &config,
270                         std::unordered_map<std::string, CdevInfo> *cooling_device_parsed);
271 bool ParsePowerRailInfo(const Json::Value &config,
272                         std::unordered_map<std::string, PowerRailInfo> *power_rail_parsed);
273 bool ParseSensorStatsConfig(const Json::Value &config,
274                             const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
275                             StatsInfo<float> *sensor_stats_info_parsed,
276                             AbnormalStatsInfo *abnormal_stats_info_parsed);
277 bool ParseCoolingDeviceStatsConfig(
278         const Json::Value &config,
279         const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_,
280         StatsInfo<int> *cooling_device_request_info_parsed);
281 }  // namespace implementation
282 }  // namespace thermal
283 }  // namespace hardware
284 }  // namespace android
285 }  // namespace aidl
286