blob: be8045ddc7b2e7c930553544797b00d437a791ec [file] [log] [blame]
/*
* Copyright (C) 2017 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 android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
import static android.os.BatteryStats.Uid.PROCESS_STATE_CACHED;
import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.UidTraffic;
import android.os.BatteryStats;
import android.os.BluetoothBatteryStats;
import android.os.WakeLockStats;
import android.os.WorkSource;
import android.util.SparseArray;
import android.view.Display;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
@LargeTest
@RunWith(AndroidJUnit4.class)
@SuppressWarnings("GuardedBy")
public class BatteryStatsImplTest {
private static final long[] CPU_FREQS = {1, 2, 3, 4, 5};
private static final int NUM_CPU_FREQS = CPU_FREQS.length;
@Mock
private KernelCpuUidFreqTimeReader mKernelUidCpuFreqTimeReader;
@Mock
private KernelSingleUidTimeReader mKernelSingleUidTimeReader;
@Mock
private PowerProfile mPowerProfile;
private final MockClock mMockClock = new MockClock();
private MockBatteryStatsImpl mBatteryStatsImpl;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mKernelUidCpuFreqTimeReader.isFastCpuTimesReader()).thenReturn(true);
when(mKernelUidCpuFreqTimeReader.readFreqs(any())).thenReturn(CPU_FREQS);
when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true);
when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true);
mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock)
.setPowerProfile(mPowerProfile)
.setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader)
.setKernelSingleUidTimeReader(mKernelSingleUidTimeReader);
}
@Test
public void testUpdateProcStateCpuTimes() {
mBatteryStatsImpl.setOnBatteryInternal(true);
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
final int[] testUids = {10032, 10048, 10145, 10139};
final int[] activityManagerProcStates = {
ActivityManager.PROCESS_STATE_RECEIVER,
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_STATE_CACHED_EMPTY
};
final int[] testProcStates = {
PROCESS_STATE_BACKGROUND,
PROCESS_STATE_FOREGROUND_SERVICE,
PROCESS_STATE_TOP,
PROCESS_STATE_CACHED
};
// Initialize time-in-freq counters
mMockClock.realtime = 1000;
for (int i = 0; i < testUids.length; ++i) {
mockKernelSingleUidTimeReader(testUids[i], new long[5]);
mBatteryStatsImpl.noteUidProcessStateLocked(testUids[i], activityManagerProcStates[i]);
}
final long[] timeInFreqs = new long[NUM_CPU_FREQS];
// Verify there are no cpu times initially.
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
// Obtain initial CPU time-in-freq counts
final long[][] cpuTimes = {
{349734983, 394982394832L, 909834, 348934, 9838},
{7498, 1239890, 988, 13298, 98980},
{989834, 384098, 98483, 23809, 4984},
{4859048, 348903, 4578967, 5973894, 298549}
};
mMockClock.realtime += 1000;
for (int i = 0; i < testUids.length; ++i) {
mockKernelSingleUidTimeReader(testUids[i], cpuTimes[i]);
mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
mMockClock.realtime);
}
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
final boolean hasTimeInFreq = u.getCpuFreqTimes(timeInFreqs, procState);
if (procState == testProcStates[i]) {
assertArrayEquals("Uid=" + testUids[i], cpuTimes[i], timeInFreqs);
} else {
assertFalse(hasTimeInFreq);
}
assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
// Accumulate CPU time-in-freq deltas
final long[][] delta1 = {
{9589, 148934, 309894, 3098493, 98754},
{21983, 94983, 4983, 9878493, 84854},
{945894, 9089432, 19478, 3834, 7845},
{843895, 43948, 949582, 99, 384}
};
mMockClock.realtime += 1000;
for (int i = 0; i < testUids.length; ++i) {
long[] newCpuTimes = new long[cpuTimes[i].length];
for (int j = 0; j < cpuTimes[i].length; j++) {
newCpuTimes[j] = cpuTimes[i][j] + delta1[i][j];
}
mockKernelSingleUidTimeReader(testUids[i], newCpuTimes);
mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
mMockClock.realtime);
}
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
if (procState == testProcStates[i]) {
long[] expectedCpuTimes = cpuTimes[i].clone();
for (int j = 0; j < expectedCpuTimes.length; ++j) {
expectedCpuTimes[j] += delta1[i][j];
}
assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
} else {
assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
}
assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
// Validate the on-battery-screen-off counter
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0,
mMockClock.realtime * 1000);
final long[][] delta2 = {
{95932, 2943, 49834, 89034, 139},
{349, 89605, 5896, 845, 98444},
{678, 7498, 9843, 889, 4894},
{488, 998, 8498, 394, 574}
};
mMockClock.realtime += 1000;
for (int i = 0; i < testUids.length; ++i) {
long[] newCpuTimes = new long[cpuTimes[i].length];
for (int j = 0; j < cpuTimes[i].length; j++) {
newCpuTimes[j] = cpuTimes[i][j] + delta1[i][j] + delta2[i][j];
}
mockKernelSingleUidTimeReader(testUids[i], newCpuTimes);
mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
mMockClock.realtime);
}
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
if (procState == testProcStates[i]) {
long[] expectedCpuTimes = cpuTimes[i].clone();
for (int j = 0; j < expectedCpuTimes.length; ++j) {
expectedCpuTimes[j] += delta1[i][j] + delta2[i][j];
}
assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
assertArrayEquals("Uid=" + testUids[i], delta2[i], timeInFreqs);
} else {
assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
}
// Verify handling of isolated UIDs - their time-in-freq must be directly
// added to that of the parent UID's. The proc state of the isolated UID is
// assumed to be the same as that of the parent UID, so there is no per-state
// data for isolated UIDs.
final long[][] delta3 = {
{98545, 95768795, 76586, 548945, 57846},
{788876, 586, 578459, 8776984, 9578923},
{3049509483598l, 4597834, 377654, 94589035, 7854},
{9493, 784, 99895, 8974893, 9879843}
};
mMockClock.realtime += 1000;
final int parentUid = testUids[1];
final int childUid = 99099;
addIsolatedUid(parentUid, childUid);
final long[] isolatedUidCpuTimes = {495784, 398473, 4895, 4905, 30984093};
mockKernelSingleUidTimeReader(childUid, isolatedUidCpuTimes, isolatedUidCpuTimes);
for (int i = 0; i < testUids.length; ++i) {
long[] newCpuTimes = new long[cpuTimes[i].length];
for (int j = 0; j < cpuTimes[i].length; j++) {
newCpuTimes[j] = cpuTimes[i][j] + delta1[i][j] + delta2[i][j] + delta3[i][j];
}
mockKernelSingleUidTimeReader(testUids[i], newCpuTimes);
mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
mMockClock.realtime);
}
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
if (procState == testProcStates[i]) {
long[] expectedCpuTimes = cpuTimes[i].clone();
for (int j = 0; j < expectedCpuTimes.length; ++j) {
expectedCpuTimes[j] += delta1[i][j] + delta2[i][j] + delta3[i][j]
+ (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
}
assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
long[] expectedScreenOffTimes = delta2[i].clone();
for (int j = 0; j < expectedScreenOffTimes.length; ++j) {
expectedScreenOffTimes[j] += delta3[i][j]
+ (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
}
assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes, timeInFreqs);
} else {
assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
}
}
@Test
public void testUpdateCpuTimesForAllUids() {
mBatteryStatsImpl.setOnBatteryInternal(false);
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
mMockClock.realtime = 1000;
final int[] testUids = {10032, 10048, 10145, 10139};
final int[] testProcStates = {
PROCESS_STATE_BACKGROUND,
PROCESS_STATE_FOREGROUND_SERVICE,
PROCESS_STATE_TOP,
PROCESS_STATE_CACHED
};
for (int i = 0; i < testUids.length; ++i) {
BatteryStatsImpl.Uid uid = mBatteryStatsImpl.getUidStatsLocked(testUids[i]);
uid.setProcessStateForTest(testProcStates[i], mMockClock.elapsedRealtime());
mockKernelSingleUidTimeReader(testUids[i], new long[NUM_CPU_FREQS]);
mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
mMockClock.elapsedRealtime());
}
final SparseArray<long[]> allUidCpuTimes = new SparseArray<>();
long[][] allCpuTimes = {
{938483, 4985984, 439893},
{499, 94904, 27694},
{302949085, 39789473, 34792839},
{9809485, 9083475, 347889834},
};
for (int i = 0; i < testUids.length; ++i) {
allUidCpuTimes.put(testUids[i], allCpuTimes[i]);
}
when(mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs()).thenReturn(allUidCpuTimes);
long[][] expectedCpuTimes = {
{843598745, 397843, 32749, 99854, 23454},
{9834, 5885, 487589, 394, 93933},
{203984, 439, 9859, 30948, 49494},
{9389, 858, 239, 349, 50505}
};
for (int i = 0; i < testUids.length; ++i) {
mockKernelSingleUidTimeReader(testUids[i], expectedCpuTimes[i]);
}
mMockClock.realtime += 1000;
mBatteryStatsImpl.updateCpuTimesForAllUids();
final long[] timeInFreqs = new long[NUM_CPU_FREQS];
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
if (procState == testProcStates[i]) {
assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i], timeInFreqs);
} else {
assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
}
assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
}
private void mockKernelSingleUidTimeReader(int testUid, long[] cpuTimes) {
doAnswer(invocation -> {
LongArrayMultiStateCounter counter = invocation.getArgument(1);
long timestampMs = invocation.getArgument(2);
LongArrayMultiStateCounter.LongArrayContainer container =
new LongArrayMultiStateCounter.LongArrayContainer(NUM_CPU_FREQS);
container.setValues(cpuTimes);
counter.updateValues(container, timestampMs);
return null;
}).when(mKernelSingleUidTimeReader).addDelta(eq(testUid),
any(LongArrayMultiStateCounter.class), anyLong());
}
private void mockKernelSingleUidTimeReader(int testUid, long[] cpuTimes, long[] delta) {
doAnswer(invocation -> {
LongArrayMultiStateCounter counter = invocation.getArgument(1);
long timestampMs = invocation.getArgument(2);
LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
invocation.getArgument(3);
LongArrayMultiStateCounter.LongArrayContainer container =
new LongArrayMultiStateCounter.LongArrayContainer(NUM_CPU_FREQS);
container.setValues(cpuTimes);
counter.updateValues(container, timestampMs);
if (deltaContainer != null) {
deltaContainer.setValues(delta);
}
return null;
}).when(mKernelSingleUidTimeReader).addDelta(eq(testUid),
any(LongArrayMultiStateCounter.class), anyLong(),
any(LongArrayMultiStateCounter.LongArrayContainer.class));
}
@Test
public void testAddCpuTimes() {
long[] timesA = null;
long[] timesB = null;
assertNull(mBatteryStatsImpl.addCpuTimes(timesA, timesB));
timesA = new long[] {34, 23, 45, 24};
assertArrayEquals(timesA, mBatteryStatsImpl.addCpuTimes(timesA, timesB));
timesB = timesA;
timesA = null;
assertArrayEquals(timesB, mBatteryStatsImpl.addCpuTimes(timesA, timesB));
final long[] expected = {434, 6784, 34987, 9984};
timesA = new long[timesB.length];
for (int i = 0; i < timesA.length; ++i) {
timesA[i] = expected[i] - timesB[i];
}
assertArrayEquals(expected, mBatteryStatsImpl.addCpuTimes(timesA, timesB));
}
@Test
public void testMulticastWakelockAcqRel() {
final int testUid = 10032;
final int acquireTimeMs = 1000;
final int releaseTimeMs = 1005;
final int currentTimeMs = 1011;
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
// Create a Uid Object
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
assertNotNull(u);
// Acquire and release the lock
u.noteWifiMulticastEnabledLocked(acquireTimeMs);
u.noteWifiMulticastDisabledLocked(releaseTimeMs);
// Get the total acquisition time
long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
BatteryStats.STATS_SINCE_CHARGED);
assertEquals("Miscalculations of Multicast wakelock acquisition time",
(releaseTimeMs - acquireTimeMs) * 1000, totalTime);
}
@Test
public void testMulticastWakelockAcqNoRel() {
final int testUid = 10032;
final int acquireTimeMs = 1000;
final int currentTimeMs = 1011;
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
// Create a Uid Object
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
assertNotNull(u);
// Acquire the lock
u.noteWifiMulticastEnabledLocked(acquireTimeMs);
// Get the total acquisition time
long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
BatteryStats.STATS_SINCE_CHARGED);
assertEquals("Miscalculations of Multicast wakelock acquisition time",
(currentTimeMs - acquireTimeMs) * 1000, totalTime);
}
@Test
public void testMulticastWakelockAcqAcqRelRel() {
final int testUid = 10032;
final int acquireTimeMs_1 = 1000;
final int acquireTimeMs_2 = 1002;
final int releaseTimeMs_1 = 1005;
final int releaseTimeMs_2 = 1009;
final int currentTimeMs = 1011;
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
// Create a Uid Object
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
assertNotNull(u);
// Acquire and release the lock (twice in nested way)
u.noteWifiMulticastEnabledLocked(acquireTimeMs_1);
u.noteWifiMulticastEnabledLocked(acquireTimeMs_2);
u.noteWifiMulticastDisabledLocked(releaseTimeMs_1);
u.noteWifiMulticastDisabledLocked(releaseTimeMs_2);
// Get the total acquisition time
long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
BatteryStats.STATS_SINCE_CHARGED);
assertEquals("Miscalculations of Multicast wakelock acquisition time",
(releaseTimeMs_2 - acquireTimeMs_1) * 1000, totalTime);
}
@Test
public void testMulticastWakelockAcqRelAcqRel() {
final int testUid = 10032;
final int acquireTimeMs_1 = 1000;
final int acquireTimeMs_2 = 1005;
final int releaseTimeMs_1 = 1002;
final int releaseTimeMs_2 = 1009;
final int currentTimeMs = 1011;
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
// Create a Uid Object
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
assertNotNull(u);
// Acquire and release the lock (twice)
u.noteWifiMulticastEnabledLocked(acquireTimeMs_1);
u.noteWifiMulticastDisabledLocked(releaseTimeMs_1);
u.noteWifiMulticastEnabledLocked(acquireTimeMs_2);
u.noteWifiMulticastDisabledLocked(releaseTimeMs_2);
// Get the total acquisition time
long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
BatteryStats.STATS_SINCE_CHARGED);
assertEquals("Miscalculations of Multicast wakelock acquisition time",
((releaseTimeMs_1 - acquireTimeMs_1) + (releaseTimeMs_2 - acquireTimeMs_2))
* 1000, totalTime);
}
private void addIsolatedUid(int parentUid, int childUid) {
final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(parentUid);
u.addIsolatedUid(childUid);
}
@Test
public void testGetWakeLockStats() {
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
// First wakelock, acquired once, not currently held
mMockClock.realtime = 1000;
mBatteryStatsImpl.noteStartWakeLocked(10100, 100, null, "wakeLock1", null,
BatteryStats.WAKE_TYPE_PARTIAL, false);
mMockClock.realtime = 3000;
mBatteryStatsImpl.noteStopWakeLocked(10100, 100, null, "wakeLock1", null,
BatteryStats.WAKE_TYPE_PARTIAL);
// Second wakelock, acquired twice, still held
mMockClock.realtime = 4000;
mBatteryStatsImpl.noteStartWakeLocked(10200, 101, null, "wakeLock2", null,
BatteryStats.WAKE_TYPE_PARTIAL, false);
mMockClock.realtime = 5000;
mBatteryStatsImpl.noteStopWakeLocked(10200, 101, null, "wakeLock2", null,
BatteryStats.WAKE_TYPE_PARTIAL);
mMockClock.realtime = 6000;
mBatteryStatsImpl.noteStartWakeLocked(10200, 101, null, "wakeLock2", null,
BatteryStats.WAKE_TYPE_PARTIAL, false);
mMockClock.realtime = 9000;
List<WakeLockStats.WakeLock> wakeLockStats =
mBatteryStatsImpl.getWakeLockStats().getWakeLocks();
assertThat(wakeLockStats).hasSize(2);
WakeLockStats.WakeLock wakeLock1 = wakeLockStats.stream()
.filter(wl -> wl.uid == 10100 && wl.name.equals("wakeLock1")).findFirst().get();
assertThat(wakeLock1.timesAcquired).isEqualTo(1);
assertThat(wakeLock1.timeHeldMs).isEqualTo(0); // Not currently held
assertThat(wakeLock1.totalTimeHeldMs).isEqualTo(2000); // 3000-1000
WakeLockStats.WakeLock wakeLock2 = wakeLockStats.stream()
.filter(wl -> wl.uid == 10200 && wl.name.equals("wakeLock2")).findFirst().get();
assertThat(wakeLock2.timesAcquired).isEqualTo(2);
assertThat(wakeLock2.timeHeldMs).isEqualTo(3000); // 9000-6000
assertThat(wakeLock2.totalTimeHeldMs).isEqualTo(4000); // (5000-4000) + (9000-6000)
}
@Test
public void testGetBluetoothBatteryStats() {
when(mPowerProfile.getAveragePower(
PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE)).thenReturn(3.0);
mBatteryStatsImpl.setOnBatteryInternal(true);
mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
final WorkSource ws = new WorkSource(10042);
mBatteryStatsImpl.noteBluetoothScanStartedFromSourceLocked(ws, false, 1000, 1000);
mBatteryStatsImpl.noteBluetoothScanStoppedFromSourceLocked(ws, false, 5000, 5000);
mBatteryStatsImpl.noteBluetoothScanStartedFromSourceLocked(ws, true, 6000, 6000);
mBatteryStatsImpl.noteBluetoothScanStoppedFromSourceLocked(ws, true, 9000, 9000);
mBatteryStatsImpl.noteBluetoothScanResultsFromSourceLocked(ws, 42, 9000, 9000);
BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000,
BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 9000, 8000, 12000, 0);
info.setUidTraffic(ImmutableList.of(
new UidTraffic(10042, 3000, 4000),
new UidTraffic(10043, 5000, 8000)));
mBatteryStatsImpl.updateBluetoothStateLocked(info, -1, 1000, 1000);
BluetoothBatteryStats stats =
mBatteryStatsImpl.getBluetoothBatteryStats();
assertThat(stats.getUidStats()).hasSize(2);
final BluetoothBatteryStats.UidStats uidStats =
stats.getUidStats().stream().filter(u -> u.uid == 10042).findFirst().get();
assertThat(uidStats.scanTimeMs).isEqualTo(7000); // 4000+3000
assertThat(uidStats.unoptimizedScanTimeMs).isEqualTo(3000);
assertThat(uidStats.scanResultCount).isEqualTo(42);
assertThat(uidStats.rxTimeMs).isEqualTo(7375); // Some scan time is treated as RX
assertThat(uidStats.txTimeMs).isEqualTo(7666); // Some scan time is treated as TX
}
}