Merge "Enable attribution for sensor and cellular wakeups" into udc-dev

This commit is contained in:
Suprabh Shukla
2023-04-20 12:55:44 +00:00
committed by Android (Google) Code Review
6 changed files with 150 additions and 24 deletions

View File

@@ -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);

View File

@@ -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 {
}
/**
@@ -106,20 +109,17 @@ 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);
}

View File

@@ -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;
}
@@ -513,15 +517,33 @@ 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

View File

@@ -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";
}

View File

@@ -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>

View File

@@ -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";
@@ -109,6 +113,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);