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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user