Merge "Reduce unnecessary overhead in CpuWakeupStats" into udc-dev am: fd8948a928
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23207090 Change-Id: I75a27f0944914f38dcf0655d6fa0ee9ca70da8b7 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -28,6 +28,8 @@
|
|||||||
- Wifi: Use this to denote network traffic that uses the wifi transport.
|
- Wifi: Use this to denote network traffic that uses the wifi transport.
|
||||||
- Sound_trigger: Use this to denote sound phrase detection, like the ones supported by
|
- Sound_trigger: Use this to denote sound phrase detection, like the ones supported by
|
||||||
SoundTriggerManager.
|
SoundTriggerManager.
|
||||||
|
- Sensor: Use this to denote wakeups due to sensor events.
|
||||||
|
- Cellular_data: Use this to denote network traffic on the cellular transport.
|
||||||
|
|
||||||
The overlay should use tags <device> and <subsystem> to describe this mapping in the
|
The overlay should use tags <device> and <subsystem> to describe this mapping in the
|
||||||
following way:
|
following way:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ 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_UNKNOWN;
|
||||||
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
|
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -48,6 +49,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.LongSupplier;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -62,15 +64,14 @@ public class CpuWakeupStats {
|
|||||||
private static final String SUBSYSTEM_SENSOR_STRING = "Sensor";
|
private static final String SUBSYSTEM_SENSOR_STRING = "Sensor";
|
||||||
private static final String SUBSYSTEM_CELLULAR_DATA_STRING = "Cellular_data";
|
private static final String SUBSYSTEM_CELLULAR_DATA_STRING = "Cellular_data";
|
||||||
private static final String TRACE_TRACK_WAKEUP_ATTRIBUTION = "wakeup_attribution";
|
private static final String TRACE_TRACK_WAKEUP_ATTRIBUTION = "wakeup_attribution";
|
||||||
@VisibleForTesting
|
|
||||||
static final long WAKEUP_REASON_HALF_WINDOW_MS = 500;
|
|
||||||
private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.SECONDS.toMillis(30);
|
private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.SECONDS.toMillis(30);
|
||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final IrqDeviceMap mIrqDeviceMap;
|
private final IrqDeviceMap mIrqDeviceMap;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final Config mConfig = new Config();
|
final Config mConfig = new Config();
|
||||||
private final WakingActivityHistory mRecentWakingActivity = new WakingActivityHistory();
|
private final WakingActivityHistory mRecentWakingActivity;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final TimeSparseArray<Wakeup> mWakeupEvents = new TimeSparseArray<>();
|
final TimeSparseArray<Wakeup> mWakeupEvents = new TimeSparseArray<>();
|
||||||
@@ -85,6 +86,8 @@ public class CpuWakeupStats {
|
|||||||
|
|
||||||
public CpuWakeupStats(Context context, int mapRes, Handler handler) {
|
public CpuWakeupStats(Context context, int mapRes, Handler handler) {
|
||||||
mIrqDeviceMap = IrqDeviceMap.getInstance(context, mapRes);
|
mIrqDeviceMap = IrqDeviceMap.getInstance(context, mapRes);
|
||||||
|
mRecentWakingActivity = new WakingActivityHistory(
|
||||||
|
() -> mConfig.WAKING_ACTIVITY_RETENTION_MS);
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,15 +205,14 @@ public class CpuWakeupStats {
|
|||||||
/** Notes a wakeup reason as reported by SuspendControlService to battery stats. */
|
/** Notes a wakeup reason as reported by SuspendControlService to battery stats. */
|
||||||
public synchronized void noteWakeupTimeAndReason(long elapsedRealtime, long uptime,
|
public synchronized void noteWakeupTimeAndReason(long elapsedRealtime, long uptime,
|
||||||
String rawReason) {
|
String rawReason) {
|
||||||
final Wakeup parsedWakeup = Wakeup.parseWakeup(rawReason, elapsedRealtime, uptime);
|
final Wakeup parsedWakeup = Wakeup.parseWakeup(rawReason, elapsedRealtime, uptime,
|
||||||
|
mIrqDeviceMap);
|
||||||
if (parsedWakeup == null) {
|
if (parsedWakeup == null) {
|
||||||
|
// This wakeup is unsupported for attribution. Exit.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mWakeupEvents.put(elapsedRealtime, parsedWakeup);
|
mWakeupEvents.put(elapsedRealtime, parsedWakeup);
|
||||||
attemptAttributionFor(parsedWakeup);
|
attemptAttributionFor(parsedWakeup);
|
||||||
// Assuming that wakeups always arrive in monotonically increasing elapsedRealtime order,
|
|
||||||
// we can delete all history that will not be useful in attributing future wakeups.
|
|
||||||
mRecentWakingActivity.clearAllBefore(elapsedRealtime - WAKEUP_REASON_HALF_WINDOW_MS);
|
|
||||||
|
|
||||||
// Limit history of wakeups and their attribution to the last retentionDuration. Note that
|
// Limit history of wakeups and their attribution to the last retentionDuration. Note that
|
||||||
// the last wakeup and its attribution (if computed) is always stored, even if that wakeup
|
// the last wakeup and its attribution (if computed) is always stored, even if that wakeup
|
||||||
@@ -244,25 +246,22 @@ public class CpuWakeupStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void attemptAttributionFor(Wakeup wakeup) {
|
private synchronized void attemptAttributionFor(Wakeup wakeup) {
|
||||||
final SparseBooleanArray subsystems = getResponsibleSubsystemsForWakeup(wakeup);
|
final SparseBooleanArray subsystems = wakeup.mResponsibleSubsystems;
|
||||||
if (subsystems == null) {
|
|
||||||
// We don't support attribution for this kind of wakeup yet.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SparseArray<SparseIntArray> attribution = mWakeupAttribution.get(wakeup.mElapsedMillis);
|
SparseArray<SparseIntArray> attribution = mWakeupAttribution.get(wakeup.mElapsedMillis);
|
||||||
if (attribution == null) {
|
if (attribution == null) {
|
||||||
attribution = new SparseArray<>();
|
attribution = new SparseArray<>();
|
||||||
mWakeupAttribution.put(wakeup.mElapsedMillis, attribution);
|
mWakeupAttribution.put(wakeup.mElapsedMillis, attribution);
|
||||||
}
|
}
|
||||||
|
final long matchingWindowMillis = mConfig.WAKEUP_MATCHING_WINDOW_MS;
|
||||||
|
|
||||||
for (int subsystemIdx = 0; subsystemIdx < subsystems.size(); subsystemIdx++) {
|
for (int subsystemIdx = 0; subsystemIdx < subsystems.size(); subsystemIdx++) {
|
||||||
final int subsystem = subsystems.keyAt(subsystemIdx);
|
final int subsystem = subsystems.keyAt(subsystemIdx);
|
||||||
|
|
||||||
// Blame all activity that happened WAKEUP_REASON_HALF_WINDOW_MS before or after
|
// Blame all activity that happened matchingWindowMillis before or after
|
||||||
// the wakeup from each responsible subsystem.
|
// the wakeup from each responsible subsystem.
|
||||||
final long startTime = wakeup.mElapsedMillis - WAKEUP_REASON_HALF_WINDOW_MS;
|
final long startTime = wakeup.mElapsedMillis - matchingWindowMillis;
|
||||||
final long endTime = wakeup.mElapsedMillis + WAKEUP_REASON_HALF_WINDOW_MS;
|
final long endTime = wakeup.mElapsedMillis + matchingWindowMillis;
|
||||||
|
|
||||||
final SparseIntArray uidsToBlame = mRecentWakingActivity.removeBetween(subsystem,
|
final SparseIntArray uidsToBlame = mRecentWakingActivity.removeBetween(subsystem,
|
||||||
startTime, endTime);
|
startTime, endTime);
|
||||||
@@ -272,18 +271,16 @@ public class CpuWakeupStats {
|
|||||||
|
|
||||||
private synchronized boolean attemptAttributionWith(int subsystem, long activityElapsed,
|
private synchronized boolean attemptAttributionWith(int subsystem, long activityElapsed,
|
||||||
SparseIntArray uidProcStates) {
|
SparseIntArray uidProcStates) {
|
||||||
|
final long matchingWindowMillis = mConfig.WAKEUP_MATCHING_WINDOW_MS;
|
||||||
|
|
||||||
final int startIdx = mWakeupEvents.closestIndexOnOrAfter(
|
final int startIdx = mWakeupEvents.closestIndexOnOrAfter(
|
||||||
activityElapsed - WAKEUP_REASON_HALF_WINDOW_MS);
|
activityElapsed - matchingWindowMillis);
|
||||||
final int endIdx = mWakeupEvents.closestIndexOnOrBefore(
|
final int endIdx = mWakeupEvents.closestIndexOnOrBefore(
|
||||||
activityElapsed + WAKEUP_REASON_HALF_WINDOW_MS);
|
activityElapsed + matchingWindowMillis);
|
||||||
|
|
||||||
for (int wakeupIdx = startIdx; wakeupIdx <= endIdx; wakeupIdx++) {
|
for (int wakeupIdx = startIdx; wakeupIdx <= endIdx; wakeupIdx++) {
|
||||||
final Wakeup wakeup = mWakeupEvents.valueAt(wakeupIdx);
|
final Wakeup wakeup = mWakeupEvents.valueAt(wakeupIdx);
|
||||||
final SparseBooleanArray subsystems = getResponsibleSubsystemsForWakeup(wakeup);
|
final SparseBooleanArray subsystems = wakeup.mResponsibleSubsystems;
|
||||||
if (subsystems == null) {
|
|
||||||
// Unsupported for attribution
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (subsystems.get(subsystem)) {
|
if (subsystems.get(subsystem)) {
|
||||||
// We don't expect more than one wakeup to be found within such a short window, so
|
// We don't expect more than one wakeup to be found within such a short window, so
|
||||||
// just attribute this one and exit
|
// just attribute this one and exit
|
||||||
@@ -405,11 +402,13 @@ public class CpuWakeupStats {
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final class WakingActivityHistory {
|
static final class WakingActivityHistory {
|
||||||
private static final long WAKING_ACTIVITY_RETENTION_MS = TimeUnit.MINUTES.toMillis(10);
|
private LongSupplier mRetentionSupplier;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final SparseArray<TimeSparseArray<SparseIntArray>> mWakingActivity =
|
final SparseArray<TimeSparseArray<SparseIntArray>> mWakingActivity = new SparseArray<>();
|
||||||
new SparseArray<>();
|
|
||||||
|
WakingActivityHistory(LongSupplier retentionSupplier) {
|
||||||
|
mRetentionSupplier = retentionSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
void recordActivity(int subsystem, long elapsedRealtime, SparseIntArray uidProcStates) {
|
void recordActivity(int subsystem, long elapsedRealtime, SparseIntArray uidProcStates) {
|
||||||
if (uidProcStates == null) {
|
if (uidProcStates == null) {
|
||||||
@@ -433,27 +432,13 @@ public class CpuWakeupStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Limit activity history per subsystem to the last WAKING_ACTIVITY_RETENTION_MS.
|
// Limit activity history per subsystem to the last retention period as supplied by
|
||||||
// Note that the last activity is always present, even if it occurred before
|
// mRetentionSupplier. Note that the last activity is always present, even if it
|
||||||
// WAKING_ACTIVITY_RETENTION_MS.
|
// occurred before the retention period.
|
||||||
final int endIdx = wakingActivity.closestIndexOnOrBefore(
|
final int endIdx = wakingActivity.closestIndexOnOrBefore(
|
||||||
elapsedRealtime - WAKING_ACTIVITY_RETENTION_MS);
|
elapsedRealtime - mRetentionSupplier.getAsLong());
|
||||||
for (int i = endIdx; i >= 0; i--) {
|
for (int i = endIdx; i >= 0; i--) {
|
||||||
wakingActivity.removeAt(endIdx);
|
wakingActivity.removeAt(i);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearAllBefore(long elapsedRealtime) {
|
|
||||||
for (int subsystemIdx = mWakingActivity.size() - 1; subsystemIdx >= 0; subsystemIdx--) {
|
|
||||||
final TimeSparseArray<SparseIntArray> activityPerSubsystem =
|
|
||||||
mWakingActivity.valueAt(subsystemIdx);
|
|
||||||
final int endIdx = activityPerSubsystem.closestIndexOnOrBefore(elapsedRealtime);
|
|
||||||
for (int removeIdx = endIdx; removeIdx >= 0; removeIdx--) {
|
|
||||||
activityPerSubsystem.removeAt(removeIdx);
|
|
||||||
}
|
|
||||||
// Generally waking activity is a high frequency occurrence for any subsystem, so we
|
|
||||||
// don't delete the TimeSparseArray even if it is now empty, to avoid object churn.
|
|
||||||
// This will leave one TimeSparseArray per subsystem, which are few right now.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,33 +500,6 @@ public class CpuWakeupStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SparseBooleanArray getResponsibleSubsystemsForWakeup(Wakeup wakeup) {
|
|
||||||
if (ArrayUtils.isEmpty(wakeup.mDevices)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final SparseBooleanArray result = new SparseBooleanArray();
|
|
||||||
for (final Wakeup.IrqDevice device : wakeup.mDevices) {
|
|
||||||
final List<String> rawSubsystems = mIrqDeviceMap.getSubsystemsForDevice(device.mDevice);
|
|
||||||
|
|
||||||
boolean anyKnownSubsystem = false;
|
|
||||||
if (rawSubsystems != null) {
|
|
||||||
for (int i = 0; i < rawSubsystems.size(); i++) {
|
|
||||||
final int subsystem = stringToKnownSubsystem(rawSubsystems.get(i));
|
|
||||||
if (subsystem != CPU_WAKEUP_SUBSYSTEM_UNKNOWN) {
|
|
||||||
// Just in case the xml had arbitrary subsystem names, we want to make sure
|
|
||||||
// that we only put the known ones into our attribution map.
|
|
||||||
result.put(subsystem, true);
|
|
||||||
anyKnownSubsystem = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!anyKnownSubsystem) {
|
|
||||||
result.put(CPU_WAKEUP_SUBSYSTEM_UNKNOWN, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int stringToKnownSubsystem(String rawSubsystem) {
|
static int stringToKnownSubsystem(String rawSubsystem) {
|
||||||
switch (rawSubsystem) {
|
switch (rawSubsystem) {
|
||||||
case SUBSYSTEM_ALARM_STRING:
|
case SUBSYSTEM_ALARM_STRING:
|
||||||
@@ -598,15 +556,19 @@ public class CpuWakeupStats {
|
|||||||
long mElapsedMillis;
|
long mElapsedMillis;
|
||||||
long mUptimeMillis;
|
long mUptimeMillis;
|
||||||
IrqDevice[] mDevices;
|
IrqDevice[] mDevices;
|
||||||
|
SparseBooleanArray mResponsibleSubsystems;
|
||||||
|
|
||||||
private Wakeup(int type, IrqDevice[] devices, long elapsedMillis, long uptimeMillis) {
|
private Wakeup(int type, IrqDevice[] devices, long elapsedMillis, long uptimeMillis,
|
||||||
|
SparseBooleanArray responsibleSubsystems) {
|
||||||
mType = type;
|
mType = type;
|
||||||
mDevices = devices;
|
mDevices = devices;
|
||||||
mElapsedMillis = elapsedMillis;
|
mElapsedMillis = elapsedMillis;
|
||||||
mUptimeMillis = uptimeMillis;
|
mUptimeMillis = uptimeMillis;
|
||||||
|
mResponsibleSubsystems = responsibleSubsystems;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Wakeup parseWakeup(String rawReason, long elapsedMillis, long uptimeMillis) {
|
static Wakeup parseWakeup(String rawReason, long elapsedMillis, long uptimeMillis,
|
||||||
|
IrqDeviceMap deviceMap) {
|
||||||
final String[] components = rawReason.split(":");
|
final String[] components = rawReason.split(":");
|
||||||
if (ArrayUtils.isEmpty(components) || components[0].startsWith(ABORT_REASON_PREFIX)) {
|
if (ArrayUtils.isEmpty(components) || components[0].startsWith(ABORT_REASON_PREFIX)) {
|
||||||
// Accounting of aborts is not supported yet.
|
// Accounting of aborts is not supported yet.
|
||||||
@@ -616,6 +578,7 @@ public class CpuWakeupStats {
|
|||||||
int type = TYPE_IRQ;
|
int type = TYPE_IRQ;
|
||||||
int parsedDeviceCount = 0;
|
int parsedDeviceCount = 0;
|
||||||
final IrqDevice[] parsedDevices = new IrqDevice[components.length];
|
final IrqDevice[] parsedDevices = new IrqDevice[components.length];
|
||||||
|
final SparseBooleanArray responsibleSubsystems = new SparseBooleanArray();
|
||||||
|
|
||||||
for (String component : components) {
|
for (String component : components) {
|
||||||
final Matcher matcher = sIrqPattern.matcher(component.trim());
|
final Matcher matcher = sIrqPattern.matcher(component.trim());
|
||||||
@@ -635,13 +598,35 @@ public class CpuWakeupStats {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
parsedDevices[parsedDeviceCount++] = new IrqDevice(line, device);
|
parsedDevices[parsedDeviceCount++] = new IrqDevice(line, device);
|
||||||
|
|
||||||
|
final List<String> rawSubsystems = deviceMap.getSubsystemsForDevice(device);
|
||||||
|
boolean anyKnownSubsystem = false;
|
||||||
|
if (rawSubsystems != null) {
|
||||||
|
for (int i = 0; i < rawSubsystems.size(); i++) {
|
||||||
|
final int subsystem = stringToKnownSubsystem(rawSubsystems.get(i));
|
||||||
|
if (subsystem != CPU_WAKEUP_SUBSYSTEM_UNKNOWN) {
|
||||||
|
// Just in case the xml had arbitrary subsystem names, we want to
|
||||||
|
// make sure that we only put the known ones into our map.
|
||||||
|
responsibleSubsystems.put(subsystem, true);
|
||||||
|
anyKnownSubsystem = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!anyKnownSubsystem) {
|
||||||
|
responsibleSubsystems.put(CPU_WAKEUP_SUBSYSTEM_UNKNOWN, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (parsedDeviceCount == 0) {
|
if (parsedDeviceCount == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (responsibleSubsystems.size() == 1 && responsibleSubsystems.get(
|
||||||
|
CPU_WAKEUP_SUBSYSTEM_UNKNOWN, false)) {
|
||||||
|
// There is no attributable subsystem here, so we do not support it.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return new Wakeup(type, Arrays.copyOf(parsedDevices, parsedDeviceCount), elapsedMillis,
|
return new Wakeup(type, Arrays.copyOf(parsedDevices, parsedDeviceCount), elapsedMillis,
|
||||||
uptimeMillis);
|
uptimeMillis, responsibleSubsystems);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -651,6 +636,7 @@ public class CpuWakeupStats {
|
|||||||
+ ", mElapsedMillis=" + mElapsedMillis
|
+ ", mElapsedMillis=" + mElapsedMillis
|
||||||
+ ", mUptimeMillis=" + mUptimeMillis
|
+ ", mUptimeMillis=" + mUptimeMillis
|
||||||
+ ", mDevices=" + Arrays.toString(mDevices)
|
+ ", mDevices=" + Arrays.toString(mDevices)
|
||||||
|
+ ", mResponsibleSubsystems=" + mResponsibleSubsystems
|
||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,18 +658,28 @@ public class CpuWakeupStats {
|
|||||||
|
|
||||||
static final class Config implements DeviceConfig.OnPropertiesChangedListener {
|
static final class Config implements DeviceConfig.OnPropertiesChangedListener {
|
||||||
static final String KEY_WAKEUP_STATS_RETENTION_MS = "wakeup_stats_retention_ms";
|
static final String KEY_WAKEUP_STATS_RETENTION_MS = "wakeup_stats_retention_ms";
|
||||||
|
static final String KEY_WAKEUP_MATCHING_WINDOW_MS = "wakeup_matching_window_ms";
|
||||||
|
static final String KEY_WAKING_ACTIVITY_RETENTION_MS = "waking_activity_retention_ms";
|
||||||
|
|
||||||
private static final String[] PROPERTY_NAMES = {
|
private static final String[] PROPERTY_NAMES = {
|
||||||
KEY_WAKEUP_STATS_RETENTION_MS,
|
KEY_WAKEUP_STATS_RETENTION_MS,
|
||||||
|
KEY_WAKEUP_MATCHING_WINDOW_MS,
|
||||||
|
KEY_WAKING_ACTIVITY_RETENTION_MS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static final long DEFAULT_WAKEUP_STATS_RETENTION_MS = TimeUnit.DAYS.toMillis(3);
|
static final long DEFAULT_WAKEUP_STATS_RETENTION_MS = TimeUnit.DAYS.toMillis(3);
|
||||||
|
private static final long DEFAULT_WAKEUP_MATCHING_WINDOW_MS = TimeUnit.SECONDS.toMillis(1);
|
||||||
|
private static final long DEFAULT_WAKING_ACTIVITY_RETENTION_MS =
|
||||||
|
TimeUnit.MINUTES.toMillis(5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wakeup stats are retained only for this duration.
|
* Wakeup stats are retained only for this duration.
|
||||||
*/
|
*/
|
||||||
public volatile long WAKEUP_STATS_RETENTION_MS = DEFAULT_WAKEUP_STATS_RETENTION_MS;
|
public volatile long WAKEUP_STATS_RETENTION_MS = DEFAULT_WAKEUP_STATS_RETENTION_MS;
|
||||||
|
public volatile long WAKEUP_MATCHING_WINDOW_MS = DEFAULT_WAKEUP_MATCHING_WINDOW_MS;
|
||||||
|
public volatile long WAKING_ACTIVITY_RETENTION_MS = DEFAULT_WAKING_ACTIVITY_RETENTION_MS;
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
void register(Executor executor) {
|
void register(Executor executor) {
|
||||||
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_STATS,
|
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_STATS,
|
||||||
executor, this);
|
executor, this);
|
||||||
@@ -702,6 +698,15 @@ public class CpuWakeupStats {
|
|||||||
WAKEUP_STATS_RETENTION_MS = properties.getLong(
|
WAKEUP_STATS_RETENTION_MS = properties.getLong(
|
||||||
KEY_WAKEUP_STATS_RETENTION_MS, DEFAULT_WAKEUP_STATS_RETENTION_MS);
|
KEY_WAKEUP_STATS_RETENTION_MS, DEFAULT_WAKEUP_STATS_RETENTION_MS);
|
||||||
break;
|
break;
|
||||||
|
case KEY_WAKEUP_MATCHING_WINDOW_MS:
|
||||||
|
WAKEUP_MATCHING_WINDOW_MS = properties.getLong(
|
||||||
|
KEY_WAKEUP_MATCHING_WINDOW_MS, DEFAULT_WAKEUP_MATCHING_WINDOW_MS);
|
||||||
|
break;
|
||||||
|
case KEY_WAKING_ACTIVITY_RETENTION_MS:
|
||||||
|
WAKING_ACTIVITY_RETENTION_MS = properties.getLong(
|
||||||
|
KEY_WAKING_ACTIVITY_RETENTION_MS,
|
||||||
|
DEFAULT_WAKING_ACTIVITY_RETENTION_MS);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -711,7 +716,19 @@ public class CpuWakeupStats {
|
|||||||
|
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
|
|
||||||
pw.print(KEY_WAKEUP_STATS_RETENTION_MS, WAKEUP_STATS_RETENTION_MS);
|
pw.print(KEY_WAKEUP_STATS_RETENTION_MS);
|
||||||
|
pw.print("=");
|
||||||
|
TimeUtils.formatDuration(WAKEUP_STATS_RETENTION_MS, pw);
|
||||||
|
pw.println();
|
||||||
|
|
||||||
|
pw.print(KEY_WAKEUP_MATCHING_WINDOW_MS);
|
||||||
|
pw.print("=");
|
||||||
|
TimeUtils.formatDuration(WAKEUP_MATCHING_WINDOW_MS, pw);
|
||||||
|
pw.println();
|
||||||
|
|
||||||
|
pw.print(KEY_WAKING_ACTIVITY_RETENTION_MS);
|
||||||
|
pw.print("=");
|
||||||
|
TimeUtils.formatDuration(WAKING_ACTIVITY_RETENTION_MS, pw);
|
||||||
pw.println();
|
pw.println();
|
||||||
|
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ 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_UNKNOWN;
|
||||||
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
|
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
|
||||||
|
|
||||||
import static com.android.server.power.stats.wakeups.CpuWakeupStats.WAKEUP_REASON_HALF_WINDOW_MS;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -55,7 +53,7 @@ public class CpuWakeupStatsTest {
|
|||||||
private static final String KERNEL_REASON_SENSOR_IRQ = "15 test.sensor.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_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_IRQ = "140 test.unknown.device";
|
||||||
private static final String KERNEL_REASON_UNKNOWN = "free-form-reason test.alarm.device";
|
private static final String KERNEL_REASON_UNKNOWN_FORMAT = "free-form-reason test.alarm.device";
|
||||||
private static final String KERNEL_REASON_ALARM_ABNORMAL = "-1 test.alarm.device";
|
private static final String KERNEL_REASON_ALARM_ABNORMAL = "-1 test.alarm.device";
|
||||||
private static final String KERNEL_REASON_ABORT = "Abort: due to test.alarm.device";
|
private static final String KERNEL_REASON_ABORT = "Abort: due to test.alarm.device";
|
||||||
|
|
||||||
@@ -85,30 +83,29 @@ public class CpuWakeupStatsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void removesOldWakeups() {
|
public void removesOldWakeups() {
|
||||||
// The xml resource doesn't matter for this test.
|
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
|
||||||
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1, mHandler);
|
|
||||||
final long retention = obj.mConfig.WAKEUP_STATS_RETENTION_MS;
|
final long retention = obj.mConfig.WAKEUP_STATS_RETENTION_MS;
|
||||||
|
|
||||||
final Set<Long> timestamps = new HashSet<>();
|
final Set<Long> timestamps = new HashSet<>();
|
||||||
final long firstWakeup = 453192;
|
final long firstWakeup = 453192;
|
||||||
|
|
||||||
obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_UNKNOWN_IRQ);
|
// Reasons do not matter for this test, as long as they map to known subsystems
|
||||||
|
obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_ALARM_IRQ);
|
||||||
timestamps.add(firstWakeup);
|
timestamps.add(firstWakeup);
|
||||||
for (int i = 1; i < 1000; i++) {
|
for (int i = 1; i < 1000; i++) {
|
||||||
final long delta = mRandom.nextLong(retention);
|
final long delta = mRandom.nextLong(retention);
|
||||||
if (timestamps.add(firstWakeup + delta)) {
|
if (timestamps.add(firstWakeup + delta)) {
|
||||||
obj.noteWakeupTimeAndReason(firstWakeup + delta, i, KERNEL_REASON_UNKNOWN_IRQ);
|
obj.noteWakeupTimeAndReason(firstWakeup + delta, i, KERNEL_REASON_SENSOR_IRQ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
|
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
|
||||||
|
|
||||||
obj.noteWakeupTimeAndReason(firstWakeup + retention + 1242, 231,
|
obj.noteWakeupTimeAndReason(firstWakeup + retention, 231, KERNEL_REASON_WIFI_IRQ);
|
||||||
KERNEL_REASON_UNKNOWN_IRQ);
|
|
||||||
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
|
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
final long now = mRandom.nextLong(retention + 1, 100 * retention);
|
final long now = mRandom.nextLong(retention + 1, 100 * retention);
|
||||||
obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ);
|
obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_SOUND_TRIGGER_IRQ);
|
||||||
assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - retention)).isLessThan(0);
|
assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - retention)).isLessThan(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,9 +198,9 @@ public class CpuWakeupStatsTest {
|
|||||||
|
|
||||||
// Outside the window, so should be ignored.
|
// Outside the window, so should be ignored.
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
||||||
wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
|
wakeupTime - obj.mConfig.WAKEUP_MATCHING_WINDOW_MS - 1, TEST_UID_1);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
||||||
wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2);
|
wakeupTime + obj.mConfig.WAKEUP_MATCHING_WINDOW_MS + 1, TEST_UID_2);
|
||||||
// Should be attributed
|
// Should be attributed
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3, TEST_UID_5);
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3, TEST_UID_5);
|
||||||
|
|
||||||
@@ -234,9 +231,9 @@ public class CpuWakeupStatsTest {
|
|||||||
|
|
||||||
// Outside the window, so should be ignored.
|
// Outside the window, so should be ignored.
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER,
|
||||||
wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
|
wakeupTime - obj.mConfig.WAKEUP_MATCHING_WINDOW_MS - 1, TEST_UID_1);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER,
|
||||||
wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2);
|
wakeupTime + obj.mConfig.WAKEUP_MATCHING_WINDOW_MS + 1, TEST_UID_2);
|
||||||
// Should be attributed
|
// Should be attributed
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER, wakeupTime + 5, TEST_UID_3,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_SOUND_TRIGGER, wakeupTime + 5, TEST_UID_3,
|
||||||
TEST_UID_5);
|
TEST_UID_5);
|
||||||
@@ -268,9 +265,9 @@ public class CpuWakeupStatsTest {
|
|||||||
|
|
||||||
// Outside the window, so should be ignored.
|
// Outside the window, so should be ignored.
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
||||||
wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
|
wakeupTime - obj.mConfig.WAKEUP_MATCHING_WINDOW_MS - 1, TEST_UID_1);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
||||||
wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2);
|
wakeupTime + obj.mConfig.WAKEUP_MATCHING_WINDOW_MS + 1, TEST_UID_2);
|
||||||
// Should be attributed
|
// Should be attributed
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 3, TEST_UID_4, TEST_UID_5);
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 3, TEST_UID_4, TEST_UID_5);
|
||||||
|
|
||||||
@@ -300,9 +297,9 @@ public class CpuWakeupStatsTest {
|
|||||||
// Alarm activity
|
// Alarm activity
|
||||||
// Outside the window, so should be ignored.
|
// Outside the window, so should be ignored.
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
||||||
wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_1);
|
wakeupTime - obj.mConfig.WAKEUP_MATCHING_WINDOW_MS - 1, TEST_UID_1);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM,
|
||||||
wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_2);
|
wakeupTime + obj.mConfig.WAKEUP_MATCHING_WINDOW_MS + 1, TEST_UID_2);
|
||||||
// Should be attributed
|
// Should be attributed
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
|
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_ALARM, wakeupTime - 3, TEST_UID_4,
|
||||||
@@ -311,9 +308,9 @@ public class CpuWakeupStatsTest {
|
|||||||
// Wifi activity
|
// Wifi activity
|
||||||
// Outside the window, so should be ignored.
|
// Outside the window, so should be ignored.
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
||||||
wakeupTime - WAKEUP_REASON_HALF_WINDOW_MS - 1, TEST_UID_4);
|
wakeupTime - obj.mConfig.WAKEUP_MATCHING_WINDOW_MS - 1, TEST_UID_4);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
||||||
wakeupTime + WAKEUP_REASON_HALF_WINDOW_MS + 1, TEST_UID_3);
|
wakeupTime + obj.mConfig.WAKEUP_MATCHING_WINDOW_MS + 1, TEST_UID_3);
|
||||||
// Should be attributed
|
// Should be attributed
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1);
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 1, TEST_UID_2,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 1, TEST_UID_2,
|
||||||
@@ -347,33 +344,67 @@ public class CpuWakeupStatsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unknownIrqAttribution() {
|
public void unknownIrqSoloIgnored() {
|
||||||
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
|
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
|
||||||
final long wakeupTime = 92123410;
|
final long wakeupTime = 92123410;
|
||||||
|
|
||||||
obj.noteWakeupTimeAndReason(wakeupTime, 24, KERNEL_REASON_UNKNOWN_IRQ);
|
obj.noteWakeupTimeAndReason(wakeupTime, 24, KERNEL_REASON_UNKNOWN_IRQ);
|
||||||
|
|
||||||
assertThat(obj.mWakeupEvents.size()).isEqualTo(1);
|
assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
|
||||||
|
|
||||||
// Unrelated subsystems, should not be attributed
|
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
|
||||||
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 3, TEST_UID_4,
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 3, TEST_UID_4,
|
||||||
TEST_UID_5);
|
TEST_UID_5);
|
||||||
|
|
||||||
final SparseArray<SparseIntArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
|
// Any nearby activity should not end up in the attribution map.
|
||||||
assertThat(attribution).isNotNull();
|
assertThat(obj.mWakeupAttribution.size()).isEqualTo(0);
|
||||||
assertThat(attribution.size()).isEqualTo(1);
|
|
||||||
assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_UNKNOWN)).isTrue();
|
|
||||||
final SparseIntArray uidProcStates = attribution.get(CPU_WAKEUP_SUBSYSTEM_UNKNOWN);
|
|
||||||
assertThat(uidProcStates == null || uidProcStates.size() == 0).isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unknownWakeupIgnored() {
|
public void unknownAndWifiAttribution() {
|
||||||
|
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
|
||||||
|
final long wakeupTime = 92123410;
|
||||||
|
|
||||||
|
populateDefaultProcStates(obj);
|
||||||
|
|
||||||
|
obj.noteWakeupTimeAndReason(wakeupTime, 24,
|
||||||
|
KERNEL_REASON_UNKNOWN_IRQ + ":" + KERNEL_REASON_WIFI_IRQ);
|
||||||
|
|
||||||
|
// Wifi activity
|
||||||
|
// Outside the window, so should be ignored.
|
||||||
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI,
|
||||||
|
wakeupTime - obj.mConfig.WAKEUP_MATCHING_WINDOW_MS - 1, TEST_UID_4);
|
||||||
|
// Should be attributed
|
||||||
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime + 2, TEST_UID_1);
|
||||||
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_WIFI, wakeupTime - 1, TEST_UID_3,
|
||||||
|
TEST_UID_5);
|
||||||
|
|
||||||
|
// Unrelated, should be ignored.
|
||||||
|
obj.noteWakingActivity(CPU_WAKEUP_SUBSYSTEM_ALARM, wakeupTime + 5, TEST_UID_3);
|
||||||
|
|
||||||
|
final SparseArray<SparseIntArray> attribution = obj.mWakeupAttribution.get(wakeupTime);
|
||||||
|
assertThat(attribution).isNotNull();
|
||||||
|
assertThat(attribution.size()).isEqualTo(2);
|
||||||
|
assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_WIFI)).isTrue();
|
||||||
|
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_1)).isEqualTo(
|
||||||
|
TEST_PROC_STATE_1);
|
||||||
|
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).indexOfKey(TEST_UID_2)).isLessThan(0);
|
||||||
|
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_3)).isEqualTo(
|
||||||
|
TEST_PROC_STATE_3);
|
||||||
|
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).indexOfKey(TEST_UID_4)).isLessThan(0);
|
||||||
|
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_WIFI).get(TEST_UID_5)).isEqualTo(
|
||||||
|
TEST_PROC_STATE_5);
|
||||||
|
assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_UNKNOWN)).isTrue();
|
||||||
|
assertThat(attribution.get(CPU_WAKEUP_SUBSYSTEM_UNKNOWN)).isNull();
|
||||||
|
assertThat(attribution.contains(CPU_WAKEUP_SUBSYSTEM_ALARM)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unknownFormatWakeupIgnored() {
|
||||||
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
|
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
|
||||||
final long wakeupTime = 72123210;
|
final long wakeupTime = 72123210;
|
||||||
|
|
||||||
obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNKNOWN);
|
obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNKNOWN_FORMAT);
|
||||||
|
|
||||||
// Should be ignored as this type of wakeup is not known.
|
// Should be ignored as this type of wakeup is not known.
|
||||||
assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
|
assertThat(obj.mWakeupEvents.size()).isEqualTo(0);
|
||||||
|
|||||||
@@ -28,8 +28,11 @@ import com.android.server.power.stats.wakeups.CpuWakeupStats.WakingActivityHisto
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class WakingActivityHistoryTest {
|
public class WakingActivityHistoryTest {
|
||||||
|
private volatile long mTestRetention = 54;
|
||||||
|
|
||||||
private static boolean areSame(SparseIntArray a, SparseIntArray b) {
|
private static boolean areSame(SparseIntArray a, SparseIntArray b) {
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
@@ -55,7 +58,7 @@ public class WakingActivityHistoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void recordActivityAppendsUids() {
|
public void recordActivityAppendsUids() {
|
||||||
final WakingActivityHistory history = new WakingActivityHistory();
|
final WakingActivityHistory history = new WakingActivityHistory(() -> Long.MAX_VALUE);
|
||||||
final int subsystem = 42;
|
final int subsystem = 42;
|
||||||
final long timestamp = 54;
|
final long timestamp = 54;
|
||||||
|
|
||||||
@@ -100,7 +103,7 @@ public class WakingActivityHistoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void recordActivityDoesNotDeleteExistingUids() {
|
public void recordActivityDoesNotDeleteExistingUids() {
|
||||||
final WakingActivityHistory history = new WakingActivityHistory();
|
final WakingActivityHistory history = new WakingActivityHistory(() -> Long.MAX_VALUE);
|
||||||
final int subsystem = 42;
|
final int subsystem = 42;
|
||||||
long timestamp = 101;
|
long timestamp = 101;
|
||||||
|
|
||||||
@@ -151,4 +154,120 @@ public class WakingActivityHistoryTest {
|
|||||||
assertThat(recordedUids.get(62, -1)).isEqualTo(31);
|
assertThat(recordedUids.get(62, -1)).isEqualTo(31);
|
||||||
assertThat(recordedUids.get(85, -1)).isEqualTo(39);
|
assertThat(recordedUids.get(85, -1)).isEqualTo(39);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void removeBetween() {
|
||||||
|
final WakingActivityHistory history = new WakingActivityHistory(() -> Long.MAX_VALUE);
|
||||||
|
|
||||||
|
final int subsystem = 43;
|
||||||
|
|
||||||
|
final SparseIntArray uids = new SparseIntArray();
|
||||||
|
uids.put(1, 17);
|
||||||
|
uids.put(15, 2);
|
||||||
|
uids.put(62, 31);
|
||||||
|
history.recordActivity(subsystem, 123, uids);
|
||||||
|
|
||||||
|
uids.put(54, 91);
|
||||||
|
history.recordActivity(subsystem, 150, uids);
|
||||||
|
|
||||||
|
uids.put(101, 32);
|
||||||
|
uids.delete(1);
|
||||||
|
history.recordActivity(subsystem, 191, uids);
|
||||||
|
|
||||||
|
SparseIntArray removedUids = history.removeBetween(subsystem, 100, 122);
|
||||||
|
assertThat(removedUids).isNull();
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(3);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 124, 149);
|
||||||
|
assertThat(removedUids).isNull();
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(3);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 151, 190);
|
||||||
|
assertThat(removedUids).isNull();
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(3);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 192, 240);
|
||||||
|
assertThat(removedUids).isNull();
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(3);
|
||||||
|
|
||||||
|
|
||||||
|
// Removing from a different subsystem should do nothing.
|
||||||
|
removedUids = history.removeBetween(subsystem + 1, 0, 300);
|
||||||
|
assertThat(removedUids).isNull();
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(3);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 0, 300);
|
||||||
|
assertThat(removedUids.size()).isEqualTo(5);
|
||||||
|
assertThat(removedUids.get(1, -1)).isEqualTo(17);
|
||||||
|
assertThat(removedUids.get(15, -1)).isEqualTo(2);
|
||||||
|
assertThat(removedUids.get(62, -1)).isEqualTo(31);
|
||||||
|
assertThat(removedUids.get(54, -1)).isEqualTo(91);
|
||||||
|
assertThat(removedUids.get(101, -1)).isEqualTo(32);
|
||||||
|
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(0);
|
||||||
|
|
||||||
|
history.recordActivity(subsystem, 23, uids);
|
||||||
|
uids.put(31, 123);
|
||||||
|
history.recordActivity(subsystem, 49, uids);
|
||||||
|
uids.put(177, 432);
|
||||||
|
history.recordActivity(subsystem, 89, uids);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 23, 23);
|
||||||
|
assertThat(removedUids.size()).isEqualTo(4);
|
||||||
|
assertThat(removedUids.get(15, -1)).isEqualTo(2);
|
||||||
|
assertThat(removedUids.get(62, -1)).isEqualTo(31);
|
||||||
|
assertThat(removedUids.get(54, -1)).isEqualTo(91);
|
||||||
|
assertThat(removedUids.get(101, -1)).isEqualTo(32);
|
||||||
|
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(2);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 49, 54);
|
||||||
|
assertThat(removedUids.size()).isEqualTo(5);
|
||||||
|
assertThat(removedUids.get(15, -1)).isEqualTo(2);
|
||||||
|
assertThat(removedUids.get(62, -1)).isEqualTo(31);
|
||||||
|
assertThat(removedUids.get(54, -1)).isEqualTo(91);
|
||||||
|
assertThat(removedUids.get(101, -1)).isEqualTo(32);
|
||||||
|
assertThat(removedUids.get(31, -1)).isEqualTo(123);
|
||||||
|
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(1);
|
||||||
|
|
||||||
|
removedUids = history.removeBetween(subsystem, 23, 89);
|
||||||
|
assertThat(removedUids.size()).isEqualTo(6);
|
||||||
|
assertThat(removedUids.get(15, -1)).isEqualTo(2);
|
||||||
|
assertThat(removedUids.get(62, -1)).isEqualTo(31);
|
||||||
|
assertThat(removedUids.get(54, -1)).isEqualTo(91);
|
||||||
|
assertThat(removedUids.get(101, -1)).isEqualTo(32);
|
||||||
|
assertThat(removedUids.get(31, -1)).isEqualTo(123);
|
||||||
|
assertThat(removedUids.get(177, -1)).isEqualTo(432);
|
||||||
|
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deletesActivityPastRetention() {
|
||||||
|
final WakingActivityHistory history = new WakingActivityHistory(() -> mTestRetention);
|
||||||
|
final int subsystem = 49;
|
||||||
|
|
||||||
|
mTestRetention = 454;
|
||||||
|
|
||||||
|
final long firstTime = 342;
|
||||||
|
for (int i = 0; i < mTestRetention; i++) {
|
||||||
|
history.recordActivity(subsystem, firstTime + i, new SparseIntArray());
|
||||||
|
}
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem)).isNotNull();
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(mTestRetention);
|
||||||
|
|
||||||
|
history.recordActivity(subsystem, firstTime + mTestRetention + 7, new SparseIntArray());
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).size()).isEqualTo(mTestRetention - 7);
|
||||||
|
|
||||||
|
final ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final long time = random.nextLong(firstTime + mTestRetention + 100,
|
||||||
|
456 * mTestRetention);
|
||||||
|
history.recordActivity(subsystem, time, new SparseIntArray());
|
||||||
|
assertThat(history.mWakingActivity.get(subsystem).closestIndexOnOrBefore(
|
||||||
|
time - mTestRetention)).isLessThan(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user