Merge "Add a device config namespace for battery_stats" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
01d61c389a
@@ -402,6 +402,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
|
|
||||||
public void systemServicesReady() {
|
public void systemServicesReady() {
|
||||||
mStats.systemServicesReady(mContext);
|
mStats.systemServicesReady(mContext);
|
||||||
|
mCpuWakeupStats.systemServicesReady();
|
||||||
mWorker.systemServicesReady();
|
mWorker.systemServicesReady();
|
||||||
final INetworkManagementService nms = INetworkManagementService.Stub.asInterface(
|
final INetworkManagementService nms = INetworkManagementService.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
|
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_WIFI;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerExecutor;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.IntArray;
|
import android.util.IntArray;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
@@ -40,6 +42,8 @@ import com.android.internal.util.IntPair;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -52,13 +56,13 @@ public class CpuWakeupStats {
|
|||||||
private static final String SUBSYSTEM_ALARM_STRING = "Alarm";
|
private static final String SUBSYSTEM_ALARM_STRING = "Alarm";
|
||||||
private static final String SUBSYSTEM_ALARM_WIFI = "Wifi";
|
private static final String SUBSYSTEM_ALARM_WIFI = "Wifi";
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final long WAKEUP_RETENTION_MS = 3 * 24 * 60 * 60_000; // 3 days.
|
|
||||||
@VisibleForTesting
|
|
||||||
static final long WAKEUP_REASON_HALF_WINDOW_MS = 500;
|
static final long WAKEUP_REASON_HALF_WINDOW_MS = 500;
|
||||||
private static final long WAKEUP_WRITE_DELAY_MS = 2 * 60 * 1000; // 2 minutes.
|
private static final long WAKEUP_WRITE_DELAY_MS = TimeUnit.MINUTES.toMillis(2);
|
||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final IrqDeviceMap mIrqDeviceMap;
|
private final IrqDeviceMap mIrqDeviceMap;
|
||||||
|
@VisibleForTesting
|
||||||
|
final Config mConfig = new Config();
|
||||||
private final WakingActivityHistory mRecentWakingActivity = new WakingActivityHistory();
|
private final WakingActivityHistory mRecentWakingActivity = new WakingActivityHistory();
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -72,6 +76,14 @@ public class CpuWakeupStats {
|
|||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on the boot phase SYSTEM_SERVICES_READY.
|
||||||
|
* This ensures that DeviceConfig is ready for calls to read properties.
|
||||||
|
*/
|
||||||
|
public synchronized void systemServicesReady() {
|
||||||
|
mConfig.register(new HandlerExecutor(mHandler));
|
||||||
|
}
|
||||||
|
|
||||||
private static int subsystemToStatsReason(int subsystem) {
|
private static int subsystemToStatsReason(int subsystem) {
|
||||||
switch (subsystem) {
|
switch (subsystem) {
|
||||||
case CPU_WAKEUP_SUBSYSTEM_ALARM:
|
case CPU_WAKEUP_SUBSYSTEM_ALARM:
|
||||||
@@ -136,14 +148,15 @@ public class CpuWakeupStats {
|
|||||||
// we can delete all history that will not be useful in attributing future wakeups.
|
// we can delete all history that will not be useful in attributing future wakeups.
|
||||||
mRecentWakingActivity.clearAllBefore(elapsedRealtime - WAKEUP_REASON_HALF_WINDOW_MS);
|
mRecentWakingActivity.clearAllBefore(elapsedRealtime - WAKEUP_REASON_HALF_WINDOW_MS);
|
||||||
|
|
||||||
// Limit history of wakeups and their attribution to the last WAKEUP_RETENTION_MS. 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
|
||||||
// had occurred before WAKEUP_RETENTION_MS.
|
// had occurred before retentionDuration.
|
||||||
int lastIdx = mWakeupEvents.closestIndexOnOrBefore(elapsedRealtime - WAKEUP_RETENTION_MS);
|
final long retentionDuration = mConfig.WAKEUP_STATS_RETENTION_MS;
|
||||||
|
int lastIdx = mWakeupEvents.closestIndexOnOrBefore(elapsedRealtime - retentionDuration);
|
||||||
for (int i = lastIdx; i >= 0; i--) {
|
for (int i = lastIdx; i >= 0; i--) {
|
||||||
mWakeupEvents.removeAt(i);
|
mWakeupEvents.removeAt(i);
|
||||||
}
|
}
|
||||||
lastIdx = mWakeupAttribution.closestIndexOnOrBefore(elapsedRealtime - WAKEUP_RETENTION_MS);
|
lastIdx = mWakeupAttribution.closestIndexOnOrBefore(elapsedRealtime - retentionDuration);
|
||||||
for (int i = lastIdx; i >= 0; i--) {
|
for (int i = lastIdx; i >= 0; i--) {
|
||||||
mWakeupAttribution.removeAt(i);
|
mWakeupAttribution.removeAt(i);
|
||||||
}
|
}
|
||||||
@@ -226,6 +239,9 @@ public class CpuWakeupStats {
|
|||||||
pw.println("CPU wakeup stats:");
|
pw.println("CPU wakeup stats:");
|
||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
|
|
||||||
|
mConfig.dump(pw);
|
||||||
|
pw.println();
|
||||||
|
|
||||||
mIrqDeviceMap.dump(pw);
|
mIrqDeviceMap.dump(pw);
|
||||||
pw.println();
|
pw.println();
|
||||||
|
|
||||||
@@ -296,7 +312,8 @@ public class CpuWakeupStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class WakingActivityHistory {
|
private static final class WakingActivityHistory {
|
||||||
private static final long WAKING_ACTIVITY_RETENTION_MS = 3 * 60 * 60_000; // 3 hours.
|
private static final long WAKING_ACTIVITY_RETENTION_MS = TimeUnit.MINUTES.toMillis(10);
|
||||||
|
|
||||||
private SparseArray<TimeSparseArray<SparseBooleanArray>> mWakingActivity =
|
private SparseArray<TimeSparseArray<SparseBooleanArray>> mWakingActivity =
|
||||||
new SparseArray<>();
|
new SparseArray<>();
|
||||||
|
|
||||||
@@ -521,4 +538,52 @@ public class CpuWakeupStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class Config implements DeviceConfig.OnPropertiesChangedListener {
|
||||||
|
static final String KEY_WAKEUP_STATS_RETENTION_MS = "wakeup_stats_retention_ms";
|
||||||
|
|
||||||
|
private static final String[] PROPERTY_NAMES = {
|
||||||
|
KEY_WAKEUP_STATS_RETENTION_MS,
|
||||||
|
};
|
||||||
|
|
||||||
|
static final long DEFAULT_WAKEUP_STATS_RETENTION_MS = TimeUnit.DAYS.toMillis(3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wakeup stats are retained only for this duration.
|
||||||
|
*/
|
||||||
|
public volatile long WAKEUP_STATS_RETENTION_MS = DEFAULT_WAKEUP_STATS_RETENTION_MS;
|
||||||
|
|
||||||
|
void register(Executor executor) {
|
||||||
|
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_STATS,
|
||||||
|
executor, this);
|
||||||
|
onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_STATS,
|
||||||
|
PROPERTY_NAMES));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPropertiesChanged(DeviceConfig.Properties properties) {
|
||||||
|
for (String name : properties.getKeyset()) {
|
||||||
|
if (name == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (name) {
|
||||||
|
case KEY_WAKEUP_STATS_RETENTION_MS:
|
||||||
|
WAKEUP_STATS_RETENTION_MS = properties.getLong(
|
||||||
|
KEY_WAKEUP_STATS_RETENTION_MS, DEFAULT_WAKEUP_STATS_RETENTION_MS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(IndentingPrintWriter pw) {
|
||||||
|
pw.println("Config:");
|
||||||
|
|
||||||
|
pw.increaseIndent();
|
||||||
|
|
||||||
|
pw.print(KEY_WAKEUP_STATS_RETENTION_MS, WAKEUP_STATS_RETENTION_MS);
|
||||||
|
pw.println();
|
||||||
|
|
||||||
|
pw.decreaseIndent();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ 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.CpuWakeupStats.WAKEUP_REASON_HALF_WINDOW_MS;
|
import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_REASON_HALF_WINDOW_MS;
|
||||||
import static com.android.server.power.stats.CpuWakeupStats.WAKEUP_RETENTION_MS;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
@@ -66,6 +65,7 @@ public class CpuWakeupStatsTest {
|
|||||||
public void removesOldWakeups() {
|
public void removesOldWakeups() {
|
||||||
// The xml resource doesn't matter for this test.
|
// The xml resource doesn't matter for this test.
|
||||||
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1, mHandler);
|
final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1, mHandler);
|
||||||
|
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;
|
||||||
@@ -73,22 +73,21 @@ public class CpuWakeupStatsTest {
|
|||||||
obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_UNKNOWN_IRQ);
|
obj.noteWakeupTimeAndReason(firstWakeup, 32, KERNEL_REASON_UNKNOWN_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(WAKEUP_RETENTION_MS);
|
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_UNKNOWN_IRQ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
|
assertThat(obj.mWakeupEvents.size()).isEqualTo(timestamps.size());
|
||||||
|
|
||||||
obj.noteWakeupTimeAndReason(firstWakeup + WAKEUP_RETENTION_MS + 1242, 231,
|
obj.noteWakeupTimeAndReason(firstWakeup + retention + 1242, 231,
|
||||||
KERNEL_REASON_UNKNOWN_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(WAKEUP_RETENTION_MS + 1, 100 * WAKEUP_RETENTION_MS);
|
final long now = mRandom.nextLong(retention + 1, 100 * retention);
|
||||||
obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ);
|
obj.noteWakeupTimeAndReason(now, i, KERNEL_REASON_UNKNOWN_IRQ);
|
||||||
assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - WAKEUP_RETENTION_MS))
|
assertThat(obj.mWakeupEvents.closestIndexOnOrBefore(now - retention)).isLessThan(0);
|
||||||
.isLessThan(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user