Transition BatteryStatsLoadTests to BatteryUsageStats API

Also, return metrics to the instrumentation instead of just
logging.

Also, clean up handling of the BATTERY_CHANGED broadcast.

Bug: 175324611
Test: mp :BatteryStatsLoadTests && ash am instrument -w -e class com.android.frameworks.core.batterystatsloadtests.SystemServiceCallLoadTest com.android.frameworks.core.batterystatsloadtests/androidx.test.runner.AndroidJUnitRunner
Change-Id: I9bc7ad361fb31fa7d53a7e383c09b1f1770db530
This commit is contained in:
Dmitri Plotnikov
2021-03-25 09:40:25 -07:00
parent 68037c9a26
commit 6c7ff2671e
4 changed files with 177 additions and 325 deletions

View File

@@ -16,261 +16,99 @@
package com.android.frameworks.core.batterystatsloadtests;
import android.os.Process;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStats;
import android.os.UidBatteryConsumer;
import android.util.DebugUtils;
import android.util.Range;
import java.util.ArrayList;
import java.util.List;
public class PowerMetrics {
private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
enum MetricKind {
POWER,
DURATION,
}
public static final String METRIC_APP_POWER = "appPower";
public static final String METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL = "appPowerExcludeSystem";
public static final String METRIC_APP_POWER_EXCLUDE_SMEARED = "appPowerExcludeSmeared";
public static final String METRIC_SCREEN_POWER = "screenPower";
public static final String METRIC_WIFI_POWER = "wifiPower";
public static final String METRIC_SYSTEM_SERVICE_CPU_POWER = "systemService";
public static final String METRIC_OTHER_POWER = "otherPower";
public static final String METRIC_CPU_POWER = "cpuPower";
public static final String METRIC_RAM_POWER = "ramPower";
public static final String METRIC_WAKELOCK_POWER = "wakelockPower";
public static final String METRIC_MOBILE_RADIO_POWER = "mobileRadioPower";
public static final String METRIC_BLUETOOTH_POWER = "bluetoothPower";
public static final String METRIC_GPS_POWER = "gpsPower";
public static final String METRIC_CAMERA_POWER = "cameraPower";
public static final String METRIC_FLASHLIGHT_POWER = "flashlightPower";
public static final String METRIC_SENSORS_POWER = "sensorsPower";
public static final String METRIC_AUDIO_POWER = "audioPower";
public static final String METRIC_VIDEO_POWER = "videoPower";
public static final String METRIC_CPU_TIME = "cpuTime";
public static final String METRIC_CPU_FOREGROUND_TIME = "cpuForegroundTime";
public static final String METRIC_WAKELOCK_TIME = "wakelockTime";
public static final String METRIC_WIFI_RUNNING_TIME = "wifiRunningTime";
public static final String METRIC_BLUETOOTH_RUNNING_TIME = "bluetoothRunningTime";
public static final String METRIC_GPS_TIME = "gpsTime";
public static final String METRIC_CAMERA_TIME = "cameraTime";
public static final String METRIC_FLASHLIGHT_TIME = "flashlightTime";
public static final String METRIC_AUDIO_TIME = "audioTime";
public static final String METRIC_VIDEO_TIME = "videoTime";
public static class Metric {
public String metricType;
public String metricName;
public MetricKind metricKind;
public String title;
public String statusKeyPrefix;
public double value;
public double total;
}
private final double mMinDrainedPower;
private final double mMaxDrainedPower;
private final double mDrainedPower;
private List<Metric> mMetrics = new ArrayList<>();
public PowerMetrics(BatteryStatsHelper batteryStatsHelper, int uid) {
mMinDrainedPower = batteryStatsHelper.getMinDrainedPower();
mMaxDrainedPower = batteryStatsHelper.getMaxDrainedPower();
public PowerMetrics(BatteryUsageStats batteryUsageStats, int uid) {
final Range<Double> dischargedPowerRange = batteryUsageStats.getDischargedPowerRange();
mDrainedPower = (dischargedPowerRange.getLower() + dischargedPowerRange.getUpper()) / 2;
double[] totalPowerPerComponentMah = new double[BatteryConsumer.POWER_COMPONENT_COUNT];
long[] totalDurationPerComponentMs = new long[BatteryConsumer.POWER_COMPONENT_COUNT];
List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
double totalPowerMah = 0;
double totalSmearedPowerMah = 0;
double totalPowerExcludeSystemMah = 0;
double totalScreenPower = 0;
double totalProportionalSmearMah = 0;
double totalCpuPowerMah = 0;
double totalSystemServiceCpuPowerMah = 0;
double totalUsagePowerMah = 0;
double totalWakeLockPowerMah = 0;
double totalMobileRadioPowerMah = 0;
double totalWifiPowerMah = 0;
double totalBluetoothPowerMah = 0;
double totalGpsPowerMah = 0;
double totalCameraPowerMah = 0;
double totalFlashlightPowerMah = 0;
double totalSensorPowerMah = 0;
double totalAudioPowerMah = 0;
double totalVideoPowerMah = 0;
long totalCpuTimeMs = 0;
long totalCpuFgTimeMs = 0;
long totalWakeLockTimeMs = 0;
long totalWifiRunningTimeMs = 0;
long totalBluetoothRunningTimeMs = 0;
long totalGpsTimeMs = 0;
long totalCameraTimeMs = 0;
long totalFlashlightTimeMs = 0;
long totalAudioTimeMs = 0;
long totalVideoTimeMs = 0;
BatterySipper uidSipper = null;
for (BatterySipper sipper : usageList) {
if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
totalScreenPower = sipper.sumPower();
UidBatteryConsumer selectedBatteryConsumer = null;
for (UidBatteryConsumer uidBatteryConsumer : batteryUsageStats.getUidBatteryConsumers()) {
if (uidBatteryConsumer.getUid() == uid) {
selectedBatteryConsumer = uidBatteryConsumer;
}
if (isHiddenDrainType(sipper.drainType)) {
continue;
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT;
component++) {
totalPowerPerComponentMah[component] += uidBatteryConsumer.getConsumedPower(
component);
}
if (sipper.drainType == BatterySipper.DrainType.APP && sipper.getUid() == uid) {
uidSipper = sipper;
for (int component = 0; component < BatteryConsumer.TIME_COMPONENT_COUNT; component++) {
totalDurationPerComponentMs[component] +=
uidBatteryConsumer.getUsageDurationMillis(component);
}
totalPowerMah += sipper.sumPower();
totalSmearedPowerMah += sipper.totalSmearedPowerMah;
totalProportionalSmearMah += sipper.proportionalSmearMah;
if (!isSystemSipper(sipper)) {
totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
}
totalCpuPowerMah += sipper.cpuPowerMah;
totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah;
totalUsagePowerMah += sipper.usagePowerMah;
totalWakeLockPowerMah += sipper.wakeLockPowerMah;
totalMobileRadioPowerMah += sipper.mobileRadioPowerMah;
totalWifiPowerMah += sipper.wifiPowerMah;
totalBluetoothPowerMah += sipper.bluetoothPowerMah;
totalGpsPowerMah += sipper.gpsPowerMah;
totalCameraPowerMah += sipper.cameraPowerMah;
totalFlashlightPowerMah += sipper.flashlightPowerMah;
totalSensorPowerMah += sipper.sensorPowerMah;
totalAudioPowerMah += sipper.audioPowerMah;
totalVideoPowerMah += sipper.videoPowerMah;
totalCpuTimeMs += sipper.cpuTimeMs;
totalCpuFgTimeMs += sipper.cpuFgTimeMs;
totalWakeLockTimeMs += sipper.wakeLockTimeMs;
totalWifiRunningTimeMs += sipper.wifiRunningTimeMs;
totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs;
totalGpsTimeMs += sipper.gpsTimeMs;
totalCameraTimeMs += sipper.cameraTimeMs;
totalFlashlightTimeMs += sipper.flashlightTimeMs;
totalAudioTimeMs += sipper.audioTimeMs;
totalVideoTimeMs += sipper.videoTimeMs;
}
if (uidSipper == null) {
if (selectedBatteryConsumer == null) {
return;
}
addMetric(METRIC_APP_POWER, MetricKind.POWER, "Total power",
uidSipper.totalSmearedPowerMah, totalSmearedPowerMah);
addMetric(METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL, MetricKind.POWER,
"Total power excluding system",
uidSipper.totalSmearedPowerMah, totalPowerExcludeSystemMah);
addMetric(METRIC_SCREEN_POWER, MetricKind.POWER, "Screen, smeared",
uidSipper.screenPowerMah, totalScreenPower);
addMetric(METRIC_OTHER_POWER, MetricKind.POWER, "Other, smeared",
uidSipper.proportionalSmearMah, totalProportionalSmearMah);
addMetric(METRIC_APP_POWER_EXCLUDE_SMEARED, MetricKind.POWER, "Excluding smeared",
uidSipper.totalPowerMah, totalPowerMah);
addMetric(METRIC_CPU_POWER, MetricKind.POWER, "CPU",
uidSipper.cpuPowerMah, totalCpuPowerMah);
addMetric(METRIC_SYSTEM_SERVICE_CPU_POWER, MetricKind.POWER, "System services",
uidSipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
addMetric(METRIC_RAM_POWER, MetricKind.POWER, "RAM",
uidSipper.usagePowerMah, totalUsagePowerMah);
addMetric(METRIC_WAKELOCK_POWER, MetricKind.POWER, "Wake lock",
uidSipper.wakeLockPowerMah, totalWakeLockPowerMah);
addMetric(METRIC_MOBILE_RADIO_POWER, MetricKind.POWER, "Mobile radio",
uidSipper.mobileRadioPowerMah, totalMobileRadioPowerMah);
addMetric(METRIC_WIFI_POWER, MetricKind.POWER, "WiFi",
uidSipper.wifiPowerMah, totalWifiPowerMah);
addMetric(METRIC_BLUETOOTH_POWER, MetricKind.POWER, "Bluetooth",
uidSipper.bluetoothPowerMah, totalBluetoothPowerMah);
addMetric(METRIC_GPS_POWER, MetricKind.POWER, "GPS",
uidSipper.gpsPowerMah, totalGpsPowerMah);
addMetric(METRIC_CAMERA_POWER, MetricKind.POWER, "Camera",
uidSipper.cameraPowerMah, totalCameraPowerMah);
addMetric(METRIC_FLASHLIGHT_POWER, MetricKind.POWER, "Flashlight",
uidSipper.flashlightPowerMah, totalFlashlightPowerMah);
addMetric(METRIC_SENSORS_POWER, MetricKind.POWER, "Sensors",
uidSipper.sensorPowerMah, totalSensorPowerMah);
addMetric(METRIC_AUDIO_POWER, MetricKind.POWER, "Audio",
uidSipper.audioPowerMah, totalAudioPowerMah);
addMetric(METRIC_VIDEO_POWER, MetricKind.POWER, "Video",
uidSipper.videoPowerMah, totalVideoPowerMah);
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
addMetric(getPowerMetricName(component), MetricKind.POWER,
selectedBatteryConsumer.getConsumedPower(component),
totalPowerPerComponentMah[component]);
}
addMetric(METRIC_CPU_TIME, MetricKind.DURATION, "CPU time",
uidSipper.cpuTimeMs, totalCpuTimeMs);
addMetric(METRIC_CPU_FOREGROUND_TIME, MetricKind.DURATION, "CPU foreground time",
uidSipper.cpuFgTimeMs, totalCpuFgTimeMs);
addMetric(METRIC_WAKELOCK_TIME, MetricKind.DURATION, "Wake lock time",
uidSipper.wakeLockTimeMs, totalWakeLockTimeMs);
addMetric(METRIC_WIFI_RUNNING_TIME, MetricKind.DURATION, "WiFi running time",
uidSipper.wifiRunningTimeMs, totalWifiRunningTimeMs);
addMetric(METRIC_BLUETOOTH_RUNNING_TIME, MetricKind.DURATION, "Bluetooth time",
uidSipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs);
addMetric(METRIC_GPS_TIME, MetricKind.DURATION, "GPS time",
uidSipper.gpsTimeMs, totalGpsTimeMs);
addMetric(METRIC_CAMERA_TIME, MetricKind.DURATION, "Camera time",
uidSipper.cameraTimeMs, totalCameraTimeMs);
addMetric(METRIC_FLASHLIGHT_TIME, MetricKind.DURATION, "Flashlight time",
uidSipper.flashlightTimeMs, totalFlashlightTimeMs);
addMetric(METRIC_AUDIO_TIME, MetricKind.DURATION, "Audio time",
uidSipper.audioTimeMs, totalAudioTimeMs);
addMetric(METRIC_VIDEO_TIME, MetricKind.DURATION, "Video time",
uidSipper.videoTimeMs, totalVideoTimeMs);
for (int component = 0; component < BatteryConsumer.TIME_COMPONENT_COUNT; component++) {
addMetric(getTimeMetricName(component), MetricKind.DURATION,
selectedBatteryConsumer.getUsageDurationMillis(component),
totalDurationPerComponentMs[component]);
}
}
static String getTimeMetricName(int componentId) {
return "TIME_" + DebugUtils.constantToString(BatteryConsumer.class,
"TIME_COMPONENT_", componentId);
}
static String getPowerMetricName(int componentId) {
return "POWER_" + DebugUtils.constantToString(BatteryConsumer.class,
"POWER_COMPONENT_", componentId);
}
public List<Metric> getMetrics() {
return mMetrics;
}
public double getMinDrainedPower() {
return mMinDrainedPower;
public double getDrainedPower() {
return mDrainedPower;
}
public double getMaxDrainedPower() {
return mMaxDrainedPower;
}
protected boolean isHiddenDrainType(BatterySipper.DrainType drainType) {
return drainType == BatterySipper.DrainType.IDLE
|| drainType == BatterySipper.DrainType.CELL
|| drainType == BatterySipper.DrainType.SCREEN
|| drainType == BatterySipper.DrainType.UNACCOUNTED
|| drainType == BatterySipper.DrainType.OVERCOUNTED
|| drainType == BatterySipper.DrainType.BLUETOOTH
|| drainType == BatterySipper.DrainType.WIFI;
}
private boolean isSystemSipper(BatterySipper sipper) {
final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
return true;
} else if (sipper.mPackages != null) {
for (final String packageName : sipper.mPackages) {
for (final String systemPackage : PACKAGES_SYSTEM) {
if (systemPackage.equals(packageName)) {
return true;
}
}
}
}
return false;
}
private void addMetric(String metricType, MetricKind metricKind, String title, double amount,
private void addMetric(String metricType, MetricKind metricKind, double amount,
double totalAmount) {
Metric metric = new Metric();
metric.metricType = metricType;
metric.metricName = metricType;
metric.metricKind = metricKind;
metric.title = title;
metric.statusKeyPrefix = metricKind.toString().toLowerCase();
metric.value = amount;
metric.total = totalAmount;
mMetrics.add(metric);

View File

@@ -19,47 +19,43 @@ package com.android.frameworks.core.batterystatsloadtests;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryConsumer;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserManager;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.TimeUtils;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.SystemUtil;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.LoggingPrintStream;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.io.PrintStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class PowerMetricsCollector implements TestRule {
private final String mTag;
private final float mBatteryDrainThresholdPct;
private final int mTimeoutMillis;
private final Instrumentation mInstrumentation;
private final Context mContext;
private final UserManager mUserManager;
private final int mUid;
private final BatteryStatsHelper mStatsHelper;
private final CountDownLatch mSuspendingBatteryInput = new CountDownLatch(1);
private final ConditionVariable mSuspendingBatteryInput = new ConditionVariable();
private long mStartTime;
private volatile float mInitialBatteryLevel;
@@ -68,29 +64,34 @@ public class PowerMetricsCollector implements TestRule {
private PowerMetrics mInitialPowerMetrics;
private PowerMetrics mFinalPowerMetrics;
private List<PowerMetrics.Metric> mPowerMetricsDelta;
private Intent mBatteryStatus;
private final BatteryStatsManager mBatteryStatsManager;
private final BroadcastReceiver mBatteryLevelReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
handleBatteryStatus(intent);
}
};
private final Bundle mStatus = new Bundle();
private final StringWriter mReportStringWriter = new StringWriter();
private final IndentingPrintWriter mReportWriter =
new IndentingPrintWriter(mReportStringWriter);
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
BroadcastReceiver batteryBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
handleBatteryStatus(intent);
}
};
mBatteryStatus = mContext.registerReceiver(batteryBroadcastReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
disableCharger();
try {
prepareBatteryLevelMonitor();
mStartTime = SystemClock.uptimeMillis();
mContext.registerReceiver(mBatteryLevelReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
base.evaluate();
captureFinalPowerStatsData();
mStatus.putString("report", mReportStringWriter.toString());
mInstrumentation.sendStatus(Activity.RESULT_OK, mStatus);
} finally {
mContext.unregisterReceiver(batteryBroadcastReceiver);
mContext.unregisterReceiver(mBatteryLevelReceiver);
enableCharger();
}
}
@@ -102,35 +103,41 @@ public class PowerMetricsCollector implements TestRule {
mBatteryDrainThresholdPct = batteryDrainThresholdPct;
mTimeoutMillis = timeoutMillis;
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
mContext = instrumentation.getContext();
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getContext();
mUid = Process.myUid();
mUserManager = mContext.getSystemService(UserManager.class);
// TODO(b/175324611): Use BatteryUsageStats instead
mStatsHelper = new BatteryStatsHelper(mContext, false /* collectBatteryBroadcast */);
mStatsHelper.create((Bundle) null);
mBatteryStatsManager = mContext.getSystemService(BatteryStatsManager.class);
}
private void disableCharger() throws InterruptedException {
SystemUtil.runShellCommand("dumpsys battery suspend_input");
final boolean success = mSuspendingBatteryInput.await(10, TimeUnit.SECONDS);
assertTrue("Timed out waiting for battery input to be suspended", success);
private void disableCharger() {
final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!isCharging(intent)) {
mInitialBatteryLevel = mCurrentBatteryLevel = getBatteryLevel(intent);
mSuspendingBatteryInput.open();
}
}
};
final Intent intent = mContext.registerReceiver(
receiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
if (isCharging(intent)) {
mBatteryStatsManager.suspendBatteryInput();
final boolean success = mSuspendingBatteryInput.block(10000);
assertTrue("Timed out waiting for battery input to be suspended", success);
}
mContext.unregisterReceiver(receiver);
}
private void enableCharger() {
SystemUtil.runShellCommand("dumpsys battery reset");
mBatteryStatsManager.resetBattery(/* forceUpdate */false);
}
private PowerMetrics readBatteryStatsData() {
mStatsHelper.clearStats();
mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
mUserManager.getUserProfiles());
return new PowerMetrics(mStatsHelper, mUid);
}
protected void prepareBatteryLevelMonitor() {
handleBatteryStatus(mBatteryStatus);
mInitialBatteryLevel = mCurrentBatteryLevel;
return new PowerMetrics(mBatteryStatsManager.getBatteryUsageStats(), mUid);
}
protected void handleBatteryStatus(Intent intent) {
@@ -138,36 +145,35 @@ public class PowerMetricsCollector implements TestRule {
return;
}
final boolean isCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
if (mSuspendingBatteryInput.getCount() > 0) {
if (!isCharging) {
mSuspendingBatteryInput.countDown();
}
return;
}
if (isCharging) {
if (isCharging(intent)) {
fail("Device must remain disconnected from the power source "
+ "for the duration of the test");
}
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
mCurrentBatteryLevel = level * 100 / (float) scale;
mCurrentBatteryLevel = getBatteryLevel(intent);
Log.i(mTag, "Battery level = " + mCurrentBatteryLevel);
// We delay tracking until the battery level drops. If the resolution of
// battery level is 1%, and the initially reported level is 73, we don't know whether
// it's 73.1 or 73.7. Once it drops to 72, we can be confident that the real battery
// level it is very close to 72.0 and can start tracking.
// level is very close to 72.0 and can start tracking.
if (mInitialPowerMetrics == null && mCurrentBatteryLevel < mInitialBatteryLevel) {
mInitialBatteryLevel = mCurrentBatteryLevel;
mInitialPowerMetrics = readBatteryStatsData();
}
}
private boolean isCharging(Intent intent) {
return intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
}
private float getBatteryLevel(Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
return level * 100 / (float) scale;
}
private void captureFinalPowerStatsData() {
if (mFinalPowerMetrics != null) {
return;
@@ -181,7 +187,7 @@ public class PowerMetricsCollector implements TestRule {
for (PowerMetrics.Metric initialMetric : initialPowerMetrics) {
PowerMetrics.Metric finalMetric = null;
for (PowerMetrics.Metric metric : finalPowerMetrics) {
if (metric.title.equals(initialMetric.title)) {
if (metric.metricName.equals(initialMetric.metricName)) {
finalMetric = metric;
break;
}
@@ -189,9 +195,9 @@ public class PowerMetricsCollector implements TestRule {
if (finalMetric != null) {
PowerMetrics.Metric delta = new PowerMetrics.Metric();
delta.metricType = initialMetric.metricType;
delta.metricName = initialMetric.metricName;
delta.metricKind = initialMetric.metricKind;
delta.title = initialMetric.title;
delta.statusKeyPrefix = initialMetric.statusKeyPrefix;
delta.total = finalMetric.total - initialMetric.total;
delta.value = finalMetric.value - initialMetric.value;
mPowerMetricsDelta.add(delta);
@@ -230,73 +236,80 @@ public class PowerMetricsCollector implements TestRule {
return mIterations;
}
public void dumpMetrics() {
dumpMetrics(new LoggingPrintStream() {
@Override
protected void log(String line) {
Log.i(mTag, line);
}
});
public void report(String line) {
mReportWriter.println(line);
}
public void dumpMetrics(PrintStream out) {
public void reportMetrics() {
List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics();
List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics();
out.println("== Power metrics at test start");
dumpPowerStatsData(out, initialPowerMetrics);
mReportWriter.println("Power metrics at test start");
mReportWriter.increaseIndent();
reportPowerStatsData(initialPowerMetrics);
mReportWriter.decreaseIndent();
out.println("== Power metrics at test end");
dumpPowerStatsData(out, finalPowerMetrics);
mReportWriter.println("Power metrics at test end");
mReportWriter.increaseIndent();
reportPowerStatsData(finalPowerMetrics);
mReportWriter.decreaseIndent();
out.println("== Power metrics delta");
dumpPowerStatsData(out, mPowerMetricsDelta);
mReportWriter.println("Power metrics delta");
mReportWriter.increaseIndent();
reportPowerStatsData(mPowerMetricsDelta);
mReportWriter.decreaseIndent();
}
protected void dumpPowerStatsData(PrintStream out, List<PowerMetrics.Metric> metrics) {
protected void reportPowerStatsData(List<PowerMetrics.Metric> metrics) {
Locale locale = Locale.getDefault();
for (PowerMetrics.Metric metric : metrics) {
double proportion = metric.total != 0 ? metric.value * 100 / metric.total : 0;
switch (metric.metricKind) {
case POWER:
out.println(
String.format(locale, " %-30s %7.1f mAh %4.1f%%", metric.title,
mReportWriter.println(
String.format(locale, "%-40s %7.1f mAh %4.1f%%", metric.metricName,
metric.value, proportion));
break;
case DURATION:
out.println(
String.format(locale, " %-30s %,7d ms %4.1f%%", metric.title,
mReportWriter.println(
String.format(locale, "%-40s %,7d ms %4.1f%%", metric.metricName,
(long) metric.value, proportion));
break;
}
}
}
public void dumpMetricAsPercentageOfDrainedPower(String metricType) {
double minDrainedPower =
mFinalPowerMetrics.getMinDrainedPower() - mInitialPowerMetrics.getMinDrainedPower();
double maxDrainedPower =
mFinalPowerMetrics.getMaxDrainedPower() - mInitialPowerMetrics.getMaxDrainedPower();
public void reportMetricAsPercentageOfDrainedPower(
@BatteryConsumer.PowerComponent int component) {
double drainedPower =
mFinalPowerMetrics.getDrainedPower() - mInitialPowerMetrics.getDrainedPower();
PowerMetrics.Metric metric = getMetric(metricType);
PowerMetrics.Metric metric = getPowerMetric(component);
double metricDelta = metric.value;
if (maxDrainedPower - minDrainedPower < 0.1f) {
Log.i(mTag, String.format(Locale.getDefault(),
"%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)",
metric.title, metricDelta, maxDrainedPower,
metricDelta / maxDrainedPower * 100));
} else {
Log.i(mTag, String.format(Locale.getDefault(),
"%s power consumed by the test: %.1f of %.1f - %.1f mAh (%.1f%% - %.1f%%)",
metric.title, metricDelta, minDrainedPower, maxDrainedPower,
metricDelta / minDrainedPower * 100, metricDelta / maxDrainedPower * 100));
}
final double percent = metricDelta / drainedPower * 100;
mStatus.putDouble(metric.statusKeyPrefix, metricDelta);
mStatus.putDouble(metric.statusKeyPrefix + "_pct", percent);
mReportWriter.println(String.format(Locale.getDefault(),
"%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)",
metric.metricName, metricDelta, drainedPower, percent));
}
public PowerMetrics.Metric getMetric(String metricType) {
public PowerMetrics.Metric getPowerMetric(@BatteryConsumer.PowerComponent int component) {
final String name = PowerMetrics.getPowerMetricName(component);
for (PowerMetrics.Metric metric : mPowerMetricsDelta) {
if (metric.metricType.equals(metricType)) {
if (metric.metricName.equals(name)) {
return metric;
}
}
return null;
}
public PowerMetrics.Metric getTimeMetric(@BatteryConsumer.TimeComponent int component) {
final String name = PowerMetrics.getTimeMetricName(component);
for (PowerMetrics.Metric metric : mPowerMetricsDelta) {
if (metric.metricName.equals(name)) {
return metric;
}
}

View File

@@ -23,7 +23,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.util.Log;
import android.os.BatteryConsumer;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -58,12 +58,12 @@ public class SystemServiceCallLoadTest {
assertNotNull(resolveInfo);
}
mPowerMetricsCollector.dumpMetrics();
mPowerMetricsCollector.reportMetrics();
Log.i(TAG, "==");
Log.i(TAG, "Total system server calls made " + mPowerMetricsCollector.getIterationCount());
mPowerMetricsCollector.report(
"Total system server calls made: " + mPowerMetricsCollector.getIterationCount());
mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
PowerMetrics.METRIC_SYSTEM_SERVICE_CPU_POWER);
mPowerMetricsCollector.reportMetricAsPercentageOfDrainedPower(
BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES);
}
}

View File

@@ -16,7 +16,7 @@
package com.android.frameworks.core.batterystatsloadtests;
import android.util.Log;
import android.os.BatteryConsumer;
import org.junit.Rule;
import org.junit.Test;
@@ -59,14 +59,15 @@ public class WiFiLoadTest {
}
}
mPowerMetricsCollector.dumpMetrics();
mPowerMetricsCollector.reportMetrics();
Log.i(TAG, "==");
Log.i(TAG, "WiFi running time: " + (long) mPowerMetricsCollector.getMetric(
PowerMetrics.METRIC_WIFI_RUNNING_TIME).value);
Log.i(TAG, "Total bytes read over WiFi: " + totalBytesRead);
mPowerMetricsCollector.report(
"WiFi running time: " + (long) mPowerMetricsCollector.getTimeMetric(
BatteryConsumer.POWER_COMPONENT_WIFI).value);
mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
PowerMetrics.METRIC_WIFI_POWER);
mPowerMetricsCollector.report("Total bytes read over WiFi: " + totalBytesRead);
mPowerMetricsCollector.reportMetricAsPercentageOfDrainedPower(
BatteryConsumer.POWER_COMPONENT_WIFI);
}
}