You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
7.5 KiB
171 lines
7.5 KiB
1 year ago
|
/*
|
||
|
* Copyright (C) 2022 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <aidl/android/frameworks/stats/IStats.h>
|
||
|
#include <aidl/android/hardware/thermal/Temperature.h>
|
||
|
#include <android-base/chrono_utils.h>
|
||
|
|
||
|
#include <chrono>
|
||
|
#include <shared_mutex>
|
||
|
#include <string_view>
|
||
|
#include <unordered_map>
|
||
|
#include <vector>
|
||
|
|
||
|
#include "thermal_info.h"
|
||
|
|
||
|
namespace aidl {
|
||
|
namespace android {
|
||
|
namespace hardware {
|
||
|
namespace thermal {
|
||
|
namespace implementation {
|
||
|
|
||
|
using aidl::android::frameworks::stats::IStats;
|
||
|
using aidl::android::frameworks::stats::VendorAtomValue;
|
||
|
using ::android::base::boot_clock;
|
||
|
using std::chrono::system_clock;
|
||
|
using SystemTimePoint = std::chrono::time_point<std::chrono::system_clock>;
|
||
|
|
||
|
constexpr int kMaxStatsReportingFailCount = 3;
|
||
|
|
||
|
struct StatsRecord {
|
||
|
int cur_state; /* temperature / cdev state at current time */
|
||
|
boot_clock::time_point cur_state_start_time;
|
||
|
boot_clock::time_point last_stats_report_time = boot_clock::time_point::min();
|
||
|
std::vector<std::chrono::milliseconds> time_in_state_ms; /* stats array */
|
||
|
int report_fail_count = 0; /* Number of times failed to report stats */
|
||
|
explicit StatsRecord(const size_t &time_in_state_size, int state = 0)
|
||
|
: cur_state(state),
|
||
|
cur_state_start_time(boot_clock::now()),
|
||
|
last_stats_report_time(boot_clock::now()),
|
||
|
report_fail_count(0) {
|
||
|
time_in_state_ms = std::vector<std::chrono::milliseconds>(
|
||
|
time_in_state_size, std::chrono::milliseconds::zero());
|
||
|
}
|
||
|
StatsRecord() = default;
|
||
|
StatsRecord(const StatsRecord &) = default;
|
||
|
StatsRecord &operator=(const StatsRecord &) = default;
|
||
|
StatsRecord(StatsRecord &&) = default;
|
||
|
StatsRecord &operator=(StatsRecord &&) = default;
|
||
|
~StatsRecord() = default;
|
||
|
};
|
||
|
|
||
|
template <typename ValueType>
|
||
|
struct StatsByThreshold {
|
||
|
std::vector<ValueType> thresholds;
|
||
|
std::optional<std::string> logging_name;
|
||
|
StatsRecord stats_record;
|
||
|
explicit StatsByThreshold(ThresholdList<ValueType> threshold_list)
|
||
|
: thresholds(threshold_list.thresholds), logging_name(threshold_list.logging_name) {
|
||
|
// number of states = number of thresholds + 1
|
||
|
// e.g. threshold: [30, 50, 60]
|
||
|
// buckets: [MIN - 30, 30 - 50, 50-60, 60-MAX]
|
||
|
int time_in_state_size = threshold_list.thresholds.size() + 1;
|
||
|
stats_record = StatsRecord(time_in_state_size);
|
||
|
}
|
||
|
StatsByThreshold() = default;
|
||
|
StatsByThreshold(const StatsByThreshold &) = default;
|
||
|
StatsByThreshold &operator=(const StatsByThreshold &) = default;
|
||
|
StatsByThreshold(StatsByThreshold &&) = default;
|
||
|
StatsByThreshold &operator=(StatsByThreshold &&) = default;
|
||
|
~StatsByThreshold() = default;
|
||
|
};
|
||
|
|
||
|
template <typename ValueType>
|
||
|
struct ThermalStats {
|
||
|
std::vector<StatsByThreshold<ValueType>> stats_by_custom_threshold;
|
||
|
std::optional<StatsRecord> stats_by_default_threshold;
|
||
|
};
|
||
|
|
||
|
struct SensorTempStats : ThermalStats<float> {
|
||
|
float max_temp = std::numeric_limits<float>::min();
|
||
|
SystemTimePoint max_temp_timestamp = SystemTimePoint::min();
|
||
|
float min_temp = std::numeric_limits<float>::max();
|
||
|
SystemTimePoint min_temp_timestamp = SystemTimePoint::min();
|
||
|
};
|
||
|
|
||
|
class ThermalStatsHelper {
|
||
|
public:
|
||
|
ThermalStatsHelper() = default;
|
||
|
~ThermalStatsHelper() = default;
|
||
|
// Disallow copy and assign
|
||
|
ThermalStatsHelper(const ThermalStatsHelper &) = delete;
|
||
|
void operator=(const ThermalStatsHelper &) = delete;
|
||
|
|
||
|
bool initializeStats(const Json::Value &config,
|
||
|
const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
|
||
|
const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_);
|
||
|
void updateSensorCdevRequestStats(std::string_view trigger_sensor, std::string_view cdev,
|
||
|
int new_state);
|
||
|
void updateSensorTempStatsBySeverity(std::string_view sensor,
|
||
|
const ThrottlingSeverity &severity);
|
||
|
void updateSensorTempStatsByThreshold(std::string_view sensor, float temperature);
|
||
|
/*
|
||
|
* Function to report all the stats by calling all specific stats reporting function.
|
||
|
* Returns:
|
||
|
* 0, if time_elapsed < kUpdateIntervalMs or if no failure in reporting
|
||
|
* -1, if failed to get AIDL stats services
|
||
|
* >0, count represents the number of stats failed to report.
|
||
|
*/
|
||
|
int reportStats();
|
||
|
// Get a snapshot of Thermal Stats Sensor Map till that point in time
|
||
|
std::unordered_map<std::string, SensorTempStats> GetSensorTempStatsSnapshot();
|
||
|
// Get a snapshot of Thermal Stats Sensor Map till that point in time
|
||
|
std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>>
|
||
|
GetSensorCoolingDeviceRequestStatsSnapshot();
|
||
|
|
||
|
private:
|
||
|
static constexpr std::chrono::milliseconds kUpdateIntervalMs =
|
||
|
std::chrono::duration_cast<std::chrono::milliseconds>(24h);
|
||
|
boot_clock::time_point last_total_stats_report_time = boot_clock::time_point::min();
|
||
|
|
||
|
mutable std::shared_mutex sensor_temp_stats_map_mutex_;
|
||
|
// Temperature stats for each sensor being watched
|
||
|
std::unordered_map<std::string, SensorTempStats> sensor_temp_stats_map_;
|
||
|
mutable std::shared_mutex sensor_cdev_request_stats_map_mutex_;
|
||
|
// userVote request stat for the sensor to the corresponding cdev (sensor -> cdev ->
|
||
|
// StatsRecord)
|
||
|
std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>>
|
||
|
sensor_cdev_request_stats_map_;
|
||
|
|
||
|
bool initializeSensorTempStats(
|
||
|
const StatsInfo<float> &sensor_stats_info,
|
||
|
const std::unordered_map<std::string, SensorInfo> &sensor_info_map_);
|
||
|
bool initializeSensorCdevRequestStats(
|
||
|
const StatsInfo<int> &request_stats_info,
|
||
|
const std::unordered_map<std::string, SensorInfo> &sensor_info_map_,
|
||
|
const std::unordered_map<std::string, CdevInfo> &cooling_device_info_map_);
|
||
|
void updateStatsRecord(StatsRecord *stats_record, int new_state);
|
||
|
int reportAllSensorTempStats(const std::shared_ptr<IStats> &stats_client);
|
||
|
bool reportSensorTempStats(const std::shared_ptr<IStats> &stats_client, std::string_view sensor,
|
||
|
const SensorTempStats &sensor_temp_stats, StatsRecord *stats_record);
|
||
|
int reportAllSensorCdevRequestStats(const std::shared_ptr<IStats> &stats_client);
|
||
|
bool reportSensorCdevRequestStats(const std::shared_ptr<IStats> &stats_client,
|
||
|
std::string_view sensor, std::string_view cdev,
|
||
|
StatsRecord *stats_record);
|
||
|
bool reportAtom(const std::shared_ptr<IStats> &stats_client, const int32_t &atom_id,
|
||
|
std::vector<VendorAtomValue> &&values);
|
||
|
std::vector<int64_t> processStatsRecordForReporting(StatsRecord *stats_record);
|
||
|
StatsRecord restoreStatsRecordOnFailure(StatsRecord &&stats_record_before_failure);
|
||
|
};
|
||
|
|
||
|
} // namespace implementation
|
||
|
} // namespace thermal
|
||
|
} // namespace hardware
|
||
|
} // namespace android
|
||
|
} // namespace aidl
|