1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.power.stats;
18 
19 import static android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
20 import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
21 import static android.os.BatteryStats.Uid.PROCESS_STATE_CACHED;
22 import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE;
23 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.junit.Assert.assertArrayEquals;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertFalse;
30 import static org.junit.Assert.assertNotNull;
31 import static org.junit.Assert.assertTrue;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.ArgumentMatchers.anyLong;
34 import static org.mockito.ArgumentMatchers.eq;
35 import static org.mockito.Mockito.doAnswer;
36 import static org.mockito.Mockito.when;
37 
38 import android.app.ActivityManager;
39 import android.bluetooth.BluetoothActivityEnergyInfo;
40 import android.bluetooth.UidTraffic;
41 import android.os.BatteryStats;
42 import android.os.BluetoothBatteryStats;
43 import android.os.Parcel;
44 import android.os.WakeLockStats;
45 import android.os.WorkSource;
46 import android.util.SparseArray;
47 import android.view.Display;
48 
49 import androidx.test.filters.LargeTest;
50 import androidx.test.runner.AndroidJUnit4;
51 
52 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
53 import com.android.internal.os.KernelSingleUidTimeReader;
54 import com.android.internal.os.LongArrayMultiStateCounter;
55 import com.android.internal.os.PowerProfile;
56 
57 import com.google.common.collect.ImmutableList;
58 
59 import org.junit.Before;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62 import org.mockito.Mock;
63 import org.mockito.MockitoAnnotations;
64 
65 import java.util.List;
66 
67 @LargeTest
68 @RunWith(AndroidJUnit4.class)
69 @SuppressWarnings("GuardedBy")
70 public class BatteryStatsImplTest {
71     private static final long[] CPU_FREQS = {1, 2, 3, 4, 5};
72     private static final int NUM_CPU_FREQS = CPU_FREQS.length;
73 
74     @Mock
75     private KernelCpuUidFreqTimeReader mKernelUidCpuFreqTimeReader;
76     @Mock
77     private KernelSingleUidTimeReader mKernelSingleUidTimeReader;
78     @Mock
79     private PowerProfile mPowerProfile;
80 
81     private final MockClock mMockClock = new MockClock();
82     private MockBatteryStatsImpl mBatteryStatsImpl;
83 
84     @Before
setUp()85     public void setUp() {
86         MockitoAnnotations.initMocks(this);
87 
88         when(mKernelUidCpuFreqTimeReader.isFastCpuTimesReader()).thenReturn(true);
89         when(mKernelUidCpuFreqTimeReader.readFreqs(any())).thenReturn(CPU_FREQS);
90         when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true);
91         when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true);
92         mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock)
93                 .setPowerProfile(mPowerProfile)
94                 .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader)
95                 .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader);
96     }
97 
98     @Test
testUpdateProcStateCpuTimes()99     public void testUpdateProcStateCpuTimes() {
100         mBatteryStatsImpl.setOnBatteryInternal(true);
101         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
102 
103         final int[] testUids = {10032, 10048, 10145, 10139};
104         final int[] activityManagerProcStates = {
105                 ActivityManager.PROCESS_STATE_RECEIVER,
106                 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
107                 ActivityManager.PROCESS_STATE_TOP,
108                 ActivityManager.PROCESS_STATE_CACHED_EMPTY
109         };
110         final int[] testProcStates = {
111                 PROCESS_STATE_BACKGROUND,
112                 PROCESS_STATE_FOREGROUND_SERVICE,
113                 PROCESS_STATE_TOP,
114                 PROCESS_STATE_CACHED
115         };
116 
117         // Initialize time-in-freq counters
118         mMockClock.realtime = 1000;
119         mMockClock.uptime = 1000;
120         for (int i = 0; i < testUids.length; ++i) {
121             mockKernelSingleUidTimeReader(testUids[i], new long[5]);
122             mBatteryStatsImpl.noteUidProcessStateLocked(testUids[i], activityManagerProcStates[i]);
123         }
124 
125         final long[] timeInFreqs = new long[NUM_CPU_FREQS];
126 
127         // Verify there are no cpu times initially.
128         for (int i = 0; i < testUids.length; ++i) {
129             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUids[i]);
130             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
131                 assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
132                 assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
133             }
134         }
135 
136         // Obtain initial CPU time-in-freq counts
137         final long[][] cpuTimes = {
138                 {349734983, 394982394832L, 909834, 348934, 9838},
139                 {7498, 1239890, 988, 13298, 98980},
140                 {989834, 384098, 98483, 23809, 4984},
141                 {4859048, 348903, 4578967, 5973894, 298549}
142         };
143 
144         mMockClock.realtime += 1000;
145         mMockClock.uptime += 1000;
146 
147         for (int i = 0; i < testUids.length; ++i) {
148             mockKernelSingleUidTimeReader(testUids[i], cpuTimes[i]);
149             mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
150                     mMockClock.realtime, mMockClock.uptime);
151         }
152 
153         for (int i = 0; i < testUids.length; ++i) {
154             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
155             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
156                 final boolean hasTimeInFreq = u.getCpuFreqTimes(timeInFreqs, procState);
157                 if (procState == testProcStates[i]) {
158                     assertArrayEquals("Uid=" + testUids[i], cpuTimes[i], timeInFreqs);
159                 } else {
160                     assertFalse(hasTimeInFreq);
161                 }
162                 assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
163             }
164         }
165 
166         // Accumulate CPU time-in-freq deltas
167         final long[][] delta1 = {
168                 {9589, 148934, 309894, 3098493, 98754},
169                 {21983, 94983, 4983, 9878493, 84854},
170                 {945894, 9089432, 19478, 3834, 7845},
171                 {843895, 43948, 949582, 99, 384}
172         };
173 
174         mMockClock.realtime += 1000;
175         mMockClock.uptime += 1000;
176 
177         for (int i = 0; i < testUids.length; ++i) {
178             long[] newCpuTimes = new long[cpuTimes[i].length];
179             for (int j = 0; j < cpuTimes[i].length; j++) {
180                 newCpuTimes[j] = cpuTimes[i][j] + delta1[i][j];
181             }
182             mockKernelSingleUidTimeReader(testUids[i], newCpuTimes);
183             mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
184                     mMockClock.realtime, mMockClock.uptime);
185         }
186 
187         for (int i = 0; i < testUids.length; ++i) {
188             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
189             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
190                 if (procState == testProcStates[i]) {
191                     long[] expectedCpuTimes = cpuTimes[i].clone();
192                     for (int j = 0; j < expectedCpuTimes.length; ++j) {
193                         expectedCpuTimes[j] += delta1[i][j];
194                     }
195                     assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
196                     assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
197                 } else {
198                     assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
199                 }
200                 assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
201             }
202         }
203 
204         // Validate the on-battery-screen-off counter
205         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, mMockClock.uptime * 1000,
206                 mMockClock.realtime * 1000);
207 
208         final long[][] delta2 = {
209                 {95932, 2943, 49834, 89034, 139},
210                 {349, 89605, 5896, 845, 98444},
211                 {678, 7498, 9843, 889, 4894},
212                 {488, 998, 8498, 394, 574}
213         };
214 
215         mMockClock.realtime += 1000;
216         mMockClock.uptime += 1000;
217 
218         for (int i = 0; i < testUids.length; ++i) {
219             long[] newCpuTimes = new long[cpuTimes[i].length];
220             for (int j = 0; j < cpuTimes[i].length; j++) {
221                 newCpuTimes[j] = cpuTimes[i][j] + delta1[i][j] + delta2[i][j];
222             }
223             mockKernelSingleUidTimeReader(testUids[i], newCpuTimes);
224             mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
225                     mMockClock.realtime, mMockClock.uptime);
226         }
227 
228         for (int i = 0; i < testUids.length; ++i) {
229             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
230             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
231                 if (procState == testProcStates[i]) {
232                     long[] expectedCpuTimes = cpuTimes[i].clone();
233                     for (int j = 0; j < expectedCpuTimes.length; ++j) {
234                         expectedCpuTimes[j] += delta1[i][j] + delta2[i][j];
235                     }
236                     assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
237                     assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
238                     assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
239                     assertArrayEquals("Uid=" + testUids[i], delta2[i], timeInFreqs);
240                 } else {
241                     assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
242                     assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
243                 }
244             }
245         }
246 
247         // Verify handling of isolated UIDs - their time-in-freq must be directly
248         // added to that of the parent UID's.  The proc state of the isolated UID is
249         // assumed to be the same as that of the parent UID, so there is no per-state
250         // data for isolated UIDs.
251         final long[][] delta3 = {
252                 {98545, 95768795, 76586, 548945, 57846},
253                 {788876, 586, 578459, 8776984, 9578923},
254                 {3049509483598l, 4597834, 377654, 94589035, 7854},
255                 {9493, 784, 99895, 8974893, 9879843}
256         };
257 
258         mMockClock.realtime += 1000;
259         mMockClock.uptime += 1000;
260 
261         final int parentUid = testUids[1];
262         final int childUid = 99099;
263         addIsolatedUid(parentUid, childUid);
264         final long[] isolatedUidCpuTimes = {495784, 398473, 4895, 4905, 30984093};
265         mockKernelSingleUidTimeReader(childUid, isolatedUidCpuTimes, isolatedUidCpuTimes);
266 
267         for (int i = 0; i < testUids.length; ++i) {
268             long[] newCpuTimes = new long[cpuTimes[i].length];
269             for (int j = 0; j < cpuTimes[i].length; j++) {
270                 newCpuTimes[j] = cpuTimes[i][j] + delta1[i][j] + delta2[i][j] + delta3[i][j];
271             }
272             mockKernelSingleUidTimeReader(testUids[i], newCpuTimes);
273             mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
274                     mMockClock.realtime, mMockClock.uptime);
275         }
276 
277         for (int i = 0; i < testUids.length; ++i) {
278             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
279             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
280                 if (procState == testProcStates[i]) {
281                     long[] expectedCpuTimes = cpuTimes[i].clone();
282                     for (int j = 0; j < expectedCpuTimes.length; ++j) {
283                         expectedCpuTimes[j] += delta1[i][j] + delta2[i][j] + delta3[i][j]
284                                 + (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
285                     }
286                     assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
287                     assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
288                     long[] expectedScreenOffTimes = delta2[i].clone();
289                     for (int j = 0; j < expectedScreenOffTimes.length; ++j) {
290                         expectedScreenOffTimes[j] += delta3[i][j]
291                                 + (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
292                     }
293                     assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
294                     assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes, timeInFreqs);
295                 } else {
296                     assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
297                     assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
298                 }
299             }
300         }
301     }
302 
303     @Test
testUpdateCpuTimesForAllUids()304     public void testUpdateCpuTimesForAllUids() {
305         mBatteryStatsImpl.setOnBatteryInternal(false);
306         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
307 
308         mMockClock.realtime = 1000;
309         mMockClock.uptime = 1000;
310 
311         final int[] testUids = {10032, 10048, 10145, 10139};
312         final int[] testProcStates = {
313                 PROCESS_STATE_BACKGROUND,
314                 PROCESS_STATE_FOREGROUND_SERVICE,
315                 PROCESS_STATE_TOP,
316                 PROCESS_STATE_CACHED
317         };
318 
319         for (int i = 0; i < testUids.length; ++i) {
320             BatteryStatsImpl.Uid uid = mBatteryStatsImpl.getUidStatsLocked(testUids[i]);
321             uid.setProcessStateForTest(testProcStates[i], mMockClock.elapsedRealtime());
322             mockKernelSingleUidTimeReader(testUids[i], new long[NUM_CPU_FREQS]);
323             mBatteryStatsImpl.updateProcStateCpuTimesLocked(testUids[i],
324                     mMockClock.elapsedRealtime(), mMockClock.uptime);
325         }
326 
327         final SparseArray<long[]> allUidCpuTimes = new SparseArray<>();
328         long[][] allCpuTimes = {
329                 {938483, 4985984, 439893},
330                 {499, 94904, 27694},
331                 {302949085, 39789473, 34792839},
332                 {9809485, 9083475, 347889834},
333         };
334         for (int i = 0; i < testUids.length; ++i) {
335             allUidCpuTimes.put(testUids[i], allCpuTimes[i]);
336         }
337         when(mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs()).thenReturn(allUidCpuTimes);
338         long[][] expectedCpuTimes = {
339                 {843598745, 397843, 32749, 99854, 23454},
340                 {9834, 5885, 487589, 394, 93933},
341                 {203984, 439, 9859, 30948, 49494},
342                 {9389, 858, 239, 349, 50505}
343         };
344         for (int i = 0; i < testUids.length; ++i) {
345             mockKernelSingleUidTimeReader(testUids[i], expectedCpuTimes[i]);
346         }
347 
348         mMockClock.realtime += 1000;
349         mMockClock.uptime += 1000;
350 
351         mBatteryStatsImpl.updateCpuTimesForAllUids();
352 
353         final long[] timeInFreqs = new long[NUM_CPU_FREQS];
354 
355         for (int i = 0; i < testUids.length; ++i) {
356             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
357             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
358                 if (procState == testProcStates[i]) {
359                     assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
360                     assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i], timeInFreqs);
361                 } else {
362                     assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
363                 }
364                 assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
365             }
366         }
367     }
368 
mockKernelSingleUidTimeReader(int testUid, long[] cpuTimes)369     private void mockKernelSingleUidTimeReader(int testUid, long[] cpuTimes) {
370         doAnswer(invocation -> {
371             LongArrayMultiStateCounter counter = invocation.getArgument(1);
372             long timestampMs = invocation.getArgument(2);
373             LongArrayMultiStateCounter.LongArrayContainer container =
374                     new LongArrayMultiStateCounter.LongArrayContainer(NUM_CPU_FREQS);
375             container.setValues(cpuTimes);
376             counter.updateValues(container, timestampMs);
377             return null;
378         }).when(mKernelSingleUidTimeReader).addDelta(eq(testUid),
379                 any(LongArrayMultiStateCounter.class), anyLong());
380     }
381 
mockKernelSingleUidTimeReader(int testUid, long[] cpuTimes, long[] delta)382     private void mockKernelSingleUidTimeReader(int testUid, long[] cpuTimes, long[] delta) {
383         doAnswer(invocation -> {
384             LongArrayMultiStateCounter counter = invocation.getArgument(1);
385             long timestampMs = invocation.getArgument(2);
386             LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
387                     invocation.getArgument(3);
388 
389             LongArrayMultiStateCounter.LongArrayContainer container =
390                     new LongArrayMultiStateCounter.LongArrayContainer(NUM_CPU_FREQS);
391             container.setValues(cpuTimes);
392             counter.updateValues(container, timestampMs);
393             if (deltaContainer != null) {
394                 deltaContainer.setValues(delta);
395             }
396             return null;
397         }).when(mKernelSingleUidTimeReader).addDelta(eq(testUid),
398                 any(LongArrayMultiStateCounter.class), anyLong(),
399                 any(LongArrayMultiStateCounter.LongArrayContainer.class));
400     }
401 
402     @Test
testMulticastWakelockAcqRel()403     public void testMulticastWakelockAcqRel() {
404         final int testUid = 10032;
405         final int acquireTimeMs = 1000;
406         final int releaseTimeMs = 1005;
407         final int currentTimeMs = 1011;
408 
409         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
410 
411         // Create a Uid Object
412         final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
413         assertNotNull(u);
414 
415         // Acquire and release the lock
416         u.noteWifiMulticastEnabledLocked(acquireTimeMs);
417         u.noteWifiMulticastDisabledLocked(releaseTimeMs);
418 
419         // Get the total acquisition time
420         long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
421                 BatteryStats.STATS_SINCE_CHARGED);
422         assertEquals("Miscalculations of Multicast wakelock acquisition time",
423                 (releaseTimeMs - acquireTimeMs) * 1000, totalTime);
424     }
425 
426     @Test
testMulticastWakelockAcqNoRel()427     public void testMulticastWakelockAcqNoRel() {
428         final int testUid = 10032;
429         final int acquireTimeMs = 1000;
430         final int currentTimeMs = 1011;
431 
432         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
433 
434         // Create a Uid Object
435         final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
436         assertNotNull(u);
437 
438         // Acquire the lock
439         u.noteWifiMulticastEnabledLocked(acquireTimeMs);
440 
441         // Get the total acquisition time
442         long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
443                 BatteryStats.STATS_SINCE_CHARGED);
444         assertEquals("Miscalculations of Multicast wakelock acquisition time",
445                 (currentTimeMs - acquireTimeMs) * 1000, totalTime);
446     }
447 
448     @Test
testMulticastWakelockAcqAcqRelRel()449     public void testMulticastWakelockAcqAcqRelRel() {
450         final int testUid = 10032;
451         final int acquireTimeMs_1 = 1000;
452         final int acquireTimeMs_2 = 1002;
453 
454         final int releaseTimeMs_1 = 1005;
455         final int releaseTimeMs_2 = 1009;
456         final int currentTimeMs = 1011;
457 
458         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
459 
460         // Create a Uid Object
461         final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
462         assertNotNull(u);
463 
464         // Acquire and release the lock (twice in nested way)
465         u.noteWifiMulticastEnabledLocked(acquireTimeMs_1);
466         u.noteWifiMulticastEnabledLocked(acquireTimeMs_2);
467 
468         u.noteWifiMulticastDisabledLocked(releaseTimeMs_1);
469         u.noteWifiMulticastDisabledLocked(releaseTimeMs_2);
470 
471         // Get the total acquisition time
472         long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
473                 BatteryStats.STATS_SINCE_CHARGED);
474         assertEquals("Miscalculations of Multicast wakelock acquisition time",
475                 (releaseTimeMs_2 - acquireTimeMs_1) * 1000, totalTime);
476     }
477 
478     @Test
testMulticastWakelockAcqRelAcqRel()479     public void testMulticastWakelockAcqRelAcqRel() {
480         final int testUid = 10032;
481         final int acquireTimeMs_1 = 1000;
482         final int acquireTimeMs_2 = 1005;
483 
484         final int releaseTimeMs_1 = 1002;
485         final int releaseTimeMs_2 = 1009;
486         final int currentTimeMs = 1011;
487 
488         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
489 
490         // Create a Uid Object
491         final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid);
492         assertNotNull(u);
493 
494         // Acquire and release the lock (twice)
495         u.noteWifiMulticastEnabledLocked(acquireTimeMs_1);
496         u.noteWifiMulticastDisabledLocked(releaseTimeMs_1);
497 
498         u.noteWifiMulticastEnabledLocked(acquireTimeMs_2);
499         u.noteWifiMulticastDisabledLocked(releaseTimeMs_2);
500 
501         // Get the total acquisition time
502         long totalTime = u.getWifiMulticastTime(currentTimeMs * 1000,
503                 BatteryStats.STATS_SINCE_CHARGED);
504         assertEquals("Miscalculations of Multicast wakelock acquisition time",
505                 ((releaseTimeMs_1 - acquireTimeMs_1) + (releaseTimeMs_2 - acquireTimeMs_2))
506                         * 1000, totalTime);
507     }
508 
addIsolatedUid(int parentUid, int childUid)509     private void addIsolatedUid(int parentUid, int childUid) {
510         final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(parentUid);
511         u.addIsolatedUid(childUid);
512     }
513 
514     @Test
testGetWakeLockStats()515     public void testGetWakeLockStats() {
516         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
517 
518         // First wakelock, acquired once, not currently held
519         mMockClock.realtime = 1000;
520         mBatteryStatsImpl.noteStartWakeLocked(10100, 100, null, "wakeLock1", null,
521                 BatteryStats.WAKE_TYPE_PARTIAL, false);
522 
523         mMockClock.realtime = 3000;
524         mBatteryStatsImpl.noteStopWakeLocked(10100, 100, null, "wakeLock1", null,
525                 BatteryStats.WAKE_TYPE_PARTIAL);
526 
527         // Second wakelock, acquired twice, still held
528         mMockClock.realtime = 4000;
529         mBatteryStatsImpl.noteStartWakeLocked(10200, 101, null, "wakeLock2", null,
530                 BatteryStats.WAKE_TYPE_PARTIAL, false);
531 
532         mMockClock.realtime = 5000;
533         mBatteryStatsImpl.noteStopWakeLocked(10200, 101, null, "wakeLock2", null,
534                 BatteryStats.WAKE_TYPE_PARTIAL);
535 
536         mMockClock.realtime = 6000;
537         mBatteryStatsImpl.noteStartWakeLocked(10200, 101, null, "wakeLock2", null,
538                 BatteryStats.WAKE_TYPE_PARTIAL, false);
539 
540         mMockClock.realtime = 9000;
541 
542         List<WakeLockStats.WakeLock> wakeLockStats =
543                 mBatteryStatsImpl.getWakeLockStats().getWakeLocks();
544         assertThat(wakeLockStats).hasSize(2);
545 
546         WakeLockStats.WakeLock wakeLock1 = wakeLockStats.stream()
547                 .filter(wl -> wl.uid == 10100 && wl.name.equals("wakeLock1")).findFirst().get();
548 
549         assertThat(wakeLock1.timesAcquired).isEqualTo(1);
550         assertThat(wakeLock1.timeHeldMs).isEqualTo(0);  // Not currently held
551         assertThat(wakeLock1.totalTimeHeldMs).isEqualTo(2000); // 3000-1000
552 
553         WakeLockStats.WakeLock wakeLock2 = wakeLockStats.stream()
554                 .filter(wl -> wl.uid == 10200 && wl.name.equals("wakeLock2")).findFirst().get();
555 
556         assertThat(wakeLock2.timesAcquired).isEqualTo(2);
557         assertThat(wakeLock2.timeHeldMs).isEqualTo(3000);  // 9000-6000
558         assertThat(wakeLock2.totalTimeHeldMs).isEqualTo(4000); // (5000-4000) + (9000-6000)
559     }
560 
561     @Test
testGetBluetoothBatteryStats()562     public void testGetBluetoothBatteryStats() {
563         when(mPowerProfile.getAveragePower(
564                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE)).thenReturn(3.0);
565         mBatteryStatsImpl.setOnBatteryInternal(true);
566         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
567 
568         final WorkSource ws = new WorkSource(10042);
569         mBatteryStatsImpl.noteBluetoothScanStartedFromSourceLocked(ws, false, 1000, 1000);
570         mBatteryStatsImpl.noteBluetoothScanStoppedFromSourceLocked(ws, false, 5000, 5000);
571         mBatteryStatsImpl.noteBluetoothScanStartedFromSourceLocked(ws, true, 6000, 6000);
572         mBatteryStatsImpl.noteBluetoothScanStoppedFromSourceLocked(ws, true, 9000, 9000);
573         mBatteryStatsImpl.noteBluetoothScanResultsFromSourceLocked(ws, 42, 9000, 9000);
574 
575         BluetoothActivityEnergyInfo info = createBluetoothActivityEnergyInfo(
576                 /* timestamp= */ 1000,
577                 /* controllerTxTimeMs= */ 9000,
578                 /* controllerRxTimeMs= */ 8000,
579                 /* controllerIdleTimeMs= */ 12000,
580                 /* controllerEnergyUsed= */ 0,
581                 createUidTraffic(/* appUid= */ 10042, /* rxBytes= */ 3000, /* txBytes= */ 4000),
582                 createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 5000, /* txBytes= */ 8000));
583 
584         mBatteryStatsImpl.updateBluetoothStateLocked(info, -1, 1000, 1000);
585 
586         BluetoothBatteryStats stats =
587                 mBatteryStatsImpl.getBluetoothBatteryStats();
588         assertThat(stats.getUidStats()).hasSize(2);
589 
590         final BluetoothBatteryStats.UidStats uidStats =
591                 stats.getUidStats().stream().filter(u -> u.uid == 10042).findFirst().get();
592         assertThat(uidStats.scanTimeMs).isEqualTo(7000);  // 4000+3000
593         assertThat(uidStats.unoptimizedScanTimeMs).isEqualTo(3000);
594         assertThat(uidStats.scanResultCount).isEqualTo(42);
595         assertThat(uidStats.rxTimeMs).isEqualTo(7375);  // Some scan time is treated as RX
596         assertThat(uidStats.txTimeMs).isEqualTo(7666);  // Some scan time is treated as TX
597     }
598 
599     /** A regression test for b/266128651 */
600     @Test
testGetNetworkActivityBytes_multipleUpdates()601     public void testGetNetworkActivityBytes_multipleUpdates() {
602         when(mPowerProfile.getAveragePower(
603                 PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE)).thenReturn(3.0);
604         mBatteryStatsImpl.setOnBatteryInternal(true);
605         mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
606 
607         BluetoothActivityEnergyInfo info1 = createBluetoothActivityEnergyInfo(
608                 /* timestamp= */ 10000,
609                 /* controllerTxTimeMs= */ 9000,
610                 /* controllerRxTimeMs= */ 8000,
611                 /* controllerIdleTimeMs= */ 2000,
612                 /* controllerEnergyUsed= */ 0,
613                 createUidTraffic(/* appUid= */ 10042, /* rxBytes= */ 3000, /* txBytes= */ 4000),
614                 createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 5000, /* txBytes= */ 8000));
615 
616         mBatteryStatsImpl.updateBluetoothStateLocked(info1, -1, 1000, 1000);
617 
618         long totalRx1 = mBatteryStatsImpl.getNetworkActivityBytes(
619                 BatteryStats.NETWORK_BT_RX_DATA, BatteryStats.STATS_SINCE_CHARGED);
620         long totalTx1 = mBatteryStatsImpl.getNetworkActivityBytes(
621                 BatteryStats.NETWORK_BT_TX_DATA, BatteryStats.STATS_SINCE_CHARGED);
622 
623         assertThat(totalRx1).isEqualTo(8000);  // 3000 + 5000
624         assertThat(totalTx1).isEqualTo(12000);  // 4000 + 8000
625 
626         BluetoothActivityEnergyInfo info2 = createBluetoothActivityEnergyInfo(
627                 /* timestamp= */ 20000,
628                 /* controllerTxTimeMs= */ 19000,
629                 /* controllerRxTimeMs= */ 18000,
630                 /* controllerIdleTimeMs= */ 3000,
631                 /* controllerEnergyUsed= */ 0,
632                 createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 6000, /* txBytes= */ 9500),
633                 createUidTraffic(/* appUid= */ 10044, /* rxBytes= */ 7000, /* txBytes= */ 9000));
634 
635         mBatteryStatsImpl.updateBluetoothStateLocked(info2, -1, 2000, 2000);
636 
637         long totalRx2 = mBatteryStatsImpl.getNetworkActivityBytes(
638                 BatteryStats.NETWORK_BT_RX_DATA, BatteryStats.STATS_SINCE_CHARGED);
639         long totalTx2 = mBatteryStatsImpl.getNetworkActivityBytes(
640                 BatteryStats.NETWORK_BT_TX_DATA, BatteryStats.STATS_SINCE_CHARGED);
641 
642         assertThat(totalRx2).isEqualTo(16000);  // 3000 + 6000 (updated) + 7000 (new)
643         assertThat(totalTx2).isEqualTo(22500);  // 4000 + 9500 (updated) + 9000 (new)
644 
645         BluetoothActivityEnergyInfo info3 = createBluetoothActivityEnergyInfo(
646                 /* timestamp= */ 30000,
647                 /* controllerTxTimeMs= */ 20000,
648                 /* controllerRxTimeMs= */ 20000,
649                 /* controllerIdleTimeMs= */ 4000,
650                 /* controllerEnergyUsed= */ 0,
651                 createUidTraffic(/* appUid= */ 10043, /* rxBytes= */ 7000, /* txBytes= */ 9900),
652                 createUidTraffic(/* appUid= */ 10044, /* rxBytes= */ 8000, /* txBytes= */ 10000));
653 
654         mBatteryStatsImpl.updateBluetoothStateLocked(info3, -1, 2000, 2000);
655 
656         long totalRx3 = mBatteryStatsImpl.getNetworkActivityBytes(
657                 BatteryStats.NETWORK_BT_RX_DATA, BatteryStats.STATS_SINCE_CHARGED);
658         long totalTx3 = mBatteryStatsImpl.getNetworkActivityBytes(
659                 BatteryStats.NETWORK_BT_TX_DATA, BatteryStats.STATS_SINCE_CHARGED);
660 
661         assertThat(totalRx3).isEqualTo(18000);  // 3000 + 7000 (updated) + 8000 (updated)
662         assertThat(totalTx3).isEqualTo(23900);  // 4000 + 9900 (updated) + 10000 (updated)
663     }
664 
createUidTraffic(int appUid, long rxBytes, long txBytes)665     private UidTraffic createUidTraffic(int appUid, long rxBytes, long txBytes) {
666         final Parcel parcel = Parcel.obtain();
667         parcel.writeInt(appUid); // mAppUid
668         parcel.writeLong(rxBytes); // mRxBytes
669         parcel.writeLong(txBytes); // mTxBytes
670         parcel.setDataPosition(0);
671         UidTraffic uidTraffic = UidTraffic.CREATOR.createFromParcel(parcel);
672         parcel.recycle();
673         return uidTraffic;
674     }
675 
createBluetoothActivityEnergyInfo( long timestamp, long controllerTxTimeMs, long controllerRxTimeMs, long controllerIdleTimeMs, long controllerEnergyUsed, UidTraffic... uidTraffic)676     private BluetoothActivityEnergyInfo createBluetoothActivityEnergyInfo(
677             long timestamp,
678             long controllerTxTimeMs,
679             long controllerRxTimeMs,
680             long controllerIdleTimeMs,
681             long controllerEnergyUsed,
682             UidTraffic... uidTraffic) {
683         Parcel parcel = Parcel.obtain();
684         parcel.writeLong(timestamp); // mTimestamp
685         parcel.writeInt(
686                 BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE); // mBluetoothStackState
687         parcel.writeLong(controllerTxTimeMs); // mControllerTxTimeMs;
688         parcel.writeLong(controllerRxTimeMs); // mControllerRxTimeMs;
689         parcel.writeLong(controllerIdleTimeMs); // mControllerIdleTimeMs;
690         parcel.writeLong(controllerEnergyUsed); // mControllerEnergyUsed;
691         parcel.writeTypedList(ImmutableList.copyOf(uidTraffic)); // mUidTraffic
692         parcel.setDataPosition(0);
693 
694         BluetoothActivityEnergyInfo info =
695                 BluetoothActivityEnergyInfo.CREATOR.createFromParcel(parcel);
696         parcel.recycle();
697         return info;
698     }
699 }
700