diff options
| author | 2023-04-14 17:23:22 -0700 | |
|---|---|---|
| committer | 2023-04-19 19:02:23 -0700 | |
| commit | 4ed309b32275a13e44db23b3c250da91d429072b (patch) | |
| tree | daab6f6d42f3f49bc5d42fe5fce3884e65569e2a | |
| parent | d43a6541a3fe13ad22d35a9bcc6830adf278fd7e (diff) | |
Enable attribution for sensor and cellular wakeups
Sensor wakeup events are already being reported to batterystats.
For cellular, the code in network stack will be enabled independently.
Test: atest FrameworksServicesTests:CpuWakeupStatsTest
Test: statsd_testdrive -e 588
Bug: 276498460
Bug: 275436924
Change-Id: I1fc925193b4f0e3713d29de552138287c9a9768e
6 files changed, 150 insertions, 24 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 3772960e8ac4..df1b66612ea2 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -4873,8 +4873,7 @@ public class AlarmManagerService extends SystemService { } } if (wakeupUids.size() > 0 && mBatteryStatsInternal != null) { - mBatteryStatsInternal.noteCpuWakingActivity( - BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM, nowELAPSED, + mBatteryStatsInternal.noteWakingAlarmBatch(nowELAPSED, wakeupUids.toArray()); } deliverAlarmsLocked(triggerList, nowELAPSED); diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java index 12ee13183221..0713999d4354 100644 --- a/services/core/java/android/os/BatteryStatsInternal.java +++ b/services/core/java/android/os/BatteryStatsInternal.java @@ -17,7 +17,6 @@ package android.os; import android.annotation.IntDef; -import android.annotation.NonNull; import android.net.Network; import com.android.internal.os.BinderCallsStats; @@ -40,6 +39,8 @@ public abstract class BatteryStatsInternal { public static final int CPU_WAKEUP_SUBSYSTEM_ALARM = 1; public static final int CPU_WAKEUP_SUBSYSTEM_WIFI = 2; public static final int CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER = 3; + public static final int CPU_WAKEUP_SUBSYSTEM_SENSOR = 4; + public static final int CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA = 5; /** @hide */ @IntDef(prefix = {"CPU_WAKEUP_SUBSYSTEM_"}, value = { @@ -47,9 +48,11 @@ public abstract class BatteryStatsInternal { CPU_WAKEUP_SUBSYSTEM_ALARM, CPU_WAKEUP_SUBSYSTEM_WIFI, CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER, + CPU_WAKEUP_SUBSYSTEM_SENSOR, + CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA, }) @Retention(RetentionPolicy.SOURCE) - @interface CpuWakeupSubsystem { + public @interface CpuWakeupSubsystem { } /** @@ -107,19 +110,16 @@ public abstract class BatteryStatsInternal { public abstract void noteBinderThreadNativeIds(int[] binderThreadNativeTids); /** - * Reports any activity that could potentially have caused the CPU to wake up. - * Accepts a timestamp to allow free ordering between the event and its reporting. - * @param subsystem The subsystem this activity should be attributed to. - * @param elapsedMillis The time when this activity happened in the elapsed timebase. - * @param uids The uid (or uids) that should be blamed for this activity. - */ - public abstract void noteCpuWakingActivity(@CpuWakeupSubsystem int subsystem, - long elapsedMillis, @NonNull int... uids); - - /** * Reports a sound trigger recognition event that may have woken up the CPU. * @param elapsedMillis The time when the event happened in the elapsed timebase. * @param uid The uid that requested this trigger. */ public abstract void noteWakingSoundTrigger(long elapsedMillis, int uid); + + /** + * Reports an alarm batch that would have woken up the CPU. + * @param elapsedMillis The time at which this alarm batch was scheduled to go off. + * @param uids the uids of all apps that have any alarm in this batch. + */ + public abstract void noteWakingAlarmBatch(long elapsedMillis, int... uids); } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index c0b3a90d923b..d140403f77c3 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -23,6 +23,7 @@ import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.POWER_SAVER; import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; @@ -51,6 +52,7 @@ import android.os.BatteryConsumer; import android.os.BatteryManagerInternal; import android.os.BatteryStats; import android.os.BatteryStatsInternal; +import android.os.BatteryStatsInternal.CpuWakeupSubsystem; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.Binder; @@ -474,6 +476,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub private int transportToSubsystem(NetworkCapabilities nc) { if (nc.hasTransport(TRANSPORT_WIFI)) { return CPU_WAKEUP_SUBSYSTEM_WIFI; + } else if (nc.hasTransport(TRANSPORT_CELLULAR)) { + return CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA; } return CPU_WAKEUP_SUBSYSTEM_UNKNOWN; } @@ -514,14 +518,32 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override - public void noteCpuWakingActivity(int subsystem, long elapsedMillis, int... uids) { - Objects.requireNonNull(uids); - mHandler.post(() -> mCpuWakeupStats.noteWakingActivity(subsystem, elapsedMillis, uids)); - } - @Override public void noteWakingSoundTrigger(long elapsedMillis, int uid) { noteCpuWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER, elapsedMillis, uid); } + + @Override + public void noteWakingAlarmBatch(long elapsedMillis, int... uids) { + noteCpuWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, elapsedMillis, uids); + } + } + + /** + * Reports any activity that could potentially have caused the CPU to wake up. + * Accepts a timestamp to allow free ordering between the event and its reporting. + * + * <p> + * This method can be called multiple times for the same wakeup and then all attribution + * reported will be unioned as long as all reports are made within a small amount of cpu uptime + * after the wakeup is reported to batterystats. + * + * @param subsystem The subsystem this activity should be attributed to. + * @param elapsedMillis The time when this activity happened in the elapsed timebase. + * @param uids The uid (or uids) that should be blamed for this activity. + */ + void noteCpuWakingActivity(@CpuWakeupSubsystem int subsystem, long elapsedMillis, int... uids) { + Objects.requireNonNull(uids); + mHandler.post(() -> mCpuWakeupStats.noteWakingActivity(subsystem, elapsedMillis, uids)); } @Override @@ -1267,6 +1289,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub if (callingUid != Process.SYSTEM_UID) { throw new SecurityException("Calling uid " + callingUid + " is not system uid"); } + final long elapsedMillis = TimeUnit.NANOSECONDS.toMillis(elapsedNanos); final SensorManager sm = mContext.getSystemService(SensorManager.class); final Sensor sensor = sm.getSensorByHandle(sensorHandle); @@ -1275,10 +1298,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub + " received in noteWakeupSensorEvent"); return; } - Slog.i(TAG, "Sensor " + sensor + " wakeup event at " + elapsedNanos + " sent to uid " - + uid); - // TODO (b/275436924): Remove log and pipe to CpuWakeupStats for wakeup attribution - // This method should return as quickly as possible. Use mHandler#post to do longer work. + if (uid < 0) { + Slog.wtf(TAG, "Invalid uid " + uid + " for sensor event with sensor: " + sensor); + return; + } + // TODO (b/278319756): Also pipe in Sensor type for more usefulness. + noteCpuWakingActivity(BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_SENSOR, elapsedMillis, uid); } @Override diff --git a/services/core/java/com/android/server/power/stats/wakeups/CpuWakeupStats.java b/services/core/java/com/android/server/power/stats/wakeups/CpuWakeupStats.java index 1d63489f3c4f..eb6d28e76ff8 100644 --- a/services/core/java/com/android/server/power/stats/wakeups/CpuWakeupStats.java +++ b/services/core/java/com/android/server/power/stats/wakeups/CpuWakeupStats.java @@ -17,6 +17,8 @@ package com.android.server.power.stats.wakeups; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM; +import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA; +import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_SENSOR; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI; @@ -54,10 +56,11 @@ import java.util.regex.Pattern; */ public class CpuWakeupStats { private static final String TAG = "CpuWakeupStats"; - private static final String SUBSYSTEM_ALARM_STRING = "Alarm"; private static final String SUBSYSTEM_WIFI_STRING = "Wifi"; private static final String SUBSYSTEM_SOUND_TRIGGER_STRING = "Sound_trigger"; + private static final String SUBSYSTEM_SENSOR_STRING = "Sensor"; + private static final String SUBSYSTEM_CELLULAR_DATA_STRING = "Cellular_data"; private static final String TRACE_TRACK_WAKEUP_ATTRIBUTION = "wakeup_attribution"; @VisibleForTesting static final long WAKEUP_REASON_HALF_WINDOW_MS = 500; @@ -111,6 +114,10 @@ public class CpuWakeupStats { return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__WIFI; case CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER: return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__SOUND_TRIGGER; + case CPU_WAKEUP_SUBSYSTEM_SENSOR: + return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__SENSOR; + case CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA: + return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__CELLULAR_DATA; } return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN; } @@ -542,6 +549,10 @@ public class CpuWakeupStats { return CPU_WAKEUP_SUBSYSTEM_WIFI; case SUBSYSTEM_SOUND_TRIGGER_STRING: return CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER; + case SUBSYSTEM_SENSOR_STRING: + return CPU_WAKEUP_SUBSYSTEM_SENSOR; + case SUBSYSTEM_CELLULAR_DATA_STRING: + return CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA; } return CPU_WAKEUP_SUBSYSTEM_UNKNOWN; } @@ -554,6 +565,10 @@ public class CpuWakeupStats { return SUBSYSTEM_WIFI_STRING; case CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER: return SUBSYSTEM_SOUND_TRIGGER_STRING; + case CPU_WAKEUP_SUBSYSTEM_SENSOR: + return SUBSYSTEM_SENSOR_STRING; + case CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA: + return SUBSYSTEM_CELLULAR_DATA_STRING; case CPU_WAKEUP_SUBSYSTEM_UNKNOWN: return "Unknown"; } 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 7e2529aa0090..fd55428c48df 100644 --- a/services/tests/servicestests/res/xml/irq_device_map_3.xml +++ b/services/tests/servicestests/res/xml/irq_device_map_3.xml @@ -26,4 +26,10 @@ <device name="test.sound_trigger.device"> <subsystem>Sound_trigger</subsystem> </device> + <device name="test.cellular_data.device"> + <subsystem>Cellular_data</subsystem> + </device> + <device name="test.sensor.device"> + <subsystem>Sensor</subsystem> + </device> </irq-device-map>
\ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java b/services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java index dca67d6da7ad..76b6a820e4a7 100644 --- a/services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java +++ b/services/tests/servicestests/src/com/android/server/power/stats/wakeups/CpuWakeupStatsTest.java @@ -17,6 +17,8 @@ package com.android.server.power.stats.wakeups; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_ALARM; +import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA; +import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_SENSOR; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN; import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI; @@ -50,6 +52,8 @@ public class CpuWakeupStatsTest { private static final String KERNEL_REASON_ALARM_IRQ = "120 test.alarm.device"; private static final String KERNEL_REASON_WIFI_IRQ = "130 test.wifi.device"; private static final String KERNEL_REASON_SOUND_TRIGGER_IRQ = "129 test.sound_trigger.device"; + private static final String KERNEL_REASON_SENSOR_IRQ = "15 test.sensor.device"; + private static final String KERNEL_REASON_CELLULAR_DATA_IRQ = "18 test.cellular_data.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_ALARM_ABNORMAL = "-1 test.alarm.device"; @@ -110,6 +114,83 @@ public class CpuWakeupStatsTest { } @Test + public void irqAttributionAllCombinations() { + final int[] subsystems = new int[] { + CPU_WAKEUP_SUBSYSTEM_ALARM, + CPU_WAKEUP_SUBSYSTEM_WIFI, + CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER, + CPU_WAKEUP_SUBSYSTEM_SENSOR, + CPU_WAKEUP_SUBSYSTEM_CELLULAR_DATA, + }; + + final String[] kernelReasons = new String[] { + KERNEL_REASON_ALARM_IRQ, + KERNEL_REASON_WIFI_IRQ, + KERNEL_REASON_SOUND_TRIGGER_IRQ, + KERNEL_REASON_SENSOR_IRQ, + KERNEL_REASON_CELLULAR_DATA_IRQ, + }; + + final int[] uids = new int[] { + TEST_UID_2, TEST_UID_3, TEST_UID_4, TEST_UID_1, TEST_UID_5 + }; + + final int[] procStates = new int[] { + TEST_PROC_STATE_2, + TEST_PROC_STATE_3, + TEST_PROC_STATE_4, + TEST_PROC_STATE_1, + TEST_PROC_STATE_5 + }; + + final int total = subsystems.length; + assertThat(kernelReasons.length).isEqualTo(total); + assertThat(uids.length).isEqualTo(total); + assertThat(procStates.length).isEqualTo(total); + + for (int mask = 1; mask < (1 << total); mask++) { + final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, + mHandler); + populateDefaultProcStates(obj); + + final long wakeupTime = mRandom.nextLong(123456); + + String combinedKernelReason = null; + for (int i = 0; i < total; i++) { + if ((mask & (1 << i)) != 0) { + combinedKernelReason = (combinedKernelReason == null) + ? kernelReasons[i] + : String.join(":", combinedKernelReason, kernelReasons[i]); + } + + obj.noteWakingActivity(subsystems[i], wakeupTime + 2, uids[i]); + } + obj.noteWakeupTimeAndReason(wakeupTime, 1, combinedKernelReason); + + assertThat(obj.mWakeupAttribution.size()).isEqualTo(1); + + final SparseArray<SparseIntArray> attribution = obj.mWakeupAttribution.get(wakeupTime); + assertThat(attribution.size()).isEqualTo(Integer.bitCount(mask)); + + for (int i = 0; i < total; i++) { + if ((mask & (1 << i)) == 0) { + assertThat(attribution.contains(subsystems[i])).isFalse(); + continue; + } + assertThat(attribution.contains(subsystems[i])).isTrue(); + assertThat(attribution.get(subsystems[i]).get(uids[i])).isEqualTo(procStates[i]); + + for (int j = 0; j < total; j++) { + if (i == j) { + continue; + } + assertThat(attribution.get(subsystems[i]).indexOfKey(uids[j])).isLessThan(0); + } + } + } + } + + @Test public void alarmIrqAttributionSolo() { final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler); final long wakeupTime = 12423121; |