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
This commit is contained in:
@@ -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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
<subsystem>Alarm</subsystem>
|
||||
</device>
|
||||
<device name="test.wifi.device">
|
||||
<subsystem>undefined</subsystem>
|
||||
<subsystem>Wifi</subsystem>
|
||||
</device>
|
||||
</irq-device-map>
|
||||
@@ -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<Long> 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<SparseBooleanArray> 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<SparseBooleanArray> 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<SparseBooleanArray> 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user