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/frameworks/stats/IStats.h> 20 #include <aidl/android/hardware/thermal/Temperature.h> 21 #include <android-base/chrono_utils.h> 22 #include <hardware/google/pixel/pixelstats/pixelatoms.pb.h> 23 24 #include <chrono> 25 #include <shared_mutex> 26 #include <string_view> 27 #include <unordered_map> 28 #include <vector> 29 30 #include "thermal_info.h" 31 32 namespace aidl { 33 namespace android { 34 namespace hardware { 35 namespace thermal { 36 namespace implementation { 37 38 class ThermalHelper; 39 40 using aidl::android::frameworks::stats::IStats; 41 using aidl::android::frameworks::stats::VendorAtomValue; 42 using ::android::base::boot_clock; 43 using ::android::hardware::google::pixel::PixelAtoms::ThermalSensorAbnormalityDetected; 44 using std::chrono::system_clock; 45 using SystemTimePoint = std::chrono::time_point<std::chrono::system_clock>; 46 47 // Number of abnormal atoms to be logged per kUpdateIntervalMs 48 constexpr int kMaxAbnormalLoggingPerUpdateInterval = 20; 49 constexpr int kMaxStatsReportingFailCount = 3; 50 // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so 51 // store everything in the values array at the index of the field number 52 // -2. 53 constexpr int kVendorAtomOffset = 2; 54 constexpr float kPrecisionThreshold = 1e-4; 55 56 struct StatsRecord { 57 int cur_state; /* temperature / cdev state at current time */ 58 boot_clock::time_point cur_state_start_time; 59 boot_clock::time_point last_stats_report_time = boot_clock::time_point::min(); 60 std::vector<std::chrono::milliseconds> time_in_state_ms; /* stats array */ 61 int report_fail_count = 0; /* Number of times failed to report stats */ 62 explicit StatsRecord(const size_t &time_in_state_size, int state = 0) cur_stateStatsRecord63 : cur_state(state), 64 cur_state_start_time(boot_clock::now()), 65 last_stats_report_time(boot_clock::now()), 66 report_fail_count(0) { 67 time_in_state_ms = std::vector<std::chrono::milliseconds>( 68 time_in_state_size, std::chrono::milliseconds::zero()); 69 } 70 StatsRecord() = default; 71 StatsRecord(const StatsRecord &) = default; 72 StatsRecord &operator=(const StatsRecord &) = default; 73 StatsRecord(StatsRecord &&) = default; 74 StatsRecord &operator=(StatsRecord &&) = default; 75 ~StatsRecord() = default; 76 }; 77 78 template <typename ValueType> 79 struct StatsByThreshold { 80 std::vector<ValueType> thresholds; 81 std::optional<std::string> logging_name; 82 StatsRecord stats_record; StatsByThresholdStatsByThreshold83 explicit StatsByThreshold(ThresholdList<ValueType> threshold_list) 84 : thresholds(threshold_list.thresholds), logging_name(threshold_list.logging_name) { 85 // number of states = number of thresholds + 1 86 // e.g. threshold: [30, 50, 60] 87 // buckets: [MIN - 30, 30 - 50, 50-60, 60-MAX] 88 int time_in_state_size = threshold_list.thresholds.size() + 1; 89 stats_record = StatsRecord(time_in_state_size); 90 } 91 StatsByThreshold() = default; 92 StatsByThreshold(const StatsByThreshold &) = default; 93 StatsByThreshold &operator=(const StatsByThreshold &) = default; 94 StatsByThreshold(StatsByThreshold &&) = default; 95 StatsByThreshold &operator=(StatsByThreshold &&) = default; 96 ~StatsByThreshold() = default; 97 }; 98 99 template <typename ValueType> 100 struct ThermalStats { 101 std::vector<StatsByThreshold<ValueType>> stats_by_custom_threshold; 102 std::optional<StatsRecord> stats_by_default_threshold; 103 }; 104 105 struct SensorTempStats : ThermalStats<float> { 106 float max_temp = std::numeric_limits<float>::min(); 107 SystemTimePoint max_temp_timestamp = SystemTimePoint::min(); 108 float min_temp = std::numeric_limits<float>::max(); 109 SystemTimePoint min_temp_timestamp = SystemTimePoint::min(); 110 }; 111 112 struct CurrTempStatus { 113 float temp; 114 boot_clock::time_point start_time; 115 int repeat_count; 116 }; 117 118 struct SensorStats { 119 // Temperature residency stats for each sensor being watched 120 std::unordered_map<std::string, SensorTempStats> temp_stats_map_; 121 // Min, Max Temp threshold info for each sensor being monitored 122 std::unordered_map<std::string, std::shared_ptr<TempRangeInfo>> temp_range_info_map_; 123 // Temperature Stuck info for each sensor being monitored 124 std::unordered_map<std::string, std::shared_ptr<TempStuckInfo>> temp_stuck_info_map_; 125 // Current temperature status for each sensor being monitored for stuck 126 std::unordered_map<std::string, CurrTempStatus> curr_temp_status_map_; 127 }; 128 129 class ThermalStatsHelper { 130 public: 131 ThermalStatsHelper() = default; 132 ~ThermalStatsHelper() = default; 133 // Disallow copy and assign 134 ThermalStatsHelper(const ThermalStatsHelper &) = delete; 135 void operator=(const ThermalStatsHelper &) = delete; 136 137 bool initializeStats(const Json::Value &config, 138 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_, 139 const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_, 140 ThermalHelper *const thermal_helper_handle); 141 void updateSensorCdevRequestStats(std::string_view trigger_sensor, std::string_view cdev, 142 int new_state); 143 void updateSensorTempStatsBySeverity(std::string_view sensor, 144 const ThrottlingSeverity &severity); 145 void updateSensorTempStatsByThreshold(std::string_view sensor, float temperature); 146 /* 147 * Function to report all the stats by calling all specific stats reporting function. 148 * Returns: 149 * 0, if time_elapsed < kUpdateIntervalMs or if no failure in reporting 150 * -1, if failed to get AIDL stats services 151 * >0, count represents the number of stats failed to report. 152 */ 153 int reportStats(); 154 bool reportThermalAbnormality(const ThermalSensorAbnormalityDetected::AbnormalityType &type, 155 std::string_view name, std::optional<int> reading); 156 // Get a snapshot of Thermal Stats Sensor Map till that point in time 157 std::unordered_map<std::string, SensorTempStats> GetSensorTempStatsSnapshot(); 158 // Get a snapshot of Thermal Stats Sensor Map till that point in time 159 std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>> 160 GetSensorCoolingDeviceRequestStatsSnapshot(); 161 162 private: 163 static constexpr std::chrono::milliseconds kUpdateIntervalMs = 164 std::chrono::duration_cast<std::chrono::milliseconds>(24h); 165 boot_clock::time_point last_total_stats_report_time = boot_clock::time_point::min(); 166 int abnormal_stats_reported_per_update_interval = 0; 167 mutable std::shared_mutex sensor_stats_mutex_; 168 SensorStats sensor_stats; 169 mutable std::shared_mutex sensor_cdev_request_stats_map_mutex_; 170 ThermalHelper *thermal_helper_handle_; 171 // userVote request stat for the sensor to the corresponding cdev (sensor -> cdev -> 172 // StatsRecord) 173 std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>> 174 sensor_cdev_request_stats_map_; 175 176 bool initializeSensorTempStats( 177 const StatsInfo<float> &sensor_stats_info, 178 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_); 179 bool initializeSensorCdevRequestStats( 180 const StatsInfo<int> &request_stats_info, 181 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_, 182 const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_); 183 bool initializeSensorAbnormalityStats( 184 const AbnormalStatsInfo &abnormal_stats_info, 185 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_); 186 void updateStatsRecord(StatsRecord *stats_record, int new_state); 187 void verifySensorAbnormality(std::string_view sensor, float temperature); 188 int reportAllSensorTempStats(const std::shared_ptr<IStats> &stats_client); 189 bool reportSensorTempStats(const std::shared_ptr<IStats> &stats_client, std::string_view sensor, 190 const SensorTempStats &sensor_temp_stats, StatsRecord *stats_record); 191 int reportAllSensorCdevRequestStats(const std::shared_ptr<IStats> &stats_client); 192 bool reportSensorCdevRequestStats(const std::shared_ptr<IStats> &stats_client, 193 std::string_view sensor, std::string_view cdev, 194 StatsRecord *stats_record); 195 bool reportAtom(const std::shared_ptr<IStats> &stats_client, const int32_t &atom_id, 196 std::vector<VendorAtomValue> &&values); 197 std::vector<int64_t> processStatsRecordForReporting(StatsRecord *stats_record); 198 StatsRecord restoreStatsRecordOnFailure(StatsRecord &&stats_record_before_failure); 199 }; 200 201 } // namespace implementation 202 } // namespace thermal 203 } // namespace hardware 204 } // namespace android 205 } // namespace aidl 206