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 23 #include <chrono> 24 #include <shared_mutex> 25 #include <string_view> 26 #include <unordered_map> 27 #include <vector> 28 29 #include "thermal_info.h" 30 31 namespace aidl { 32 namespace android { 33 namespace hardware { 34 namespace thermal { 35 namespace implementation { 36 37 using aidl::android::frameworks::stats::IStats; 38 using aidl::android::frameworks::stats::VendorAtomValue; 39 using ::android::base::boot_clock; 40 using std::chrono::system_clock; 41 using SystemTimePoint = std::chrono::time_point<std::chrono::system_clock>; 42 43 constexpr int kMaxStatsReportingFailCount = 3; 44 45 struct StatsRecord { 46 int cur_state; /* temperature / cdev state at current time */ 47 boot_clock::time_point cur_state_start_time; 48 boot_clock::time_point last_stats_report_time = boot_clock::time_point::min(); 49 std::vector<std::chrono::milliseconds> time_in_state_ms; /* stats array */ 50 int report_fail_count = 0; /* Number of times failed to report stats */ 51 explicit StatsRecord(const size_t &time_in_state_size, int state = 0) cur_stateStatsRecord52 : cur_state(state), 53 cur_state_start_time(boot_clock::now()), 54 last_stats_report_time(boot_clock::now()), 55 report_fail_count(0) { 56 time_in_state_ms = std::vector<std::chrono::milliseconds>( 57 time_in_state_size, std::chrono::milliseconds::zero()); 58 } 59 StatsRecord() = default; 60 StatsRecord(const StatsRecord &) = default; 61 StatsRecord &operator=(const StatsRecord &) = default; 62 StatsRecord(StatsRecord &&) = default; 63 StatsRecord &operator=(StatsRecord &&) = default; 64 ~StatsRecord() = default; 65 }; 66 67 template <typename ValueType> 68 struct StatsByThreshold { 69 std::vector<ValueType> thresholds; 70 std::optional<std::string> logging_name; 71 StatsRecord stats_record; StatsByThresholdStatsByThreshold72 explicit StatsByThreshold(ThresholdList<ValueType> threshold_list) 73 : thresholds(threshold_list.thresholds), logging_name(threshold_list.logging_name) { 74 // number of states = number of thresholds + 1 75 // e.g. threshold: [30, 50, 60] 76 // buckets: [MIN - 30, 30 - 50, 50-60, 60-MAX] 77 int time_in_state_size = threshold_list.thresholds.size() + 1; 78 stats_record = StatsRecord(time_in_state_size); 79 } 80 StatsByThreshold() = default; 81 StatsByThreshold(const StatsByThreshold &) = default; 82 StatsByThreshold &operator=(const StatsByThreshold &) = default; 83 StatsByThreshold(StatsByThreshold &&) = default; 84 StatsByThreshold &operator=(StatsByThreshold &&) = default; 85 ~StatsByThreshold() = default; 86 }; 87 88 template <typename ValueType> 89 struct ThermalStats { 90 std::vector<StatsByThreshold<ValueType>> stats_by_custom_threshold; 91 std::optional<StatsRecord> stats_by_default_threshold; 92 }; 93 94 struct SensorTempStats : ThermalStats<float> { 95 float max_temp = std::numeric_limits<float>::min(); 96 SystemTimePoint max_temp_timestamp = SystemTimePoint::min(); 97 float min_temp = std::numeric_limits<float>::max(); 98 SystemTimePoint min_temp_timestamp = SystemTimePoint::min(); 99 }; 100 101 class ThermalStatsHelper { 102 public: 103 ThermalStatsHelper() = default; 104 ~ThermalStatsHelper() = default; 105 // Disallow copy and assign 106 ThermalStatsHelper(const ThermalStatsHelper &) = delete; 107 void operator=(const ThermalStatsHelper &) = delete; 108 109 bool initializeStats(const Json::Value &config, 110 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_, 111 const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_); 112 void updateSensorCdevRequestStats(std::string_view trigger_sensor, std::string_view cdev, 113 int new_state); 114 void updateSensorTempStatsBySeverity(std::string_view sensor, 115 const ThrottlingSeverity &severity); 116 void updateSensorTempStatsByThreshold(std::string_view sensor, float temperature); 117 /* 118 * Function to report all the stats by calling all specific stats reporting function. 119 * Returns: 120 * 0, if time_elapsed < kUpdateIntervalMs or if no failure in reporting 121 * -1, if failed to get AIDL stats services 122 * >0, count represents the number of stats failed to report. 123 */ 124 int reportStats(); 125 // Get a snapshot of Thermal Stats Sensor Map till that point in time 126 std::unordered_map<std::string, SensorTempStats> GetSensorTempStatsSnapshot(); 127 // Get a snapshot of Thermal Stats Sensor Map till that point in time 128 std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>> 129 GetSensorCoolingDeviceRequestStatsSnapshot(); 130 131 private: 132 static constexpr std::chrono::milliseconds kUpdateIntervalMs = 133 std::chrono::duration_cast<std::chrono::milliseconds>(24h); 134 boot_clock::time_point last_total_stats_report_time = boot_clock::time_point::min(); 135 136 mutable std::shared_mutex sensor_temp_stats_map_mutex_; 137 // Temperature stats for each sensor being watched 138 std::unordered_map<std::string, SensorTempStats> sensor_temp_stats_map_; 139 mutable std::shared_mutex sensor_cdev_request_stats_map_mutex_; 140 // userVote request stat for the sensor to the corresponding cdev (sensor -> cdev -> 141 // StatsRecord) 142 std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>> 143 sensor_cdev_request_stats_map_; 144 145 bool initializeSensorTempStats( 146 const StatsInfo<float> &sensor_stats_info, 147 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_); 148 bool initializeSensorCdevRequestStats( 149 const StatsInfo<int> &request_stats_info, 150 const std::unordered_map<std::string, SensorInfo> &sensor_info_map_, 151 const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_); 152 void updateStatsRecord(StatsRecord *stats_record, int new_state); 153 int reportAllSensorTempStats(const std::shared_ptr<IStats> &stats_client); 154 bool reportSensorTempStats(const std::shared_ptr<IStats> &stats_client, std::string_view sensor, 155 const SensorTempStats &sensor_temp_stats, StatsRecord *stats_record); 156 int reportAllSensorCdevRequestStats(const std::shared_ptr<IStats> &stats_client); 157 bool reportSensorCdevRequestStats(const std::shared_ptr<IStats> &stats_client, 158 std::string_view sensor, std::string_view cdev, 159 StatsRecord *stats_record); 160 bool reportAtom(const std::shared_ptr<IStats> &stats_client, const int32_t &atom_id, 161 std::vector<VendorAtomValue> &&values); 162 std::vector<int64_t> processStatsRecordForReporting(StatsRecord *stats_record); 163 StatsRecord restoreStatsRecordOnFailure(StatsRecord &&stats_record_before_failure); 164 }; 165 166 } // namespace implementation 167 } // namespace thermal 168 } // namespace hardware 169 } // namespace android 170 } // namespace aidl 171