diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-12-02 00:22:21 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-12-02 00:22:21 +0000 |
commit | 344e34ae44225c918a422c8217dbc76c7ff17296 (patch) | |
tree | 5dcd8026d92de6a753dfe8c1a9b1c88018f4a836 | |
parent | ae50908ab9a4c78f2b1a90661e257774a840ea5f (diff) | |
parent | d4fe1ba8b5cf5ac32282b98c4941bf4dcd6fadce (diff) | |
download | pixel-android13-d4-release.tar.gz |
Snap for 9358956 from d4fe1ba8b5cf5ac32282b98c4941bf4dcd6fadce to tm-d4-releaseandroid-13.0.0_r48android-13.0.0_r47android-13.0.0_r46android13-d4-s2-releaseandroid13-d4-s1-releaseandroid13-d4-release
Change-Id: I8b2448a69bb1dd519677f1c1e771bb3fd92ecbd8
-rw-r--r-- | pixelstats/Android.bp | 1 | ||||
-rw-r--r-- | pixelstats/SysfsCollector.cpp | 237 | ||||
-rw-r--r-- | pixelstats/TempResidencyReporter.cpp | 176 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/SysfsCollector.h | 23 | ||||
-rw-r--r-- | pixelstats/include/pixelstats/TempResidencyReporter.h | 50 | ||||
-rw-r--r-- | pixelstats/pixelatoms.proto | 140 |
6 files changed, 620 insertions, 7 deletions
diff --git a/pixelstats/Android.bp b/pixelstats/Android.bp index eadd8a96..ae49b535 100644 --- a/pixelstats/Android.bp +++ b/pixelstats/Android.bp @@ -73,6 +73,7 @@ cc_library { "StatsHelper.cpp", "SysfsCollector.cpp", "ThermalStatsReporter.cpp", + "TempResidencyReporter.cpp", "UeventListener.cpp", "WirelessChargeStats.cpp", "WlcReporter.cpp", diff --git a/pixelstats/SysfsCollector.cpp b/pixelstats/SysfsCollector.cpp index 8e5c709c..203ff0f7 100644 --- a/pixelstats/SysfsCollector.cpp +++ b/pixelstats/SysfsCollector.cpp @@ -55,10 +55,13 @@ using android::hardware::google::pixel::PixelAtoms::ThermalDfsStats; using android::hardware::google::pixel::PixelAtoms::VendorAudioHardwareStatsReported; using android::hardware::google::pixel::PixelAtoms::VendorChargeCycles; using android::hardware::google::pixel::PixelAtoms::VendorHardwareFailed; +using android::hardware::google::pixel::PixelAtoms::VendorLongIRQStatsReported; +using android::hardware::google::pixel::PixelAtoms::VendorResumeLatencyStats; using android::hardware::google::pixel::PixelAtoms::VendorSlowIo; using android::hardware::google::pixel::PixelAtoms::VendorSpeakerImpedance; using android::hardware::google::pixel::PixelAtoms::VendorSpeakerStatsReported; using android::hardware::google::pixel::PixelAtoms::VendorSpeechDspStat; +using android::hardware::google::pixel::PixelAtoms::VendorTempResidencyStats; using android::hardware::google::pixel::PixelAtoms::ZramBdStat; using android::hardware::google::pixel::PixelAtoms::ZramMmStat; @@ -89,7 +92,10 @@ SysfsCollector::SysfsCollector(const struct SysfsPaths &sysfs_paths) kBlockStatsLength(sysfs_paths.BlockStatsLength), kAmsRatePath(sysfs_paths.AmsRatePath), kThermalStatsPaths(sysfs_paths.ThermalStatsPaths), - kCCARatePath(sysfs_paths.CCARatePath) {} + kCCARatePath(sysfs_paths.CCARatePath), + kTempResidencyPath(sysfs_paths.TempResidencyPath), + kLongIRQMetricsPath(sysfs_paths.LongIRQMetricsPath), + kResumeLatencyMetricsPath(sysfs_paths.ResumeLatencyMetricsPath) {} bool SysfsCollector::ReadFileToInt(const std::string &path, int *val) { return ReadFileToInt(path.c_str(), val); @@ -814,6 +820,10 @@ void SysfsCollector::logBlockStatsReported(const std::shared_ptr<IStats> &stats_ } } +void SysfsCollector::logTempResidencyStats(const std::shared_ptr<IStats> &stats_client) { + temp_residency_reporter_.logTempResidencyStats(stats_client, kTempResidencyPath); +} + void SysfsCollector::reportZramMmStat(const std::shared_ptr<IStats> &stats_client) { std::string file_contents; if (!kZramMmStatPath) { @@ -1044,6 +1054,228 @@ void SysfsCollector::logVendorAudioHardwareStats(const std::shared_ptr<IStats> & ALOGE("Unable to report VendorAudioHardwareStatsReported to Stats service"); } +/** + * Logs the Resume Latency stats. + */ +void SysfsCollector::logVendorResumeLatencyStats(const std::shared_ptr<IStats> &stats_client) { + std::string file_contents; + if (!kResumeLatencyMetricsPath) { + ALOGE("ResumeLatencyMetrics path not specified"); + return; + } + if (!ReadFileToString(kResumeLatencyMetricsPath, &file_contents)) { + ALOGE("Unable to ResumeLatencyMetric %s - %s", kResumeLatencyMetricsPath, strerror(errno)); + return; + } + + int offset = 0; + int bytes_read; + const char *data = file_contents.c_str(); + int data_len = file_contents.length(); + + int curr_bucket_cnt; + if (!sscanf(data + offset, "Resume Latency Bucket Count: %d\n%n", &curr_bucket_cnt, + &bytes_read)) + return; + offset += bytes_read; + if (offset >= data_len) + return; + + int64_t max_latency; + if (!sscanf(data + offset, "Max Resume Latency: %ld\n%n", &max_latency, &bytes_read)) + return; + offset += bytes_read; + if (offset >= data_len) + return; + + uint64_t sum_latency; + if (!sscanf(data + offset, "Sum Resume Latency: %lu\n%n", &sum_latency, &bytes_read)) + return; + offset += bytes_read; + if (offset >= data_len) + return; + + if (curr_bucket_cnt > kMaxResumeLatencyBuckets) + return; + if (curr_bucket_cnt != prev_data.bucket_cnt) { + prev_data.resume_latency_buckets.clear(); + } + + int64_t total_latency_cnt = 0; + int64_t count; + int index = 2; + std::vector<VendorAtomValue> values(curr_bucket_cnt + 2); + VendorAtomValue tmp; + // Iterate over resume latency buckets to get latency count within some latency thresholds + while (sscanf(data + offset, "%*ld - %*ldms ====> %ld\n%n", &count, &bytes_read) == 1 || + sscanf(data + offset, "%*ld - infms ====> %ld\n%n", &count, &bytes_read) == 1) { + offset += bytes_read; + if (offset >= data_len && (index + 1 < curr_bucket_cnt + 2)) + return; + if (curr_bucket_cnt == prev_data.bucket_cnt) { + tmp.set<VendorAtomValue::longValue>(count - + prev_data.resume_latency_buckets[index - 2]); + prev_data.resume_latency_buckets[index - 2] = count; + } else { + tmp.set<VendorAtomValue::longValue>(count); + prev_data.resume_latency_buckets.push_back(count); + } + if (index >= curr_bucket_cnt + 2) + return; + values[index] = tmp; + index += 1; + total_latency_cnt += count; + } + tmp.set<VendorAtomValue::longValue>(max_latency); + values[0] = tmp; + if ((sum_latency - prev_data.resume_latency_sum_ms < 0) || + (total_latency_cnt - prev_data.resume_count <= 0)) { + tmp.set<VendorAtomValue::longValue>(-1); + ALOGI("average resume latency get overflow"); + } else { + tmp.set<VendorAtomValue::longValue>( + (int64_t)(sum_latency - prev_data.resume_latency_sum_ms) / + (total_latency_cnt - prev_data.resume_count)); + } + values[1] = tmp; + + prev_data.resume_latency_sum_ms = sum_latency; + prev_data.resume_count = total_latency_cnt; + prev_data.bucket_cnt = curr_bucket_cnt; + // Send vendor atom to IStats HAL + VendorAtom event = {.reverseDomainName = "", + .atomId = PixelAtoms::Atom::kVendorResumeLatencyStats, + .values = std::move(values)}; + const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event); + if (!ret.isOk()) + ALOGE("Unable to report VendorResumeLatencyStats to Stats service"); +} + +bool cmp(const std::pair<int, int64_t> &a, const std::pair<int, int64_t> &b) { + return a.second > b.second; +} + +/** + * Sort irq stats by irq latency, and load top 5 irq stats. + */ +void process_irqatom_values(std::vector<std::pair<int, int64_t>> sorted_pair, + std::vector<VendorAtomValue> *values) { + VendorAtomValue tmp; + sort(sorted_pair.begin(), sorted_pair.end(), cmp); + int irq_stats_size = sorted_pair.size(); + for (int i = 0; i < 5; i++) { + if (irq_stats_size < 5 && i >= irq_stats_size) { + tmp.set<VendorAtomValue::longValue>(-1); + values->push_back(tmp); + tmp.set<VendorAtomValue::longValue>(0); + values->push_back(tmp); + } else { + tmp.set<VendorAtomValue::longValue>(sorted_pair[i].first); + values->push_back(tmp); + tmp.set<VendorAtomValue::longValue>(sorted_pair[i].second); + values->push_back(tmp); + } + } +} + +/** + * Logs the Long irq stats. + */ +void SysfsCollector::logVendorLongIRQStatsReported(const std::shared_ptr<IStats> &stats_client) { + std::string file_contents; + if (!kLongIRQMetricsPath) { + ALOGV("LongIRQ path not specified"); + return; + } + if (!ReadFileToString(kLongIRQMetricsPath, &file_contents)) { + ALOGE("Unable to LongIRQ %s - %s", kLongIRQMetricsPath, strerror(errno)); + return; + } + int offset = 0; + int bytes_read; + const char *data = file_contents.c_str(); + int data_len = file_contents.length(); + // Get, process, store softirq stats + std::vector<std::pair<int, int64_t>> sorted_softirq_pair; + int64_t softirq_count; + if (sscanf(data + offset, "long SOFTIRQ count: %ld\n%n", &softirq_count, &bytes_read) != 1) + return; + offset += bytes_read; + if (offset >= data_len) + return; + std::vector<VendorAtomValue> values; + VendorAtomValue tmp; + if (softirq_count - prev_data.softirq_count < 0) { + tmp.set<VendorAtomValue::intValue>(-1); + ALOGI("long softirq count get overflow"); + } else { + tmp.set<VendorAtomValue::longValue>(softirq_count - prev_data.softirq_count); + } + values.push_back(tmp); + + if (sscanf(data + offset, "long SOFTIRQ detail (num, latency):\n%n", &bytes_read) != 0) + return; + offset += bytes_read; + if (offset >= data_len) + return; + + // Iterate over softirq stats and record top 5 long softirq + int64_t softirq_latency; + int softirq_num; + while (sscanf(data + offset, "%d %ld\n%n", &softirq_num, &softirq_latency, &bytes_read) == 2) { + sorted_softirq_pair.push_back(std::make_pair(softirq_num, softirq_latency)); + offset += bytes_read; + if (offset >= data_len) + return; + } + process_irqatom_values(sorted_softirq_pair, &values); + + // Get, process, store irq stats + std::vector<std::pair<int, int64_t>> sorted_irq_pair; + int64_t irq_count; + if (sscanf(data + offset, "long IRQ count: %ld\n%n", &irq_count, &bytes_read) != 1) + return; + offset += bytes_read; + if (offset >= data_len) + return; + if (irq_count - prev_data.irq_count < 0) { + tmp.set<VendorAtomValue::intValue>(-1); + ALOGI("long irq count get overflow"); + } else { + tmp.set<VendorAtomValue::longValue>(irq_count - prev_data.irq_count); + } + values.push_back(tmp); + + if (sscanf(data + offset, "long IRQ detail (num, latency):\n%n", &bytes_read) != 0) + return; + offset += bytes_read; + if (offset >= data_len) + return; + + int64_t irq_latency; + int irq_num; + int index = 0; + // Iterate over softirq stats and record top 5 long irq + while (sscanf(data + offset, "%d %ld\n%n", &irq_num, &irq_latency, &bytes_read) == 2) { + sorted_irq_pair.push_back(std::make_pair(irq_num, irq_latency)); + offset += bytes_read; + if (offset >= data_len && index < 5) + return; + index += 1; + } + process_irqatom_values(sorted_irq_pair, &values); + + prev_data.softirq_count = softirq_count; + prev_data.irq_count = irq_count; + // Send vendor atom to IStats HAL + VendorAtom event = {.reverseDomainName = "", + .atomId = PixelAtoms::Atom::kVendorLongIrqStatsReported, + .values = std::move(values)}; + const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event); + if (!ret.isOk()) + ALOGE("Unable to report kVendorLongIRQStatsReported to Stats service"); +} + void SysfsCollector::logPerDay() { const std::shared_ptr<IStats> stats_client = getStatsService(); if (!stats_client) { @@ -1075,6 +1307,9 @@ void SysfsCollector::logPerDay() { mm_metrics_reporter_.logPixelMmMetricsPerDay(stats_client); logVendorAudioHardwareStats(stats_client); logThermalStats(stats_client); + logTempResidencyStats(stats_client); + logVendorLongIRQStatsReported(stats_client); + logVendorResumeLatencyStats(stats_client); } void SysfsCollector::aggregatePer5Min() { diff --git a/pixelstats/TempResidencyReporter.cpp b/pixelstats/TempResidencyReporter.cpp new file mode 100644 index 00000000..baa1d4a5 --- /dev/null +++ b/pixelstats/TempResidencyReporter.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2021 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. + */ + +#define LOG_TAG "pixelstats: TempResidencyStats" + +#include <aidl/android/frameworks/stats/IStats.h> +#include <android-base/chrono_utils.h> +#include <android-base/file.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> +#include <android/binder_manager.h> +#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h> +#include <pixelstats/TempResidencyReporter.h> +#include <utils/Log.h> + +#include <cinttypes> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +using aidl::android::frameworks::stats::IStats; +using aidl::android::frameworks::stats::VendorAtom; +using aidl::android::frameworks::stats::VendorAtomValue; +using android::base::ReadFileToString; +using android::hardware::google::pixel::PixelAtoms::ThermalDfsStats; + +/** + * Parse file_contents and read residency stats into cur_stats. + */ +bool parse_file_contents(std::string file_contents, + std::map<std::string, std::vector<int64_t>> *cur_stats) { + const char *data = file_contents.c_str(); + int data_len = file_contents.length(); + char sensor_name[32]; + int offset = 0; + int bytes_read; + + while (sscanf(data + offset, "THERMAL ZONE: %31s\n%n", sensor_name, &bytes_read) == 1) { + int64_t temp_res_value; + int num_stats_buckets; + int index = 0; + offset += bytes_read; + if (offset >= data_len) + return false; + + std::string sensor_name_str = sensor_name; + + if (!sscanf(data + offset, "NUM_TEMP_RESIDENCY_BUCKETS: %d\n%n", &num_stats_buckets, + &bytes_read)) + return false; + offset += bytes_read; + if (offset >= data_len) + return false; + while (index < num_stats_buckets) { + if (sscanf(data + offset, "-inf - %*d ====> %ldms\n%n", &temp_res_value, &bytes_read) != + 1 && + sscanf(data + offset, "%*d - %*d ====> %ldms\n%n", &temp_res_value, &bytes_read) != + 1 && + sscanf(data + offset, "%*d - inf ====> %ldms\n\n%n", &temp_res_value, + &bytes_read) != 1) + return false; + + (*cur_stats)[sensor_name_str].push_back(temp_res_value); + index++; + + offset += bytes_read; + if ((offset >= data_len) && (index < num_stats_buckets)) + return false; + } + } + return true; +} + +/** + * Logs the Temperature residency stats for every thermal zone. + */ +void TempResidencyReporter::logTempResidencyStats(const std::shared_ptr<IStats> &stats_client, + const char *const temperature_residency_path) { + if (!temperature_residency_path) { + ALOGV("TempResidencyStatsPath path not specified"); + return; + } + std::string file_contents; + if (!ReadFileToString(temperature_residency_path, &file_contents)) { + ALOGE("Unable to read TempResidencyStatsPath %s - %s", temperature_residency_path, + strerror(errno)); + return; + } + std::map<std::string, std::vector<int64_t>> cur_stats_map; + if (!parse_file_contents(file_contents, &cur_stats_map)) { + ALOGE("Fail to parse TempResidencyStatsPath"); + return; + } + if (!cur_stats_map.size()) + return; + ::android::base::boot_clock::time_point curTime = ::android::base::boot_clock::now(); + int64_t since_last_update_ms = + std::chrono::duration_cast<std::chrono::milliseconds>(curTime - prevTime).count(); + + auto cur_stats_map_iterator = cur_stats_map.begin(); + VendorAtomValue tmp_atom_value; + + // Iterate through cur_stats_map by sensor_name + while (cur_stats_map_iterator != cur_stats_map.end()) { + std::vector<VendorAtomValue> values; + std::string sensor_name_str = cur_stats_map_iterator->first; + std::vector<int64_t> residency_stats = cur_stats_map_iterator->second; + tmp_atom_value.set<VendorAtomValue::stringValue>(sensor_name_str); + values.push_back(tmp_atom_value); + tmp_atom_value.set<VendorAtomValue::longValue>(since_last_update_ms); + values.push_back(tmp_atom_value); + + bool key_in_map = (prev_stats.find(sensor_name_str)) != prev_stats.end(); + bool stat_len_match = (residency_stats.size() == prev_stats[sensor_name_str].size()); + if (key_in_map && !stat_len_match) + prev_stats[sensor_name_str].clear(); + + int64_t sum_residency = 0; + if (residency_stats.size() > kMaxBucketLen) { + cur_stats_map_iterator++; + continue; + } + // Iterate over every temperature residency buckets + for (int index = 0; index < residency_stats.size(); index++) { + // Get diff if stats arr length match previous stats + // Otherwise use raw stats as temperature residency stats per day + if (key_in_map && stat_len_match) { + int64_t diff_residency = + residency_stats[index] - prev_stats[sensor_name_str][index]; + tmp_atom_value.set<VendorAtomValue::longValue>(diff_residency); + sum_residency += diff_residency; + prev_stats[sensor_name_str][index] = residency_stats[index]; + } else { + tmp_atom_value.set<VendorAtomValue::longValue>(residency_stats[index]); + sum_residency += residency_stats[index]; + prev_stats[sensor_name_str].push_back(residency_stats[index]); + } + values.push_back(tmp_atom_value); + } + if (abs(since_last_update_ms - sum_residency) > kMaxResidencyDiffMs) + ALOGI("Thermal zone: %s Temperature residency stats not good!\ndevice sum_residency: " + "%ldms, since_last_update_ms %ldms\n", + sensor_name_str.c_str(), sum_residency, since_last_update_ms); + + // Send vendor atom to IStats HAL + VendorAtom event = {.reverseDomainName = "", + .atomId = PixelAtoms::Atom::kVendorTempResidencyStats, + .values = std::move(values)}; + ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event); + if (!ret.isOk()) + ALOGE("Unable to report VendorTempResidencyStats to Stats service"); + + cur_stats_map_iterator++; + } + prevTime = curTime; +} + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/pixelstats/include/pixelstats/SysfsCollector.h b/pixelstats/include/pixelstats/SysfsCollector.h index f487dda0..df4a3315 100644 --- a/pixelstats/include/pixelstats/SysfsCollector.h +++ b/pixelstats/include/pixelstats/SysfsCollector.h @@ -24,6 +24,7 @@ #include "BatteryHealthReporter.h" #include "MitigationStatsReporter.h" #include "MmMetricsReporter.h" +#include "TempResidencyReporter.h" #include "ThermalStatsReporter.h" namespace android { @@ -65,6 +66,9 @@ class SysfsCollector { const char *const AmsRatePath; const std::vector<std::string> ThermalStatsPaths; const char *const CCARatePath; + const char *const TempResidencyPath; + const char *const LongIRQMetricsPath; + const char *const ResumeLatencyMetricsPath; }; SysfsCollector(const struct SysfsPaths &paths); @@ -100,10 +104,13 @@ class SysfsCollector { void reportSlowIoFromFile(const std::shared_ptr<IStats> &stats_client, const char *path, const VendorSlowIo::IoOperation &operation_s); + void logTempResidencyStats(const std::shared_ptr<IStats> &stats_client); void reportZramMmStat(const std::shared_ptr<IStats> &stats_client); void reportZramBdStat(const std::shared_ptr<IStats> &stats_client); int getReclaimedSegments(const std::string &mode); void logVendorAudioHardwareStats(const std::shared_ptr<IStats> &stats_client); + void logVendorLongIRQStatsReported(const std::shared_ptr<IStats> &stats_client); + void logVendorResumeLatencyStats(const std::shared_ptr<IStats> &stats_client); const char *const kSlowioReadCntPath; const char *const kSlowioWriteCntPath; @@ -132,13 +139,16 @@ class SysfsCollector { const char *const kAmsRatePath; const std::vector<std::string> kThermalStatsPaths; const char *const kCCARatePath; + const char *const kTempResidencyPath; + const char *const kLongIRQMetricsPath; + const char *const kResumeLatencyMetricsPath; BatteryEEPROMReporter battery_EEPROM_reporter_; MmMetricsReporter mm_metrics_reporter_; MitigationStatsReporter mitigation_stats_reporter_; ThermalStatsReporter thermal_stats_reporter_; BatteryHealthReporter battery_health_reporter_; - + TempResidencyReporter temp_residency_reporter_; // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so // store everything in the values array at the index of the field number // -2. @@ -146,6 +156,17 @@ class SysfsCollector { bool log_once_reported = false; int64_t prev_huge_pages_since_boot_ = -1; + + struct perf_metrics_data { + int64_t softirq_count; + int64_t irq_count; + uint64_t resume_latency_sum_ms; + int64_t resume_count; + std::vector<int64_t> resume_latency_buckets; + int bucket_cnt; + }; + struct perf_metrics_data prev_data; + const int kMaxResumeLatencyBuckets = 36; }; } // namespace pixel diff --git a/pixelstats/include/pixelstats/TempResidencyReporter.h b/pixelstats/include/pixelstats/TempResidencyReporter.h new file mode 100644 index 00000000..07e33433 --- /dev/null +++ b/pixelstats/include/pixelstats/TempResidencyReporter.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 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. + */ + +#include <aidl/android/frameworks/stats/IStats.h> +#include <android-base/chrono_utils.h> +#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h> + +#include <string> + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +using aidl::android::frameworks::stats::IStats; +using aidl::android::frameworks::stats::VendorAtomValue; + +/** + * A class to upload Pixel TempResidency Stats metrics + */ +class TempResidencyReporter { + public: + void logTempResidencyStats(const std::shared_ptr<IStats> &stats_client, + const char *const temperature_residency_path); + + private: + std::map<std::string, std::vector<int64_t>> prev_stats; + ::android::base::boot_clock::time_point prevTime = + ::android::base::boot_clock::time_point::min(); + const int kMaxBucketLen = 20; + const int kMaxResidencyDiffMs = 3000; +}; + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/pixelstats/pixelatoms.proto b/pixelstats/pixelatoms.proto index e4d98bfd..433768a3 100644 --- a/pixelstats/pixelatoms.proto +++ b/pixelstats/pixelatoms.proto @@ -84,6 +84,9 @@ message Atom { VendorAudioHardwareStatsReported vendor_audio_hardware_stats_reported = 105041; ThermalDfsStats thermal_dfs_stats = 105042; + VendorLongIRQStatsReported vendor_long_irq_stats_reported = 105043; + VendorResumeLatencyStats vendor_resume_latency_stats = 105044; + VendorTempResidencyStats vendor_temp_residency_stats = 105045; } // AOSP atom ID range ends at 109999 } @@ -1158,11 +1161,11 @@ message BatteryHealthStatus { optional int32 health_algorithm = 2; enum HealthStatus { - UNKNOWN = 0; // The health status is unknown due to a SW limitation or issue - NOMINAL = 1; // The battery is operating as expected - MARGINAL = 2; // The battery may need replacement soon - NEEDS_REPLACEMENT = 3; // The battery needs replacement - FAILED = 4; // The battery has failed and no longer operates as expected + UNKNOWN = -1; // The health status is unknown due to a SW limitation or issue + NOMINAL = 0; // The battery is operating as expected + MARGINAL = 1; // The battery may need replacement soon + NEEDS_REPLACEMENT = 2; // The battery needs replacement + FAILED = 3; // The battery has failed and no longer operates as expected } // HealthStatus calculated using health_index, health_perf_index. @@ -1281,3 +1284,130 @@ message VendorAudioHardwareStatsReported { /* cca_enable: UI enable & algorithm is inactive. (C2) */ optional int32 rate_of_cca_enable_per_day = 4; } + +/* + * Logs vendor stats about long IRQs. + * + * IRQ is considered long when it exceeds a threshold (currently 1 ms). + * Stats include top 5 slowest IRQs: their numbers and the worst latency. + * Stats are reset after every report. + */ +message VendorLongIRQStatsReported { + optional string reverse_domain_name = 1; + + // Count of long soft IRQ since last report. + optional int64 long_softirq_count = 2; + + optional int64 top1_softirq_num = 3; + optional int64 top1_softirq_latency_us = 4; + optional int64 top2_softirq_num = 5; + optional int64 top2_softirq_latency_us = 6; + optional int64 top3_softirq_num = 7; + optional int64 top3_softirq_latency_us = 8; + optional int64 top4_softirq_num = 9; + optional int64 top4_softirq_latency_us = 10; + optional int64 top5_softirq_num = 11; + optional int64 top5_softirq_latency_us = 12; + + // Count of long IRQ since last report. + optional int64 long_irq_count = 13; + + optional int64 top1_irq_num = 14; + optional int64 top1_irq_latency_us = 15; + optional int64 top2_irq_num = 16; + optional int64 top2_irq_latency_us = 17; + optional int64 top3_irq_num = 18; + optional int64 top3_irq_latency_us = 19; + optional int64 top4_irq_num = 20; + optional int64 top4_irq_latency_us = 21; + optional int64 top5_irq_num = 22; + optional int64 top5_irq_latency_us = 23; +} + +/** + * Logs the Temperature residency stats per thermal zone. + */ +message VendorTempResidencyStats { + optional string reverse_domain_name = 1; + // Thermal zone name + optional string sensor_name = 2; + + // Time since last collect of this thermal zone + optional int64 since_last_update_ms = 3; + + // Temperature residency stats is measured by time in ms that a temperature zone's temperature + // lay within some temperature thresholds + // e.g. + // With temperature thresholds predefined as thresholds_i, thresholds_i+1, + // temp_residency_ms_bucket_i measures how much time the sensor lay within this two thresholds + optional int64 temp_residency_ms_bucket_1 = 4; + optional int64 temp_residency_ms_bucket_2 = 5; + optional int64 temp_residency_ms_bucket_3 = 6; + optional int64 temp_residency_ms_bucket_4 = 7; + optional int64 temp_residency_ms_bucket_5 = 8; + optional int64 temp_residency_ms_bucket_6 = 9; + optional int64 temp_residency_ms_bucket_7 = 10; + optional int64 temp_residency_ms_bucket_8 = 11; + optional int64 temp_residency_ms_bucket_9 = 12; + optional int64 temp_residency_ms_bucket_10 = 13; + optional int64 temp_residency_ms_bucket_11 = 14; + optional int64 temp_residency_ms_bucket_12 = 15; + optional int64 temp_residency_ms_bucket_13 = 16; + optional int64 temp_residency_ms_bucket_14 = 17; + optional int64 temp_residency_ms_bucket_15 = 18; + optional int64 temp_residency_ms_bucket_16 = 19; + optional int64 temp_residency_ms_bucket_17 = 20; + optional int64 temp_residency_ms_bucket_18 = 21; + optional int64 temp_residency_ms_bucket_19 = 22; + optional int64 temp_residency_ms_bucket_20 = 23; +} + +/** + * Logs the Resume Latency stats. + */ +message VendorResumeLatencyStats { + optional string reverse_domain_name = 1; + optional int64 max_latency_ms = 2; + optional int64 avg_latency_ms = 3; + + // Resume Latency stats is measured by count of resumes that lay within some latency thresholds + // e.g. + // With resume times thresholds predefined as thresholds_i, thresholds_i+1, + // resume_count_bucket_i measures count of resumes that lay within this two thresholds + optional int64 resume_count_bucket_1 = 4; + optional int64 resume_count_bucket_2 = 5; + optional int64 resume_count_bucket_3 = 6; + optional int64 resume_count_bucket_4 = 7; + optional int64 resume_count_bucket_5 = 8; + optional int64 resume_count_bucket_6 = 9; + optional int64 resume_count_bucket_7 = 10; + optional int64 resume_count_bucket_8 = 11; + optional int64 resume_count_bucket_9 = 12; + optional int64 resume_count_bucket_10 = 13; + optional int64 resume_count_bucket_11 = 14; + optional int64 resume_count_bucket_12 = 15; + optional int64 resume_count_bucket_13 = 16; + optional int64 resume_count_bucket_14 = 17; + optional int64 resume_count_bucket_15 = 18; + optional int64 resume_count_bucket_16 = 19; + optional int64 resume_count_bucket_17 = 20; + optional int64 resume_count_bucket_18 = 21; + optional int64 resume_count_bucket_19 = 22; + optional int64 resume_count_bucket_20 = 23; + optional int64 resume_count_bucket_21 = 24; + optional int64 resume_count_bucket_22 = 25; + optional int64 resume_count_bucket_23 = 26; + optional int64 resume_count_bucket_24 = 27; + optional int64 resume_count_bucket_25 = 28; + optional int64 resume_count_bucket_26 = 29; + optional int64 resume_count_bucket_27 = 30; + optional int64 resume_count_bucket_28 = 31; + optional int64 resume_count_bucket_29 = 32; + optional int64 resume_count_bucket_30 = 33; + optional int64 resume_count_bucket_31 = 34; + optional int64 resume_count_bucket_32 = 35; + optional int64 resume_count_bucket_33 = 36; + optional int64 resume_count_bucket_34 = 37; + optional int64 resume_count_bucket_35 = 38; + optional int64 resume_count_bucket_36 = 39; +} |