summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pixelstats/SysfsCollector.cpp102
-rw-r--r--pixelstats/include/pixelstats/SysfsCollector.h9
-rw-r--r--pixelstats/pixelatoms.proto53
3 files changed, 162 insertions, 2 deletions
diff --git a/pixelstats/SysfsCollector.cpp b/pixelstats/SysfsCollector.cpp
index 698644f..203ff0f 100644
--- a/pixelstats/SysfsCollector.cpp
+++ b/pixelstats/SysfsCollector.cpp
@@ -56,6 +56,7 @@ using android::hardware::google::pixel::PixelAtoms::VendorAudioHardwareStatsRepo
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;
@@ -93,7 +94,8 @@ SysfsCollector::SysfsCollector(const struct SysfsPaths &sysfs_paths)
kThermalStatsPaths(sysfs_paths.ThermalStatsPaths),
kCCARatePath(sysfs_paths.CCARatePath),
kTempResidencyPath(sysfs_paths.TempResidencyPath),
- kLongIRQMetricsPath(sysfs_paths.LongIRQMetricsPath) {}
+ kLongIRQMetricsPath(sysfs_paths.LongIRQMetricsPath),
+ kResumeLatencyMetricsPath(sysfs_paths.ResumeLatencyMetricsPath) {}
bool SysfsCollector::ReadFileToInt(const std::string &path, int *val) {
return ReadFileToInt(path.c_str(), val);
@@ -1052,6 +1054,103 @@ 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;
}
@@ -1210,6 +1309,7 @@ void SysfsCollector::logPerDay() {
logThermalStats(stats_client);
logTempResidencyStats(stats_client);
logVendorLongIRQStatsReported(stats_client);
+ logVendorResumeLatencyStats(stats_client);
}
void SysfsCollector::aggregatePer5Min() {
diff --git a/pixelstats/include/pixelstats/SysfsCollector.h b/pixelstats/include/pixelstats/SysfsCollector.h
index e0aef81..df4a331 100644
--- a/pixelstats/include/pixelstats/SysfsCollector.h
+++ b/pixelstats/include/pixelstats/SysfsCollector.h
@@ -68,6 +68,7 @@ class SysfsCollector {
const char *const CCARatePath;
const char *const TempResidencyPath;
const char *const LongIRQMetricsPath;
+ const char *const ResumeLatencyMetricsPath;
};
SysfsCollector(const struct SysfsPaths &paths);
@@ -109,6 +110,7 @@ class SysfsCollector {
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;
@@ -139,6 +141,7 @@ class SysfsCollector {
const char *const kCCARatePath;
const char *const kTempResidencyPath;
const char *const kLongIRQMetricsPath;
+ const char *const kResumeLatencyMetricsPath;
BatteryEEPROMReporter battery_EEPROM_reporter_;
MmMetricsReporter mm_metrics_reporter_;
@@ -153,11 +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/pixelatoms.proto b/pixelstats/pixelatoms.proto
index 9e9c83e..33796c7 100644
--- a/pixelstats/pixelatoms.proto
+++ b/pixelstats/pixelatoms.proto
@@ -85,6 +85,7 @@ message Atom {
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
@@ -1291,7 +1292,7 @@ message VendorAudioHardwareStatsReported {
* Stats include top 5 slowest IRQs: their numbers and the worst latency.
* Stats are reset after every report.
*/
- message VendorLongIRQStatsReported {
+message VendorLongIRQStatsReported {
optional string reverse_domain_name = 1;
// Count of long soft IRQ since last report.
@@ -1360,3 +1361,53 @@ message VendorTempResidencyStats {
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;
+}