Merge "Add SystemBatteryConsumer for the Bluetooth drain type"
This commit is contained in:
committed by
Android (Google) Code Review
commit
026102b5c8
@@ -36,7 +36,9 @@ public abstract class BatteryConsumer {
|
||||
* @hide
|
||||
*/
|
||||
@IntDef(prefix = {"POWER_COMPONENT_"}, value = {
|
||||
POWER_COMPONENT_USAGE,
|
||||
POWER_COMPONENT_CPU,
|
||||
POWER_COMPONENT_BLUETOOTH,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public static @interface PowerComponent {
|
||||
@@ -44,8 +46,9 @@ public abstract class BatteryConsumer {
|
||||
|
||||
public static final int POWER_COMPONENT_USAGE = 0;
|
||||
public static final int POWER_COMPONENT_CPU = 1;
|
||||
public static final int POWER_COMPONENT_BLUETOOTH = 2;
|
||||
|
||||
public static final int POWER_COMPONENT_COUNT = 2;
|
||||
public static final int POWER_COMPONENT_COUNT = 3;
|
||||
|
||||
public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
|
||||
public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
|
||||
@@ -68,8 +71,10 @@ public abstract class BatteryConsumer {
|
||||
* @hide
|
||||
*/
|
||||
@IntDef(prefix = {"TIME_COMPONENT_"}, value = {
|
||||
TIME_COMPONENT_USAGE,
|
||||
TIME_COMPONENT_CPU,
|
||||
TIME_COMPONENT_CPU_FOREGROUND,
|
||||
TIME_COMPONENT_BLUETOOTH,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public static @interface TimeComponent {
|
||||
@@ -78,8 +83,9 @@ public abstract class BatteryConsumer {
|
||||
public static final int TIME_COMPONENT_USAGE = 0;
|
||||
public static final int TIME_COMPONENT_CPU = 1;
|
||||
public static final int TIME_COMPONENT_CPU_FOREGROUND = 2;
|
||||
public static final int TIME_COMPONENT_BLUETOOTH = 3;
|
||||
|
||||
public static final int TIME_COMPONENT_COUNT = 3;
|
||||
public static final int TIME_COMPONENT_COUNT = 4;
|
||||
|
||||
public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
|
||||
public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
|
||||
|
||||
@@ -289,6 +289,15 @@ class PowerComponents {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addPowerAndDuration(Builder other) {
|
||||
for (int i = 0; i < mPowerComponents.length; i++) {
|
||||
mPowerComponents[i] += other.mPowerComponents[i];
|
||||
}
|
||||
for (int i = 0; i < mTimeComponents.length; i++) {
|
||||
mTimeComponents[i] += other.mTimeComponents[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a read-only object out of the Builder values.
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.annotation.NonNull;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
@@ -118,6 +120,7 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
|
||||
public static final class Builder extends BaseBuilder<Builder> {
|
||||
@DrainType
|
||||
private final int mDrainType;
|
||||
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
|
||||
|
||||
Builder(int customPowerComponentCount, int customTimeComponentCount,
|
||||
boolean includeModeledComponents, @DrainType int drainType) {
|
||||
@@ -125,11 +128,36 @@ public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable
|
||||
mDrainType = drainType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a UidBatteryConsumer to this SystemBatteryConsumer. For example,
|
||||
* the UidBatteryConsumer with the UID == {@link Process#BLUETOOTH_UID} should
|
||||
* be added to the SystemBatteryConsumer with the drain type == {@link
|
||||
* #DRAIN_TYPE_BLUETOOTH}.
|
||||
* <p>
|
||||
* Calculated power and duration components of the added battery consumers
|
||||
* are aggregated at the time the SystemBatteryConsumer is built by the {@link #build()}
|
||||
* method.
|
||||
* </p>
|
||||
*/
|
||||
public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) {
|
||||
if (mUidBatteryConsumers == null) {
|
||||
mUidBatteryConsumers = new ArrayList<>();
|
||||
}
|
||||
mUidBatteryConsumers.add(uidBatteryConsumerBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a read-only object out of the Builder values.
|
||||
*/
|
||||
@NonNull
|
||||
public SystemBatteryConsumer build() {
|
||||
if (mUidBatteryConsumers != null) {
|
||||
for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
|
||||
UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i);
|
||||
mPowerComponentsBuilder.addPowerAndDuration(
|
||||
uidBatteryConsumer.mPowerComponentsBuilder);
|
||||
}
|
||||
}
|
||||
return new SystemBatteryConsumer(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,21 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
|
||||
private final int mUid;
|
||||
@Nullable
|
||||
private final String mPackageWithHighestDrain;
|
||||
private boolean mSystemComponent;
|
||||
|
||||
public int getUid() {
|
||||
return mUid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this battery consumer is considered to be a part of the operating
|
||||
* system itself. For example, the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID}
|
||||
* is a system component.
|
||||
*/
|
||||
public boolean isSystemComponent() {
|
||||
return mSystemComponent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPackageWithHighestDrain() {
|
||||
return mPackageWithHighestDrain;
|
||||
@@ -42,6 +52,7 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
|
||||
private UidBatteryConsumer(@NonNull Builder builder) {
|
||||
super(builder.mPowerComponentsBuilder.build());
|
||||
mUid = builder.mUid;
|
||||
mSystemComponent = builder.mSystemComponent;
|
||||
mPackageWithHighestDrain = builder.mPackageWithHighestDrain;
|
||||
}
|
||||
|
||||
@@ -84,6 +95,7 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
|
||||
private final BatteryStats.Uid mBatteryStatsUid;
|
||||
private final int mUid;
|
||||
private String mPackageWithHighestDrain;
|
||||
private boolean mSystemComponent;
|
||||
|
||||
public Builder(int customPowerComponentCount, int customTimeComponentCount,
|
||||
boolean includeModeledComponents, BatteryStats.Uid batteryStatsUid) {
|
||||
@@ -117,5 +129,14 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela
|
||||
mPackageWithHighestDrain = packageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the UidBatteryConsumer as part of the system. For example,
|
||||
* the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID} is considered
|
||||
* as a system component.
|
||||
*/
|
||||
public void setSystemComponent(boolean systemComponent) {
|
||||
mSystemComponent = systemComponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -953,7 +953,8 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
/**
|
||||
* The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
|
||||
*/
|
||||
ControllerActivityCounterImpl mBluetoothActivity;
|
||||
@VisibleForTesting
|
||||
protected ControllerActivityCounterImpl mBluetoothActivity;
|
||||
|
||||
/**
|
||||
* The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
|
||||
|
||||
@@ -15,8 +15,13 @@
|
||||
*/
|
||||
package com.android.internal.os;
|
||||
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Process;
|
||||
import android.os.SystemBatteryConsumer;
|
||||
import android.os.UidBatteryConsumer;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
@@ -30,8 +35,16 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
private final double mRxMa;
|
||||
private final double mTxMa;
|
||||
private final boolean mHasBluetoothPowerController;
|
||||
private double mAppTotalPowerMah = 0;
|
||||
private long mAppTotalTimeMs = 0;
|
||||
|
||||
private static class PowerAndDuration {
|
||||
public long durationMs;
|
||||
public double powerMah;
|
||||
}
|
||||
|
||||
// Objects used for passing calculation results. Fields are used to avoid allocations.
|
||||
private final PowerAndDuration mUidPowerAndDuration = new PowerAndDuration();
|
||||
private final PowerAndDuration mTotalPowerAndDuration = new PowerAndDuration();
|
||||
private final PowerAndDuration mSystemPowerAndDuration = new PowerAndDuration();
|
||||
|
||||
public BluetoothPowerCalculator(PowerProfile profile) {
|
||||
mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
|
||||
@@ -40,6 +53,63 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
mHasBluetoothPowerController = mIdleMa != 0 && mRxMa != 0 && mTxMa != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
|
||||
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
|
||||
SparseArray<UserHandle> asUsers) {
|
||||
if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mTotalPowerAndDuration.durationMs = 0;
|
||||
mTotalPowerAndDuration.powerMah = 0;
|
||||
|
||||
SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
|
||||
builder.getOrCreateSystemBatteryConsumerBuilder(
|
||||
SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH);
|
||||
|
||||
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
|
||||
builder.getUidBatteryConsumerBuilders();
|
||||
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
|
||||
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
|
||||
calculateApp(app);
|
||||
if (app.getUid() == Process.BLUETOOTH_UID) {
|
||||
app.setSystemComponent(true);
|
||||
systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
|
||||
}
|
||||
}
|
||||
|
||||
final BatteryStats.ControllerActivityCounter counter =
|
||||
batteryStats.getBluetoothControllerActivity();
|
||||
|
||||
calculatePowerAndDuration(counter, mSystemPowerAndDuration);
|
||||
|
||||
// Subtract what the apps used, but clamp to 0.
|
||||
final long systemComponentDurationMs = Math.max(0,
|
||||
mSystemPowerAndDuration.durationMs - mTotalPowerAndDuration.durationMs);
|
||||
final double systemComponentPowerMah = Math.max(0,
|
||||
mSystemPowerAndDuration.powerMah - mTotalPowerAndDuration.powerMah);
|
||||
|
||||
systemBatteryConsumerBuilder
|
||||
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
|
||||
systemComponentDurationMs)
|
||||
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
|
||||
systemComponentPowerMah);
|
||||
}
|
||||
|
||||
private void calculateApp(UidBatteryConsumer.Builder app) {
|
||||
calculatePowerAndDuration(app.getBatteryStatsUid().getBluetoothControllerActivity(),
|
||||
mUidPowerAndDuration);
|
||||
|
||||
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
|
||||
mUidPowerAndDuration.durationMs)
|
||||
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
|
||||
mUidPowerAndDuration.powerMah);
|
||||
|
||||
mTotalPowerAndDuration.powerMah += mUidPowerAndDuration.powerMah;
|
||||
mTotalPowerAndDuration.durationMs += mUidPowerAndDuration.durationMs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
|
||||
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
|
||||
@@ -47,10 +117,27 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
return;
|
||||
}
|
||||
|
||||
mTotalPowerAndDuration.durationMs = 0;
|
||||
mTotalPowerAndDuration.powerMah = 0;
|
||||
|
||||
super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
|
||||
|
||||
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
|
||||
calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
|
||||
calculatePowerAndDuration(batteryStats.getBluetoothControllerActivity(),
|
||||
mSystemPowerAndDuration);
|
||||
|
||||
// Subtract what the apps used, but clamp to 0.
|
||||
double powerMah =
|
||||
Math.max(0, mSystemPowerAndDuration.powerMah - mTotalPowerAndDuration.powerMah);
|
||||
final long durationMs =
|
||||
Math.max(0, mSystemPowerAndDuration.durationMs - mTotalPowerAndDuration.durationMs);
|
||||
if (DEBUG && powerMah != 0) {
|
||||
Log.d(TAG, "Bluetooth active: time=" + (durationMs)
|
||||
+ " power=" + formatCharge(powerMah));
|
||||
}
|
||||
|
||||
bs.bluetoothPowerMah = powerMah;
|
||||
bs.bluetoothRunningTimeMs = durationMs;
|
||||
|
||||
for (int i = sippers.size() - 1; i >= 0; i--) {
|
||||
BatterySipper app = sippers.get(i);
|
||||
@@ -69,65 +156,42 @@ public class BluetoothPowerCalculator extends PowerCalculator {
|
||||
protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
|
||||
long rawUptimeUs, int statsType) {
|
||||
|
||||
final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();
|
||||
if (counter == null) {
|
||||
return;
|
||||
}
|
||||
calculatePowerAndDuration(u.getBluetoothControllerActivity(), mUidPowerAndDuration);
|
||||
|
||||
final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
|
||||
final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
|
||||
final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
|
||||
final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
|
||||
double powerMah = counter.getPowerCounter().getCountLocked(statsType)
|
||||
/ (double)(1000*60*60);
|
||||
|
||||
if (powerMah == 0) {
|
||||
powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
|
||||
/ (1000*60*60);
|
||||
}
|
||||
|
||||
app.bluetoothPowerMah = powerMah;
|
||||
app.bluetoothRunningTimeMs = totalTimeMs;
|
||||
app.bluetoothPowerMah = mUidPowerAndDuration.powerMah;
|
||||
app.bluetoothRunningTimeMs = mUidPowerAndDuration.durationMs;
|
||||
app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);
|
||||
app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);
|
||||
|
||||
mAppTotalPowerMah += powerMah;
|
||||
mAppTotalTimeMs += totalTimeMs;
|
||||
mTotalPowerAndDuration.powerMah += mUidPowerAndDuration.powerMah;
|
||||
mTotalPowerAndDuration.durationMs += mUidPowerAndDuration.durationMs;
|
||||
}
|
||||
|
||||
private void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
|
||||
long rawUptimeUs, int statsType) {
|
||||
final BatteryStats.ControllerActivityCounter counter =
|
||||
stats.getBluetoothControllerActivity();
|
||||
private void calculatePowerAndDuration(BatteryStats.ControllerActivityCounter counter,
|
||||
PowerAndDuration powerAndDuration) {
|
||||
if (counter == null) {
|
||||
powerAndDuration.durationMs = 0;
|
||||
powerAndDuration.powerMah = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
|
||||
final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
|
||||
final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
|
||||
final long idleTimeMs =
|
||||
counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
|
||||
final long rxTimeMs =
|
||||
counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
|
||||
final long txTimeMs =
|
||||
counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
|
||||
final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
|
||||
double powerMah = counter.getPowerCounter().getCountLocked(statsType)
|
||||
/ (double)(1000*60*60);
|
||||
double powerMah =
|
||||
counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED)
|
||||
/ (double) (1000 * 60 * 60);
|
||||
|
||||
if (powerMah == 0) {
|
||||
// Some devices do not report the power, so calculate it.
|
||||
powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
|
||||
/ (1000*60*60);
|
||||
/ (1000 * 60 * 60);
|
||||
}
|
||||
|
||||
// Subtract what the apps used, but clamp to 0.
|
||||
powerMah = Math.max(0, powerMah - mAppTotalPowerMah);
|
||||
|
||||
if (DEBUG && powerMah != 0) {
|
||||
Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
|
||||
+ " power=" + formatCharge(powerMah));
|
||||
}
|
||||
|
||||
app.bluetoothPowerMah = powerMah;
|
||||
app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
mAppTotalPowerMah = 0;
|
||||
mAppTotalTimeMs = 0;
|
||||
powerAndDuration.durationMs = totalTimeMs;
|
||||
powerAndDuration.powerMah = powerMah;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.junit.runners.Suite;
|
||||
BatteryStatsTimerTest.class,
|
||||
BatteryStatsUidTest.class,
|
||||
BatteryStatsUserLifecycleTests.class,
|
||||
BluetoothPowerCalculatorTest.class,
|
||||
BstatsCpuTimesValidationTest.class,
|
||||
KernelCpuProcStringReaderTest.class,
|
||||
KernelCpuUidActiveTimeReaderTest.class,
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.BatteryUsageStatsQuery;
|
||||
import android.os.Process;
|
||||
import android.os.SystemBatteryConsumer;
|
||||
import android.os.UidBatteryConsumer;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class BluetoothPowerCalculatorTest {
|
||||
private static final double PRECISION = 0.00001;
|
||||
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
|
||||
|
||||
@Mock
|
||||
private PowerProfile mMockPowerProfile;
|
||||
private MockBatteryStatsImpl mMockBatteryStats;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mMockBatteryStats = new MockBatteryStatsImpl(new MockClocks()) {
|
||||
@Override
|
||||
public boolean hasBluetoothActivityReporting() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
mMockBatteryStats.getOnBatteryTimeBase().setRunning(true, 100_000, 100_000);
|
||||
when(mMockPowerProfile.getAveragePower(
|
||||
PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE)).thenReturn(10.0);
|
||||
when(mMockPowerProfile.getAveragePower(
|
||||
PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX)).thenReturn(50.0);
|
||||
when(mMockPowerProfile.getAveragePower(
|
||||
PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX)).thenReturn(100.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimerBasedModel() {
|
||||
setDurationsAndPower(
|
||||
mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID)
|
||||
.getOrCreateBluetoothControllerActivityLocked(),
|
||||
1000, 2000, 3000, 0);
|
||||
|
||||
setDurationsAndPower(mMockBatteryStats.getUidStatsLocked(APP_UID)
|
||||
.getOrCreateBluetoothControllerActivityLocked(),
|
||||
4000, 5000, 6000, 0);
|
||||
|
||||
setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl)
|
||||
mMockBatteryStats.getBluetoothControllerActivity(),
|
||||
6000, 8000, 10000, 0);
|
||||
|
||||
BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
|
||||
|
||||
assertBluetoothPowerAndDuration(
|
||||
getUidBatteryConsumer(batteryUsageStats, Process.BLUETOOTH_UID),
|
||||
0.11388, 6000);
|
||||
assertBluetoothPowerAndDuration(
|
||||
getUidBatteryConsumer(batteryUsageStats, APP_UID),
|
||||
0.24722, 15000);
|
||||
assertBluetoothPowerAndDuration(
|
||||
getBluetoothSystemBatteryConsumer(batteryUsageStats,
|
||||
SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
|
||||
0.15833, 9000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportedPowerBasedModel() {
|
||||
setDurationsAndPower(
|
||||
mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID)
|
||||
.getOrCreateBluetoothControllerActivityLocked(),
|
||||
1000, 2000, 3000, 360000);
|
||||
|
||||
setDurationsAndPower(mMockBatteryStats.getUidStatsLocked(APP_UID)
|
||||
.getOrCreateBluetoothControllerActivityLocked(),
|
||||
4000, 5000, 6000, 720000);
|
||||
|
||||
setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl)
|
||||
mMockBatteryStats.getBluetoothControllerActivity(),
|
||||
6000, 8000, 10000, 1260000);
|
||||
|
||||
BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
|
||||
|
||||
assertBluetoothPowerAndDuration(
|
||||
getUidBatteryConsumer(batteryUsageStats, Process.BLUETOOTH_UID),
|
||||
0.1, 6000);
|
||||
assertBluetoothPowerAndDuration(
|
||||
getUidBatteryConsumer(batteryUsageStats, APP_UID),
|
||||
0.2, 15000);
|
||||
assertBluetoothPowerAndDuration(
|
||||
getBluetoothSystemBatteryConsumer(batteryUsageStats,
|
||||
SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
|
||||
0.15, 9000);
|
||||
}
|
||||
|
||||
private void setDurationsAndPower(
|
||||
BatteryStatsImpl.ControllerActivityCounterImpl controllerActivity, int idleDurationMs,
|
||||
int rxDurationMs, int txDurationMs, long powerMaMs) {
|
||||
controllerActivity.getIdleTimeCounter().addCountLocked(idleDurationMs);
|
||||
controllerActivity.getRxTimeCounter().addCountLocked(rxDurationMs);
|
||||
controllerActivity.getTxTimeCounters()[0].addCountLocked(txDurationMs);
|
||||
controllerActivity.getPowerCounter().addCountLocked(powerMaMs);
|
||||
}
|
||||
|
||||
private BatteryUsageStats buildBatteryUsageStats() {
|
||||
BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(0, 0, false);
|
||||
builder.getOrCreateUidBatteryConsumerBuilder(
|
||||
mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID));
|
||||
builder.getOrCreateUidBatteryConsumerBuilder(
|
||||
mMockBatteryStats.getUidStatsLocked(APP_UID));
|
||||
|
||||
BluetoothPowerCalculator bpc = new BluetoothPowerCalculator(mMockPowerProfile);
|
||||
bpc.calculate(builder, mMockBatteryStats, 200_000, 200_000, BatteryUsageStatsQuery.DEFAULT,
|
||||
null);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private UidBatteryConsumer getUidBatteryConsumer(BatteryUsageStats batteryUsageStats, int uid) {
|
||||
for (UidBatteryConsumer ubc : batteryUsageStats.getUidBatteryConsumers()) {
|
||||
if (ubc.getUid() == uid) {
|
||||
return ubc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SystemBatteryConsumer getBluetoothSystemBatteryConsumer(
|
||||
BatteryUsageStats batteryUsageStats, int drainType) {
|
||||
for (SystemBatteryConsumer sbc : batteryUsageStats.getSystemBatteryConsumers()) {
|
||||
if (sbc.getDrainType() == drainType) {
|
||||
return sbc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void assertBluetoothPowerAndDuration(@Nullable BatteryConsumer batteryConsumer,
|
||||
double powerMah, int durationMs) {
|
||||
assertThat(batteryConsumer).isNotNull();
|
||||
|
||||
double consumedPower = batteryConsumer.getConsumedPower(
|
||||
BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
|
||||
assertThat(consumedPower).isWithin(PRECISION).of(powerMah);
|
||||
|
||||
long usageDurationMillis = batteryConsumer.getUsageDurationMillis(
|
||||
BatteryConsumer.TIME_COMPONENT_BLUETOOTH);
|
||||
|
||||
assertThat(usageDurationMillis).isEqualTo(durationMs);
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
|
||||
mScreenDozeTimer = new BatteryStatsImpl.StopwatchTimer(clocks, null, -1, null,
|
||||
mOnBatteryTimeBase);
|
||||
mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
|
||||
mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, 1);
|
||||
setExternalStatsSyncLocked(new DummyExternalStatsSync());
|
||||
|
||||
for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
|
||||
|
||||
Reference in New Issue
Block a user