1 /*
2  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * *    * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above
10  *       copyright notice, this list of conditions and the following
11  *       disclaimer in the documentation and/or other materials provided
12  *       with the distribution.
13  *     * Neither the name of The Linux Foundation nor the names of its
14  *       contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #pragma once
31 
32 #include <array>
33 #include <chrono>
34 #include <mutex>
35 #include <shared_mutex>
36 #include <string>
37 #include <string_view>
38 #include <thread>
39 #include <unordered_map>
40 #include <vector>
41 
42 #include <aidl/android/hardware/power/IPower.h>
43 #include <aidl/google/hardware/power/extension/pixel/IPowerExt.h>
44 #include <android/hardware/thermal/2.0/IThermal.h>
45 
46 #include "utils/config_parser.h"
47 #include "utils/power_files.h"
48 #include "utils/thermal_files.h"
49 #include "utils/thermal_watcher.h"
50 
51 namespace android {
52 namespace hardware {
53 namespace thermal {
54 namespace V2_0 {
55 namespace implementation {
56 
57 using ::aidl::android::hardware::power::IPower;
58 using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
59 using ::android::hardware::hidl_vec;
60 using ::android::hardware::thermal::V1_0::CpuUsage;
61 using ::android::hardware::thermal::V2_0::CoolingType;
62 using ::android::hardware::thermal::V2_0::IThermal;
63 using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice;
64 using CoolingDevice_2_0 = ::android::hardware::thermal::V2_0::CoolingDevice;
65 using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature;
66 using Temperature_2_0 = ::android::hardware::thermal::V2_0::Temperature;
67 using TemperatureType_1_0 = ::android::hardware::thermal::V1_0::TemperatureType;
68 using TemperatureType_2_0 = ::android::hardware::thermal::V2_0::TemperatureType;
69 using ::android::hardware::thermal::V2_0::TemperatureThreshold;
70 using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
71 
72 using NotificationCallback = std::function<void(const Temperature_2_0 &t)>;
73 using NotificationTime = std::chrono::time_point<std::chrono::steady_clock>;
74 using CdevRequestStatus = std::unordered_map<std::string, int>;
75 
76 // Get thermal_zone type
77 bool getThermalZoneTypeById(int tz_id, std::string *);
78 
79 struct SensorStatus {
80     ThrottlingSeverity severity;
81     ThrottlingSeverity prev_hot_severity;
82     ThrottlingSeverity prev_cold_severity;
83     ThrottlingSeverity prev_hint_severity;
84     boot_clock::time_point last_update_time;
85     std::unordered_map<std::string, int> pid_request_map;
86     std::unordered_map<std::string, int> hard_limit_request_map;
87     float err_integral;
88     float prev_err;
89 };
90 
91 class PowerHalService {
92   public:
93     PowerHalService();
94     ~PowerHalService() = default;
95     bool connect();
isAidlPowerHalExist()96     bool isAidlPowerHalExist() { return power_hal_aidl_exist_; }
97     bool isModeSupported(const std::string &type, const ThrottlingSeverity &t);
isPowerHalConnected()98     bool isPowerHalConnected() { return power_hal_aidl_ != nullptr; }
isPowerHalExtConnected()99     bool isPowerHalExtConnected() { return power_hal_ext_aidl_ != nullptr; }
100     void setMode(const std::string &type, const ThrottlingSeverity &t, const bool &enable);
101 
102   private:
103     bool power_hal_aidl_exist_;
104     std::shared_ptr<IPower> power_hal_aidl_;
105     std::shared_ptr<IPowerExt> power_hal_ext_aidl_;
106     std::mutex lock_;
107 };
108 
109 class ThermalHelper {
110   public:
111     explicit ThermalHelper(const NotificationCallback &cb);
112     ~ThermalHelper() = default;
113 
114     bool fillTemperatures(hidl_vec<Temperature_1_0> *temperatures) const;
115     bool fillCurrentTemperatures(bool filterType, bool filterCallback, TemperatureType_2_0 type,
116                                  hidl_vec<Temperature_2_0> *temperatures) const;
117     bool fillTemperatureThresholds(bool filterType, TemperatureType_2_0 type,
118                                    hidl_vec<TemperatureThreshold> *thresholds) const;
119     bool fillCurrentCoolingDevices(bool filterType, CoolingType type,
120                                    hidl_vec<CoolingDevice_2_0> *coolingdevices) const;
121     bool fillCpuUsages(hidl_vec<CpuUsage> *cpu_usages) const;
122 
123     // Dissallow copy and assign.
124     ThermalHelper(const ThermalHelper &) = delete;
125     void operator=(const ThermalHelper &) = delete;
126 
isInitializedOk()127     bool isInitializedOk() const { return is_initialized_; }
128 
129     // Read the temperature of a single sensor.
130     bool readTemperature(std::string_view sensor_name, Temperature_1_0 *out,
131                          bool is_virtual_sensor = false) const;
132     bool readTemperature(
133             std::string_view sensor_name, Temperature_2_0 *out,
134             std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status = nullptr,
135             bool is_virtual_sensor = false) const;
136     bool readTemperatureThreshold(std::string_view sensor_name, TemperatureThreshold *out) const;
137     // Read the value of a single cooling device.
138     bool readCoolingDevice(std::string_view cooling_device, CoolingDevice_2_0 *out) const;
139     // Get SensorInfo Map
GetSensorInfoMap()140     const std::unordered_map<std::string, SensorInfo> &GetSensorInfoMap() const {
141         return sensor_info_map_;
142     }
143     // Get CdevInfo Map
GetCdevInfoMap()144     const std::unordered_map<std::string, CdevInfo> &GetCdevInfoMap() const {
145         return cooling_device_info_map_;
146     }
147     // Get PowerRailInfo Map
GetPowerRailInfoMap()148     const std::unordered_map<std::string, PowerRailInfo> &GetPowerRailInfoMap() const {
149         return power_rail_info_map_;
150     }
151     // Get SensorStatus Map
GetSensorStatusMap()152     const std::unordered_map<std::string, SensorStatus> &GetSensorStatusMap() const {
153         std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
154         return sensor_status_map_;
155     }
156     // Get CdevStatus Map
GetCdevStatusMap()157     const std::unordered_map<std::string, CdevRequestStatus> &GetCdevStatusMap() const {
158         std::shared_lock<std::shared_mutex> _lock(cdev_status_map_mutex_);
159         return cdev_status_map_;
160     }
161     // Get ThrottlingRelease Map
GetThrottlingReleaseMap()162     const std::unordered_map<std::string, CdevReleaseStatus> &GetThrottlingReleaseMap() const {
163         return power_files_.GetThrottlingReleaseMap();
164     }
165 
166     // Get PowerStatus Map
GetPowerStatusMap()167     const std::unordered_map<std::string, PowerStatusMap> &GetPowerStatusMap() const {
168         return power_files_.GetPowerStatusMap();
169     }
170 
171     void sendPowerExtHint(const Temperature_2_0 &t);
isAidlPowerHalExist()172     bool isAidlPowerHalExist() { return power_hal_service_.isAidlPowerHalExist(); }
isPowerHalConnected()173     bool isPowerHalConnected() { return power_hal_service_.isPowerHalConnected(); }
isPowerHalExtConnected()174     bool isPowerHalExtConnected() { return power_hal_service_.isPowerHalExtConnected(); }
175 
176   private:
177     bool initializeSensorMap(const std::unordered_map<std::string, std::string> &path_map);
178     bool initializeCoolingDevices(const std::unordered_map<std::string, std::string> &path_map);
179     void setMinTimeout(SensorInfo *sensor_info);
180     void initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
181                         std::set<std::string> *monitored_sensors, bool thermal_genl_enabled);
182 
183     // For thermal_watcher_'s polling thread, return the sleep interval
184     std::chrono::milliseconds thermalWatcherCallbackFunc(
185             const std::set<std::string> &uevent_sensors);
186     // Return hot and cold severity status as std::pair
187     std::pair<ThrottlingSeverity, ThrottlingSeverity> getSeverityFromThresholds(
188         const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
189         const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
190         ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
191         float value) const;
192     bool checkVirtualSensor(std::string_view sensor_name, std::string *temp) const;
193 
194     // Return the target state of PID algorithm
195     size_t getTargetStateOfPID(const SensorInfo &sensor_info, const SensorStatus &sensor_status);
196     // Return the power budget which is computed by PID algorithm
197     float pidPowerCalculator(const Temperature_2_0 &temp, const SensorInfo &sensor_info,
198                              SensorStatus *sensor_status,
199                              const std::chrono::milliseconds time_elapsed_ms, size_t target_state);
200     bool connectToPowerHal();
201     void updateSupportedPowerHints();
202     bool requestCdevByPower(std::string_view sensor_name, SensorStatus *sensor_status,
203                             const SensorInfo &sensor_info, float total_power_budget,
204                             size_t target_state);
205     void requestCdevBySeverity(std::string_view sensor_name, SensorStatus *sensor_status,
206                                const SensorInfo &sensor_info);
207     void computeCoolingDevicesRequest(std::string_view sensor_name, const SensorInfo &sensor_info,
208                                       const SensorStatus &sensor_status,
209                                       std::vector<std::string> *cooling_devices_to_update);
210     void updateCoolingDevices(const std::vector<std::string> &cooling_devices_to_update);
211     sp<ThermalWatcher> thermal_watcher_;
212     PowerFiles power_files_;
213     ThermalFiles thermal_sensors_;
214     ThermalFiles cooling_devices_;
215     bool is_initialized_;
216     const NotificationCallback cb_;
217     std::unordered_map<std::string, CdevInfo> cooling_device_info_map_;
218     std::unordered_map<std::string, SensorInfo> sensor_info_map_;
219     std::unordered_map<std::string, PowerRailInfo> power_rail_info_map_;
220     std::unordered_map<std::string, std::map<ThrottlingSeverity, ThrottlingSeverity>>
221             supported_powerhint_map_;
222     PowerHalService power_hal_service_;
223 
224     mutable std::shared_mutex sensor_status_map_mutex_;
225     std::unordered_map<std::string, SensorStatus> sensor_status_map_;
226     mutable std::shared_mutex cdev_status_map_mutex_;
227     std::unordered_map<std::string, CdevRequestStatus> cdev_status_map_;
228 };
229 
230 }  // namespace implementation
231 }  // namespace V2_0
232 }  // namespace thermal
233 }  // namespace hardware
234 }  // namespace android
235