• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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