From e8a76f230a125576ff4d129e627e95176bf8560c Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Thu, 2 Mar 2023 17:36:54 -0800 Subject: [PATCH] Trim unnecessary data from CpuWakeupStats Unsupported wakeups, like aborts, were taking up unnecessary memory as Wakeup objects. Also removed the raw reason string which would be redundant after it was successfully parsed into components. Also added some unit tests exercising CPU_WAKEUP_SUBSYSTEM_WIFI. Test: atest FrameworksServicesTests:CpuWakeupStatsTest Bug: 271216325 Change-Id: I7fb678586b581e380ddc0361028a0e23c653dd14 --- .../server/power/stats/CpuWakeupStats.java | 29 +++--- .../res/xml/irq_device_map_3.xml | 2 +- .../power/stats/CpuWakeupStatsTest.java | 89 +++++++++++++++---- 3 files changed, 90 insertions(+), 30 deletions(-) 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 e8c0e5924252c..706aedcbba7bc 100644 --- a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java +++ b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java @@ -126,7 +126,10 @@ public class CpuWakeupStats { /** Notes a wakeup reason as reported by SuspendControlService to battery stats. */ public synchronized void noteWakeupTimeAndReason(long elapsedRealtime, long uptime, String rawReason) { - final Wakeup parsedWakeup = new Wakeup(rawReason, elapsedRealtime, uptime); + final Wakeup parsedWakeup = Wakeup.parseWakeup(rawReason, elapsedRealtime, uptime); + if (parsedWakeup == null) { + return; + } mWakeupEvents.put(elapsedRealtime, parsedWakeup); attemptAttributionFor(parsedWakeup); // Assuming that wakeups always arrive in monotonically increasing elapsedRealtime order, @@ -451,28 +454,25 @@ public class CpuWakeupStats { private static final String PARSER_TAG = "CpuWakeupStats.Wakeup"; private static final String ABORT_REASON_PREFIX = "Abort"; private static final Pattern sIrqPattern = Pattern.compile("^(\\d+)\\s+(\\S+)"); - - String mRawReason; long mElapsedMillis; long mUptimeMillis; IrqDevice[] mDevices; - Wakeup(String rawReason, long elapsedMillis, long uptimeMillis) { - mRawReason = rawReason; + private Wakeup(IrqDevice[] devices, long elapsedMillis, long uptimeMillis) { mElapsedMillis = elapsedMillis; mUptimeMillis = uptimeMillis; - mDevices = parseIrqDevices(rawReason); + mDevices = devices; } - private static IrqDevice[] parseIrqDevices(String rawReason) { + static Wakeup parseWakeup(String rawReason, long elapsedMillis, long uptimeMillis) { final String[] components = rawReason.split(":"); if (ArrayUtils.isEmpty(components) || components[0].startsWith(ABORT_REASON_PREFIX)) { - // We don't support parsing aborts yet. + // Accounting of aborts is not supported yet. return null; } int parsedDeviceCount = 0; - IrqDevice[] parsedDevices = new IrqDevice[components.length]; + final IrqDevice[] parsedDevices = new IrqDevice[components.length]; for (String component : components) { final Matcher matcher = sIrqPattern.matcher(component.trim()); @@ -490,14 +490,17 @@ public class CpuWakeupStats { parsedDevices[parsedDeviceCount++] = new IrqDevice(line, device); } } - return (parsedDeviceCount > 0) ? Arrays.copyOf(parsedDevices, parsedDeviceCount) : null; + if (parsedDeviceCount == 0) { + return null; + } + return new Wakeup(Arrays.copyOf(parsedDevices, parsedDeviceCount), elapsedMillis, + uptimeMillis); } @Override public String toString() { return "Wakeup{" - + "mRawReason='" + mRawReason + '\'' - + ", mElapsedMillis=" + mElapsedMillis + + "mElapsedMillis=" + mElapsedMillis + ", mUptimeMillis=" + TimeUtils.formatDuration(mUptimeMillis) + ", mDevices=" + Arrays.toString(mDevices) + '}'; @@ -514,7 +517,7 @@ public class CpuWakeupStats { @Override public String toString() { - return "IrqDevice{" + "mLine=" + mLine + ", mDevice='" + mDevice + '\'' + '}'; + return "IrqDevice{" + "mLine=" + mLine + ", mDevice=\'" + mDevice + '\'' + '}'; } } } diff --git a/services/tests/servicestests/res/xml/irq_device_map_3.xml b/services/tests/servicestests/res/xml/irq_device_map_3.xml index 498b676dd1dc6..1d2a7d37d613d 100644 --- a/services/tests/servicestests/res/xml/irq_device_map_3.xml +++ b/services/tests/servicestests/res/xml/irq_device_map_3.xml @@ -21,6 +21,6 @@ Alarm - undefined + Wifi \ No newline at end of file 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 34e45c2096ea9..178670e678f09 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 @@ -18,6 +18,7 @@ package com.android.server.power.stats; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM; 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; @@ -45,6 +46,7 @@ import java.util.concurrent.ThreadLocalRandom; @RunWith(AndroidJUnit4.class) public class CpuWakeupStatsTest { private static final String KERNEL_REASON_ALARM_IRQ = "120 test.alarm.device"; + private static final String KERNEL_REASON_WIFI_IRQ = "120 test.wifi.device"; private static final String KERNEL_REASON_UNKNOWN_IRQ = "140 test.unknown.device"; private static final String KERNEL_REASON_UNKNOWN = "free-form-reason test.alarm.device"; private static final String KERNEL_REASON_UNSUPPORTED = "-1 test.alarm.device"; @@ -68,22 +70,23 @@ public class CpuWakeupStatsTest { final Set timestamps = new HashSet<>(); final long firstWakeup = 453192; - obj.noteWakeupTimeAndReason(firstWakeup, 32, "unused"); + 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); if (timestamps.add(firstWakeup + delta)) { - obj.noteWakeupTimeAndReason(firstWakeup + delta, i, "unused"); + obj.noteWakeupTimeAndReason(firstWakeup + delta, i, KERNEL_REASON_UNKNOWN_IRQ); } } assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size()); - obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 1242, 231, "unused"); + obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 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); - obj.noteWakeupTimeAndReason(now, i, "unused"); + obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ); assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - WAKEUP_RETENTION_MS)) .isLessThan(0); } @@ -111,17 +114,45 @@ public class CpuWakeupStatsTest { assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_1)).isEqualTo(false); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_2)).isEqualTo(false); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_3)).isEqualTo(true); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_4)).isEqualTo(false); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_5)).isEqualTo(true); } @Test - public void alarmIrqAttributionCombined() { + public void wifiIrqAttributionSolo() { + final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler); + final long wakeupTime = 12423121; + + obj.noteWakeupTimeAndReason(wakeupTime, 1, KERNEL_REASON_WIFI_IRQ); + + // Outside the window, so should be ignored. + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, + wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1); + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, + wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2); + // Should be attributed + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 3, TEST_UID_4, TEST_UID_5); + + final SparseArray attribution = obj.mWakeupAttribution.get(wakeupTime); + assertThat(attribution).isNotNull(); + assertThat(attribution.size()).isEqualTo(1); + assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue(); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(false); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_2)).isEqualTo(false); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(false); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_4)).isEqualTo(true); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(true); + } + + @Test + public void alarmAndWifiIrqAttribution() { final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler); final long wakeupTime = 92123210; obj.noteWakeupTimeAndReason(wakeupTime, 4, - KERNEL_REASON_UNKNOWN_IRQ + ":" + KERNEL_REASON_ALARM_IRQ); + KERNEL_REASON_WIFI_IRQ + ":" + KERNEL_REASON_ALARM_IRQ); + // Alarm activity // Outside the window, so should be ignored. obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1); @@ -132,16 +163,34 @@ public class CpuWakeupStatsTest { obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4, TEST_UID_5); + // Wifi activity + // Outside the window, so should be ignored. + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, + wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_4); + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, + wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_3); + // Should be attributed + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1); + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 1, TEST_UID_2, + TEST_UID_5); + final SparseArray attribution = obj.mWakeupAttribution.get(wakeupTime); assertThat(attribution).isNotNull(); assertThat(attribution.size()).isEqualTo(2); + assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_ALARM)).isTrue(); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_1)).isEqualTo(false); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_2)).isEqualTo(false); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_3)).isEqualTo(true); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_4)).isEqualTo(true); assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_ALARM).get(TEST_UID_5)).isEqualTo(true); - assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_UNKNOWN)).isTrue(); + + assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue(); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(true); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_2)).isEqualTo(true); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(false); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_4)).isEqualTo(false); + assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(true); } @Test @@ -151,9 +200,11 @@ public class CpuWakeupStatsTest { obj.noteWakeupTimeAndReason(wakeupTime, 24, KERNEL_REASON_UNKNOWN_IRQ); + assertThat(obj.mWakeupEvents.size()).isEqualTo(1); + // Unrelated subsystems, should not be attributed obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3); - obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4, + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 3, TEST_UID_4, TEST_UID_5); final SparseArray attribution = obj.mWakeupAttribution.get(wakeupTime); @@ -165,42 +216,48 @@ public class CpuWakeupStatsTest { } @Test - public void unknownAttribution() { + public void unknownWakeupIgnored() { final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler); final long wakeupTime = 72123210; obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNKNOWN); - // Should be ignored as this type of wakeup is unsupported. + // Should be ignored as this type of wakeup is not known. + assertThat(obj.mWakeupEvents.size()).isEqualTo(0); + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3); obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4); - // There should be nothing in the attribution map. + // Any nearby activity should not end up in the attribution map. assertThat(obj.mWakeupAttribution.size()).isEqualTo(0); } @Test - public void unsupportedAttribution() { + public void unsupportedWakeupIgnored() { final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler); long wakeupTime = 970934; obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNSUPPORTED); // Should be ignored as this type of wakeup is unsupported. + assertThat(obj.mWakeupEvents.size()).isEqualTo(0); + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3); obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 3, TEST_UID_4); - // There should be nothing in the attribution map. + // Any nearby activity should not end up in the attribution map. assertThat(obj.mWakeupAttribution.size()).isEqualTo(0); wakeupTime = 883124; obj.noteWakeupTimeAndReason(wakeupTime, 3, KERNEL_REASON_ABORT); // Should be ignored as this type of wakeup is unsupported. - obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 2, TEST_UID_1, TEST_UID_4); - obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime - 5, TEST_UID_3); + assertThat(obj.mWakeupEvents.size()).isEqualTo(0); - // There should be nothing in the attribution map. + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1, TEST_UID_4); + obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 5, TEST_UID_3); + + // Any nearby activity should not end up in the attribution map. assertThat(obj.mWakeupAttribution.size()).isEqualTo(0); } }