From 2e54743a1669ce2fb49b3aa2e3dc9b0f19c4d9be Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Wed, 1 Mar 2023 01:41:47 -0800 Subject: [PATCH] Add a device config namespace for battery_stats CpuWakeupStats uses it for new settings. But existing battery_stats settings should be migrated to it later. Test: atest FrameworksServicesTests:CpuWakeupStatsTest Test: Manually inspect the output of `dumpsys batterystats --wakeups` Bug: 252903682 Change-Id: I011cf8a118fdbaafb29fba9fed349994038585e8 --- .../server/am/BatteryStatsService.java | 1 + .../server/power/stats/CpuWakeupStats.java | 81 +++++++++++++++++-- .../power/stats/CpuWakeupStatsTest.java | 11 ++- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 0ee883f745ca8..f236a961fcb6e 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -402,6 +402,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void systemServicesReady() { mStats.systemServicesReady(mContext); + mCpuWakeupStats.systemServicesReady(); mWorker.systemServicesReady(); final INetworkManagementService nms = INetworkManagementService.Stub.asInterface( ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); diff --git a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java index 706aedcbba7bc..b05b662dc1e89 100644 --- a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java +++ b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java @@ -22,7 +22,9 @@ import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI; import android.content.Context; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.UserHandle; +import android.provider.DeviceConfig; import android.util.IndentingPrintWriter; import android.util.IntArray; import android.util.LongSparseArray; @@ -40,6 +42,8 @@ import com.android.internal.util.IntPair; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -52,13 +56,13 @@ public class CpuWakeupStats { private static final String SUBSYSTEM_ALARM_STRING = "Alarm"; private static final String SUBSYSTEM_ALARM_WIFI = "Wifi"; @VisibleForTesting - static final long WAKEUP_RETENTION_MS = 3 * 24 * 60 * 60_000; // 3 days. - @VisibleForTesting static final long WAKEUP_REASON_HALF_WINDOW_MS = 500; - private static final long WAKEUP_WRITE_DELAY_MS = 2 * 60 * 1000; // 2 minutes. + private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.MINUTES.toMillis(2); private final Handler mHandler; private final IrqDeviceMap mIrqDeviceMap; + @VisibleForTesting + final Config mConfig = new Config(); private final WakingActivityHistory mRecentWakingActivity = new WakingActivityHistory(); @VisibleForTesting @@ -72,6 +76,14 @@ public class CpuWakeupStats { mHandler = handler; } + /** + * Called on the boot phase SYSTEM_SERVICES_READY. + * This ensures that DeviceConfig is ready for calls to read properties. + */ + public synchronized void systemServicesReady() { + mConfig.register(new HandlerExecutor(mHandler)); + } + private static int subsystemToStatsReason(int subsystem) { switch (subsystem) { case CPU_WAKEUP_SUBSYSTEM_ALARM: @@ -136,14 +148,15 @@ public class CpuWakeupStats { // we can delete all history that will not be useful in attributing future wakeups. mRecentWakingActivity.clearAllBefore(elapsedRealtime - WAKEUP_REASON_HALF_WINDOW_MS); - // Limit history of wakeups and their attribution to the last WAKEUP_RETENTION_MS. Note that + // Limit history of wakeups and their attribution to the last retentionDuration. Note that // the last wakeup and its attribution (if computed) is always stored, even if that wakeup - // had occurred before WAKEUP_RETENTION_MS. - int lastIdx = mWakeupEvents.closestIndexOnOrBefore(elapsedRealtime - WAKEUP_RETENTION_MS); + // had occurred before retentionDuration. + final long retentionDuration = mConfig.WAKEUP_STATS_RETENTION_MS; + int lastIdx = mWakeupEvents.closestIndexOnOrBefore(elapsedRealtime - retentionDuration); for (int i = lastIdx; i >= 0; i--) { mWakeupEvents.removeAt(i); } - lastIdx = mWakeupAttribution.closestIndexOnOrBefore(elapsedRealtime - WAKEUP_RETENTION_MS); + lastIdx = mWakeupAttribution.closestIndexOnOrBefore(elapsedRealtime - retentionDuration); for (int i = lastIdx; i >= 0; i--) { mWakeupAttribution.removeAt(i); } @@ -226,6 +239,9 @@ public class CpuWakeupStats { pw.println("CPU wakeup stats:"); pw.increaseIndent(); + mConfig.dump(pw); + pw.println(); + mIrqDeviceMap.dump(pw); pw.println(); @@ -296,7 +312,8 @@ public class CpuWakeupStats { } private static final class WakingActivityHistory { - private static final long WAKING_ACTIVITY_RETENTION_MS = 3 * 60 * 60_000; // 3 hours. + private static final long WAKING_ACTIVITY_RETENTION_MS = TimeUnit.MINUTES.toMillis(10); + private SparseArray> mWakingActivity = new SparseArray<>(); @@ -521,4 +538,52 @@ public class CpuWakeupStats { } } } + + static final class Config implements DeviceConfig.OnPropertiesChangedListener { + static final String KEY_WAKEUP_STATS_RETENTION_MS = "wakeup_stats_retention_ms"; + + private static final String[] PROPERTY_NAMES = { + KEY_WAKEUP_STATS_RETENTION_MS, + }; + + static final long DEFAULT_WAKEUP_STATS_RETENTION_MS = TimeUnit.DAYS.toMillis(3); + + /** + * Wakeup stats are retained only for this duration. + */ + public volatile long WAKEUP_STATS_RETENTION_MS = DEFAULT_WAKEUP_STATS_RETENTION_MS; + + void register(Executor executor) { + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_STATS, + executor, this); + onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_STATS, + PROPERTY_NAMES)); + } + + @Override + public void onPropertiesChanged(DeviceConfig.Properties properties) { + for (String name : properties.getKeyset()) { + if (name == null) { + continue; + } + switch (name) { + case KEY_WAKEUP_STATS_RETENTION_MS: + WAKEUP_STATS_RETENTION_MS = properties.getLong( + KEY_WAKEUP_STATS_RETENTION_MS, DEFAULT_WAKEUP_STATS_RETENTION_MS); + break; + } + } + } + + void dump(IndentingPrintWriter pw) { + pw.println("Config:"); + + pw.increaseIndent(); + + pw.print(KEY_WAKEUP_STATS_RETENTION_MS, WAKEUP_STATS_RETENTION_MS); + pw.println(); + + pw.decreaseIndent(); + } + } } diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java index 178670e678f09..397d7b5f2a3e8 100644 --- a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java +++ b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java @@ -21,7 +21,6 @@ import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI; import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_REASON_HALF_WINDOW_MS; -import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_RETENTION_MS; import static com.google.common.truth.Truth.assertThat; @@ -66,6 +65,7 @@ public class CpuWakeupStatsTest { public void removesOldWakeups() { // The xml resource doesn't matter for this test. final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1, mHandler); + final long retention = obj.mConfig.WAKEUP_STATS_RETENTION_MS; final Set timestamps = new HashSet<>(); final long firstWakeup = 453192; @@ -73,22 +73,21 @@ public class CpuWakeupStatsTest { obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_UNKNOWN_IRQ); timestamps.add(firstWakeup); for (int i = 1; i < 1000; i++) { - final long delta = mRandom.nextLong(WAKEUP_RETENTION_MS); + final long delta = mRandom.nextLong(retention); if (timestamps.add(firstWakeup + delta)) { obj.noteWakeupTimeAndReason(firstWakeup + delta, i, KERNEL_REASON_UNKNOWN_IRQ); } } assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size()); - obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 1242, 231, + obj.noteWakeupTimeAndReason(firstWakeup + retention + 1242, 231, KERNEL_REASON_UNKNOWN_IRQ); assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size()); for (int i = 0; i < 100; i++) { - final long now = mRandom.nextLong(WAKEUP_RETENTION_MS + 1, 100 * WAKEUP_RETENTION_MS); + final long now = mRandom.nextLong(retention + 1, 100 * retention); obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ); - assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - WAKEUP_RETENTION_MS)) - .isLessThan(0); + assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - retention)).isLessThan(0); } }