1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
20 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
21 import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
22 
23 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
24 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
25 
26 import android.app.ActivityManager;
27 import android.os.BatteryStats;
28 import android.os.BatteryStats.HistoryItem;
29 import android.os.BatteryStats.Uid.Sensor;
30 import android.os.Process;
31 import android.os.UserHandle;
32 import android.os.WorkSource;
33 import android.util.SparseLongArray;
34 import android.view.Display;
35 
36 import androidx.test.filters.SmallTest;
37 
38 import com.android.internal.os.BatteryStatsImpl.DualTimer;
39 import com.android.internal.os.BatteryStatsImpl.Uid;
40 import com.android.internal.power.MeasuredEnergyStats;
41 
42 import junit.framework.TestCase;
43 
44 import java.util.Arrays;
45 import java.util.HashMap;
46 import java.util.Map;
47 import java.util.function.IntConsumer;
48 
49 /**
50  * Test various BatteryStatsImpl noteStart methods.
51  *
52  * Build/Install/Run: bit FrameworksCoreTests:com.android.internal.os.BatteryStatsNoteTest
53  *
54  * Alternatively,
55  * Build: m FrameworksCoreTests
56  * Install: adb install -r \
57  *      ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
58  * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsNoteTest -w \
59  *      com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
60  */
61 public class BatteryStatsNoteTest extends TestCase {
62 
63     private static final int UID = 10500;
64     private static final int ISOLATED_APP_ID = Process.FIRST_ISOLATED_UID + 23;
65     private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID);
66     private static final WorkSource WS = new WorkSource(UID);
67 
68     /**
69      * Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
70      */
71     @SmallTest
testNoteBluetoothScanResultLocked()72     public void testNoteBluetoothScanResultLocked() throws Exception {
73         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks());
74         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
75         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
76 
77         bi.noteBluetoothScanResultsFromSourceLocked(WS, 1);
78         bi.noteBluetoothScanResultsFromSourceLocked(WS, 100);
79         assertEquals(101,
80                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
81                         .getCountLocked(STATS_SINCE_CHARGED));
82         BatteryStats.Counter bgCntr = bi.getUidStats().get(UID).getBluetoothScanResultBgCounter();
83         if (bgCntr != null) {
84             assertEquals(0, bgCntr.getCountLocked(STATS_SINCE_CHARGED));
85         }
86 
87         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
88         bi.noteBluetoothScanResultsFromSourceLocked(WS, 17);
89         assertEquals(101 + 17,
90                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
91                         .getCountLocked(STATS_SINCE_CHARGED));
92         assertEquals(17,
93                 bi.getUidStats().get(UID).getBluetoothScanResultBgCounter()
94                         .getCountLocked(STATS_SINCE_CHARGED));
95     }
96 
97     /**
98      * Test BatteryStatsImpl.Uid.noteStartWakeLocked.
99      */
100     @SmallTest
testNoteStartWakeLocked()101     public void testNoteStartWakeLocked() throws Exception {
102         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
103         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
104 
105         int pid = 10;
106         String name = "name";
107 
108         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
109         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
110         bi.getUidStatsLocked(UID)
111                 .noteStartWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
112 
113         clocks.realtime = clocks.uptime = 100;
114         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
115 
116         clocks.realtime = clocks.uptime = 220;
117         bi.getUidStatsLocked(UID).noteStopWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
118 
119         BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
120                 .getAggregatedPartialWakelockTimer();
121         long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
122         long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
123         assertEquals(220_000, actualTime);
124         assertEquals(120_000, bgTime);
125     }
126 
127     /**
128      * Test BatteryStatsImpl.Uid.noteStartWakeLocked for an isolated uid.
129      */
130     @SmallTest
testNoteStartWakeLocked_isolatedUid()131     public void testNoteStartWakeLocked_isolatedUid() throws Exception {
132         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
133         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
134 
135         int pid = 10;
136         String name = "name";
137         String historyName = "historyName";
138 
139         WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain();
140         isolatedWorkChain.addNode(ISOLATED_UID, name);
141 
142         // Map ISOLATED_UID to UID.
143         bi.addIsolatedUidLocked(ISOLATED_UID, UID);
144 
145         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
146         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
147         bi.noteStartWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
148                 WAKE_TYPE_PARTIAL, false);
149 
150         clocks.realtime = clocks.uptime = 100;
151         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
152 
153         clocks.realtime = clocks.uptime = 220;
154         bi.noteStopWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
155                 WAKE_TYPE_PARTIAL);
156 
157         // ISOLATED_UID wakelock time should be attributed to UID.
158         BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
159                 .getAggregatedPartialWakelockTimer();
160         long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
161         long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
162         assertEquals(220_000, actualTime);
163         assertEquals(120_000, bgTime);
164     }
165 
166     /**
167      * Test BatteryStatsImpl.Uid.noteStartWakeLocked for an isolated uid, with a race where the
168      * isolated uid is removed from batterystats before the wakelock has been stopped.
169      */
170     @SmallTest
testNoteStartWakeLocked_isolatedUidRace()171     public void testNoteStartWakeLocked_isolatedUidRace() throws Exception {
172         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
173         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
174 
175         int pid = 10;
176         String name = "name";
177         String historyName = "historyName";
178 
179         WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain();
180         isolatedWorkChain.addNode(ISOLATED_UID, name);
181 
182         // Map ISOLATED_UID to UID.
183         bi.addIsolatedUidLocked(ISOLATED_UID, UID);
184 
185         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
186         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
187         bi.noteStartWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
188                 WAKE_TYPE_PARTIAL, false);
189 
190         clocks.realtime = clocks.uptime = 100;
191         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
192 
193         clocks.realtime = clocks.uptime = 150;
194         bi.maybeRemoveIsolatedUidLocked(ISOLATED_UID, clocks.realtime, clocks.uptime);
195 
196         clocks.realtime = clocks.uptime = 220;
197         bi.noteStopWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
198                 WAKE_TYPE_PARTIAL);
199 
200         // ISOLATED_UID wakelock time should be attributed to UID.
201         BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
202                 .getAggregatedPartialWakelockTimer();
203         long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
204         long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
205         assertEquals(220_000, actualTime);
206         assertEquals(120_000, bgTime);
207     }
208 
209 
210     /**
211      * Test BatteryStatsImpl.noteUidProcessStateLocked.
212      */
213     @SmallTest
testNoteUidProcessStateLocked()214     public void testNoteUidProcessStateLocked() throws Exception {
215         final MockClocks clocks = new MockClocks();
216         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
217 
218         // map of ActivityManager process states and how long to simulate run time in each state
219         Map<Integer, Integer> stateRuntimeMap = new HashMap<Integer, Integer>();
220         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TOP, 1111);
221         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 1234);
222         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 2468);
223         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TOP_SLEEPING, 7531);
224         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 4455);
225         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 1337);
226         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BACKUP, 90210);
227         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_HEAVY_WEIGHT, 911);
228         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_SERVICE, 404);
229         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_RECEIVER, 31459);
230         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_HOME, 1123);
231         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_LAST_ACTIVITY, 5813);
232         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 867);
233         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT, 5309);
234         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_EMPTY, 42);
235 
236         bi.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
237 
238         for (Map.Entry<Integer, Integer> entry : stateRuntimeMap.entrySet()) {
239             bi.noteUidProcessStateLocked(UID, entry.getKey());
240             clocks.realtime += entry.getValue();
241             clocks.uptime = clocks.realtime;
242         }
243 
244         long actualRunTimeUs;
245         long expectedRunTimeMs;
246         long elapsedTimeUs = clocks.realtime * 1000;
247         BatteryStats.Uid uid = bi.getUidStats().get(UID);
248 
249         // compare runtime of process states to the Uid process states they map to
250         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP, elapsedTimeUs,
251                 STATS_SINCE_CHARGED);
252         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP);
253         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
254 
255         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
256                 elapsedTimeUs, STATS_SINCE_CHARGED);
257         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
258         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
259 
260         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
261                 elapsedTimeUs, STATS_SINCE_CHARGED);
262         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
263         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
264 
265         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND,
266                 elapsedTimeUs, STATS_SINCE_CHARGED);
267         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
268                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
269         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
270 
271         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND,
272                 elapsedTimeUs, STATS_SINCE_CHARGED);
273         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND)
274                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BACKUP)
275                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_SERVICE)
276                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_RECEIVER);
277         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
278 
279         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_CACHED,
280                 elapsedTimeUs, STATS_SINCE_CHARGED);
281         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_HOME)
282                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_LAST_ACTIVITY)
283                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY)
284                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT)
285                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
286         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
287 
288         // Special check for foreground service timer
289         actualRunTimeUs = uid.getForegroundServiceTimer().getTotalTimeLocked(elapsedTimeUs,
290                 STATS_SINCE_CHARGED);
291         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
292         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
293     }
294 
295     /**
296      * Test BatteryStatsImpl.updateTimeBasesLocked.
297      */
298     @SmallTest
testUpdateTimeBasesLocked()299     public void testUpdateTimeBasesLocked() throws Exception {
300         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
301         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
302 
303         bi.updateTimeBasesLocked(false, Display.STATE_OFF, 0, 0);
304         assertFalse(bi.getOnBatteryTimeBase().isRunning());
305         bi.updateTimeBasesLocked(false, Display.STATE_DOZE, 10, 10);
306         assertFalse(bi.getOnBatteryTimeBase().isRunning());
307         bi.updateTimeBasesLocked(false, Display.STATE_ON, 20, 20);
308         assertFalse(bi.getOnBatteryTimeBase().isRunning());
309 
310         bi.updateTimeBasesLocked(true, Display.STATE_ON, 30, 30);
311         assertTrue(bi.getOnBatteryTimeBase().isRunning());
312         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
313         bi.updateTimeBasesLocked(true, Display.STATE_DOZE, 40, 40);
314         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
315         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 40, 40);
316         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
317     }
318 
319     /**
320      * Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly.
321      */
322     @SmallTest
testNoteScreenStateLocked()323     public void testNoteScreenStateLocked() throws Exception {
324         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
325         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
326         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
327 
328         bi.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
329         bi.noteScreenStateLocked(0, Display.STATE_ON);
330 
331         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
332         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
333         assertEquals(Display.STATE_DOZE, bi.getScreenState());
334         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
335 
336         bi.noteScreenStateLocked(0, Display.STATE_ON);
337         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
338         assertEquals(Display.STATE_ON, bi.getScreenState());
339         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
340 
341         bi.noteScreenStateLocked(0, Display.STATE_OFF);
342         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
343         assertEquals(Display.STATE_OFF, bi.getScreenState());
344         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
345 
346         bi.noteScreenStateLocked(0, Display.STATE_DOZE_SUSPEND);
347         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
348         assertEquals(Display.STATE_DOZE_SUSPEND, bi.getScreenState());
349         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
350 
351         // STATE_VR note should map to STATE_ON.
352         bi.noteScreenStateLocked(0, Display.STATE_VR);
353         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
354         assertEquals(Display.STATE_ON, bi.getScreenState());
355         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
356 
357         // STATE_ON_SUSPEND note should map to STATE_ON.
358         bi.noteScreenStateLocked(0, Display.STATE_ON_SUSPEND);
359         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
360         assertEquals(Display.STATE_ON, bi.getScreenState());
361         // Transition from ON to ON state should not cause an External Sync
362         assertEquals(0, bi.getAndClearExternalStatsSyncFlags());
363     }
364 
365     /**
366      * Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly for
367      * multi display devices
368      */
369     @SmallTest
testNoteScreenStateLocked_multiDisplay()370     public void testNoteScreenStateLocked_multiDisplay() throws Exception {
371         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
372         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
373         bi.setDisplayCountLocked(2);
374         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
375 
376         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
377         bi.noteScreenStateLocked(0, Display.STATE_OFF);
378         bi.noteScreenStateLocked(1, Display.STATE_OFF);
379 
380         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
381         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
382         assertEquals(Display.STATE_DOZE, bi.getScreenState());
383         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
384 
385         bi.noteScreenStateLocked(0, Display.STATE_ON);
386         assertEquals(Display.STATE_ON, bi.getScreenState());
387         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
388         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
389 
390         bi.noteScreenStateLocked(0, Display.STATE_OFF);
391         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
392         assertEquals(Display.STATE_OFF, bi.getScreenState());
393         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
394 
395         bi.noteScreenStateLocked(0, Display.STATE_DOZE_SUSPEND);
396         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
397         assertEquals(Display.STATE_DOZE_SUSPEND, bi.getScreenState());
398         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
399 
400         // STATE_VR note should map to STATE_ON.
401         bi.noteScreenStateLocked(0, Display.STATE_VR);
402         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
403         assertEquals(Display.STATE_ON, bi.getScreenState());
404         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
405 
406         // STATE_ON_SUSPEND note should map to STATE_ON.
407         bi.noteScreenStateLocked(0, Display.STATE_ON_SUSPEND);
408         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
409         assertEquals(Display.STATE_ON, bi.getScreenState());
410         // Transition from ON to ON state should not cause an External Sync
411         assertEquals(0, bi.getAndClearExternalStatsSyncFlags());
412 
413         bi.noteScreenStateLocked(1, Display.STATE_DOZE);
414         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
415         // Should remain STATE_ON since display0 is still on.
416         assertEquals(Display.STATE_ON, bi.getScreenState());
417         // Overall screen state did not change, so no need to sync CPU stats.
418         assertEquals(UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
419 
420         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
421         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
422         assertEquals(Display.STATE_DOZE, bi.getScreenState());
423         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
424 
425         bi.noteScreenStateLocked(0, Display.STATE_ON);
426         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
427         assertEquals(Display.STATE_ON, bi.getScreenState());
428         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
429 
430         bi.noteScreenStateLocked(0, Display.STATE_OFF);
431         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
432         assertEquals(Display.STATE_DOZE, bi.getScreenState());
433         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
434 
435         bi.noteScreenStateLocked(0, Display.STATE_DOZE_SUSPEND);
436         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
437         assertEquals(Display.STATE_DOZE, bi.getScreenState());
438         // Overall screen state did not change, so no need to sync CPU stats.
439         assertEquals(UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
440 
441         bi.noteScreenStateLocked(0, Display.STATE_VR);
442         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
443         assertEquals(Display.STATE_ON, bi.getScreenState());
444         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
445 
446         bi.noteScreenStateLocked(0, Display.STATE_ON_SUSPEND);
447         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
448         assertEquals(Display.STATE_ON, bi.getScreenState());
449         assertEquals(0, bi.getAndClearExternalStatsSyncFlags());
450     }
451 
452     /*
453      * Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly.
454      *
455      * Unknown and doze should both be subset of off state
456      *
457      * Timeline 0----100----200----310----400------------1000
458      * Unknown         -------
459      * On                     -------
460      * Off             -------       ----------------------
461      * Doze                                ----------------
462      */
463     @SmallTest
testNoteScreenStateTimersLocked()464     public void testNoteScreenStateTimersLocked() throws Exception {
465         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
466         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
467 
468         clocks.realtime = clocks.uptime = 100;
469         // Device startup, setOnBatteryLocked calls updateTimebases
470         bi.updateTimeBasesLocked(true, Display.STATE_UNKNOWN, 100_000, 100_000);
471         // Turn on display at 200us
472         clocks.realtime = clocks.uptime = 200;
473         bi.noteScreenStateLocked(0, Display.STATE_ON);
474         assertEquals(150_000, bi.computeBatteryRealtime(250_000, STATS_SINCE_CHARGED));
475         assertEquals(100_000, bi.computeBatteryScreenOffRealtime(250_000, STATS_SINCE_CHARGED));
476         assertEquals(50_000, bi.getScreenOnTime(250_000, STATS_SINCE_CHARGED));
477         assertEquals(0, bi.getScreenDozeTime(250_000, STATS_SINCE_CHARGED));
478         assertEquals(50_000, bi.getDisplayScreenOnTime(0, 250_000));
479         assertEquals(0, bi.getDisplayScreenDozeTime(0, 250_000));
480 
481         clocks.realtime = clocks.uptime = 310;
482         bi.noteScreenStateLocked(0, Display.STATE_OFF);
483         assertEquals(250_000, bi.computeBatteryRealtime(350_000, STATS_SINCE_CHARGED));
484         assertEquals(140_000, bi.computeBatteryScreenOffRealtime(350_000, STATS_SINCE_CHARGED));
485         assertEquals(110_000, bi.getScreenOnTime(350_000, STATS_SINCE_CHARGED));
486         assertEquals(0, bi.getScreenDozeTime(350_000, STATS_SINCE_CHARGED));
487         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 350_000));
488         assertEquals(0, bi.getDisplayScreenDozeTime(0, 350_000));
489 
490         clocks.realtime = clocks.uptime = 400;
491         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
492         assertEquals(400_000, bi.computeBatteryRealtime(500_000, STATS_SINCE_CHARGED));
493         assertEquals(290_000, bi.computeBatteryScreenOffRealtime(500_000, STATS_SINCE_CHARGED));
494         assertEquals(110_000, bi.getScreenOnTime(500_000, STATS_SINCE_CHARGED));
495         assertEquals(100_000, bi.getScreenDozeTime(500_000, STATS_SINCE_CHARGED));
496         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 500_000));
497         assertEquals(100_000, bi.getDisplayScreenDozeTime(0, 500_000));
498 
499         clocks.realtime = clocks.uptime = 1000;
500         bi.noteScreenStateLocked(0, Display.STATE_OFF);
501         assertEquals(1400_000, bi.computeBatteryRealtime(1500_000, STATS_SINCE_CHARGED));
502         assertEquals(1290_000, bi.computeBatteryScreenOffRealtime(1500_000, STATS_SINCE_CHARGED));
503         assertEquals(110_000, bi.getScreenOnTime(1500_000, STATS_SINCE_CHARGED));
504         assertEquals(600_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
505         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 1500_000));
506         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1500_000));
507     }
508 
509     /*
510      * Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly for multi display
511      * devices.
512      */
513     @SmallTest
testNoteScreenStateTimersLocked_multiDisplay()514     public void testNoteScreenStateTimersLocked_multiDisplay() throws Exception {
515         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
516         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
517         bi.setDisplayCountLocked(2);
518 
519         clocks.realtime = clocks.uptime = 100;
520         // Device startup, setOnBatteryLocked calls updateTimebases
521         bi.updateTimeBasesLocked(true, Display.STATE_UNKNOWN, 100_000, 100_000);
522         // Turn on display at 200us
523         clocks.realtime = clocks.uptime = 200;
524         bi.noteScreenStateLocked(0, Display.STATE_ON);
525         bi.noteScreenStateLocked(1, Display.STATE_OFF);
526         assertEquals(150_000, bi.computeBatteryRealtime(250_000, STATS_SINCE_CHARGED));
527         assertEquals(100_000, bi.computeBatteryScreenOffRealtime(250_000, STATS_SINCE_CHARGED));
528         assertEquals(50_000, bi.getScreenOnTime(250_000, STATS_SINCE_CHARGED));
529         assertEquals(0, bi.getScreenDozeTime(250_000, STATS_SINCE_CHARGED));
530         assertEquals(50_000, bi.getDisplayScreenOnTime(0, 250_000));
531         assertEquals(0, bi.getDisplayScreenDozeTime(0, 250_000));
532         assertEquals(0, bi.getDisplayScreenOnTime(1, 250_000));
533         assertEquals(0, bi.getDisplayScreenDozeTime(1, 250_000));
534 
535         clocks.realtime = clocks.uptime = 310;
536         bi.noteScreenStateLocked(0, Display.STATE_OFF);
537         assertEquals(250_000, bi.computeBatteryRealtime(350_000, STATS_SINCE_CHARGED));
538         assertEquals(140_000, bi.computeBatteryScreenOffRealtime(350_000, STATS_SINCE_CHARGED));
539         assertEquals(110_000, bi.getScreenOnTime(350_000, STATS_SINCE_CHARGED));
540         assertEquals(0, bi.getScreenDozeTime(350_000, STATS_SINCE_CHARGED));
541         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 350_000));
542         assertEquals(0, bi.getDisplayScreenDozeTime(0, 350_000));
543         assertEquals(0, bi.getDisplayScreenOnTime(1, 350_000));
544         assertEquals(0, bi.getDisplayScreenDozeTime(1, 350_000));
545 
546         clocks.realtime = clocks.uptime = 400;
547         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
548         assertEquals(400_000, bi.computeBatteryRealtime(500_000, STATS_SINCE_CHARGED));
549         assertEquals(290_000, bi.computeBatteryScreenOffRealtime(500_000, STATS_SINCE_CHARGED));
550         assertEquals(110_000, bi.getScreenOnTime(500_000, STATS_SINCE_CHARGED));
551         assertEquals(100_000, bi.getScreenDozeTime(500_000, STATS_SINCE_CHARGED));
552         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 500_000));
553         assertEquals(100_000, bi.getDisplayScreenDozeTime(0, 500_000));
554         assertEquals(0, bi.getDisplayScreenOnTime(1, 500_000));
555         assertEquals(0, bi.getDisplayScreenDozeTime(1, 500_000));
556 
557         clocks.realtime = clocks.uptime = 1000;
558         bi.noteScreenStateLocked(0, Display.STATE_OFF);
559         assertEquals(1000_000, bi.computeBatteryRealtime(1100_000, STATS_SINCE_CHARGED));
560         assertEquals(890_000, bi.computeBatteryScreenOffRealtime(1100_000, STATS_SINCE_CHARGED));
561         assertEquals(110_000, bi.getScreenOnTime(1100_000, STATS_SINCE_CHARGED));
562         assertEquals(600_000, bi.getScreenDozeTime(1100_000, STATS_SINCE_CHARGED));
563         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 1100_000));
564         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1100_000));
565         assertEquals(0, bi.getDisplayScreenOnTime(1, 1100_000));
566         assertEquals(0, bi.getDisplayScreenDozeTime(1, 1100_000));
567 
568         clocks.realtime = clocks.uptime = 1200;
569         // Change state of second display to doze
570         bi.noteScreenStateLocked(1, Display.STATE_DOZE);
571         assertEquals(1150_000, bi.computeBatteryRealtime(1250_000, STATS_SINCE_CHARGED));
572         assertEquals(1040_000, bi.computeBatteryScreenOffRealtime(1250_000, STATS_SINCE_CHARGED));
573         assertEquals(110_000, bi.getScreenOnTime(1250_000, STATS_SINCE_CHARGED));
574         assertEquals(650_000, bi.getScreenDozeTime(1250_000, STATS_SINCE_CHARGED));
575         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 1250_000));
576         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1250_000));
577         assertEquals(0, bi.getDisplayScreenOnTime(1, 1250_000));
578         assertEquals(50_000, bi.getDisplayScreenDozeTime(1, 1250_000));
579 
580         clocks.realtime = clocks.uptime = 1310;
581         bi.noteScreenStateLocked(0, Display.STATE_ON);
582         assertEquals(1250_000, bi.computeBatteryRealtime(1350_000, STATS_SINCE_CHARGED));
583         assertEquals(1100_000, bi.computeBatteryScreenOffRealtime(1350_000, STATS_SINCE_CHARGED));
584         assertEquals(150_000, bi.getScreenOnTime(1350_000, STATS_SINCE_CHARGED));
585         assertEquals(710_000, bi.getScreenDozeTime(1350_000, STATS_SINCE_CHARGED));
586         assertEquals(150_000, bi.getDisplayScreenOnTime(0, 1350_000));
587         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1350_000));
588         assertEquals(0, bi.getDisplayScreenOnTime(1, 1350_000));
589         assertEquals(150_000, bi.getDisplayScreenDozeTime(1, 1350_000));
590 
591         clocks.realtime = clocks.uptime = 1400;
592         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
593         assertEquals(1400_000, bi.computeBatteryRealtime(1500_000, STATS_SINCE_CHARGED));
594         assertEquals(1200_000, bi.computeBatteryScreenOffRealtime(1500_000, STATS_SINCE_CHARGED));
595         assertEquals(200_000, bi.getScreenOnTime(1500_000, STATS_SINCE_CHARGED));
596         assertEquals(810_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
597         assertEquals(200_000, bi.getDisplayScreenOnTime(0, 1500_000));
598         assertEquals(700_000, bi.getDisplayScreenDozeTime(0, 1500_000));
599         assertEquals(0, bi.getDisplayScreenOnTime(1, 1500_000));
600         assertEquals(300_000, bi.getDisplayScreenDozeTime(1, 1500_000));
601 
602         clocks.realtime = clocks.uptime = 2000;
603         bi.noteScreenStateLocked(0, Display.STATE_OFF);
604         assertEquals(2000_000, bi.computeBatteryRealtime(2100_000, STATS_SINCE_CHARGED));
605         assertEquals(1800_000, bi.computeBatteryScreenOffRealtime(2100_000, STATS_SINCE_CHARGED));
606         assertEquals(200_000, bi.getScreenOnTime(2100_000, STATS_SINCE_CHARGED));
607         assertEquals(1410_000, bi.getScreenDozeTime(2100_000, STATS_SINCE_CHARGED));
608         assertEquals(200_000, bi.getDisplayScreenOnTime(0, 2100_000));
609         assertEquals(1200_000, bi.getDisplayScreenDozeTime(0, 2100_000));
610         assertEquals(0, bi.getDisplayScreenOnTime(1, 2100_000));
611         assertEquals(900_000, bi.getDisplayScreenDozeTime(1, 2100_000));
612 
613 
614         clocks.realtime = clocks.uptime = 2200;
615         // Change state of second display to on
616         bi.noteScreenStateLocked(1, Display.STATE_ON);
617         assertEquals(2150_000, bi.computeBatteryRealtime(2250_000, STATS_SINCE_CHARGED));
618         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(2250_000, STATS_SINCE_CHARGED));
619         assertEquals(250_000, bi.getScreenOnTime(2250_000, STATS_SINCE_CHARGED));
620         assertEquals(1510_000, bi.getScreenDozeTime(2250_000, STATS_SINCE_CHARGED));
621         assertEquals(200_000, bi.getDisplayScreenOnTime(0, 2250_000));
622         assertEquals(1200_000, bi.getDisplayScreenDozeTime(0, 2250_000));
623         assertEquals(50_000, bi.getDisplayScreenOnTime(1, 2250_000));
624         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 2250_000));
625 
626         clocks.realtime = clocks.uptime = 2310;
627         bi.noteScreenStateLocked(0, Display.STATE_ON);
628         assertEquals(2250_000, bi.computeBatteryRealtime(2350_000, STATS_SINCE_CHARGED));
629         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(2350_000, STATS_SINCE_CHARGED));
630         assertEquals(350_000, bi.getScreenOnTime(2350_000, STATS_SINCE_CHARGED));
631         assertEquals(1510_000, bi.getScreenDozeTime(2350_000, STATS_SINCE_CHARGED));
632         assertEquals(240_000, bi.getDisplayScreenOnTime(0, 2350_000));
633         assertEquals(1200_000, bi.getDisplayScreenDozeTime(0, 2350_000));
634         assertEquals(150_000, bi.getDisplayScreenOnTime(1, 2350_000));
635         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 2350_000));
636 
637         clocks.realtime = clocks.uptime = 2400;
638         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
639         assertEquals(2400_000, bi.computeBatteryRealtime(2500_000, STATS_SINCE_CHARGED));
640         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(2500_000, STATS_SINCE_CHARGED));
641         assertEquals(500_000, bi.getScreenOnTime(2500_000, STATS_SINCE_CHARGED));
642         assertEquals(1510_000, bi.getScreenDozeTime(2500_000, STATS_SINCE_CHARGED));
643         assertEquals(290_000, bi.getDisplayScreenOnTime(0, 2500_000));
644         assertEquals(1300_000, bi.getDisplayScreenDozeTime(0, 2500_000));
645         assertEquals(300_000, bi.getDisplayScreenOnTime(1, 2500_000));
646         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 2500_000));
647 
648         clocks.realtime = clocks.uptime = 3000;
649         bi.noteScreenStateLocked(0, Display.STATE_OFF);
650         assertEquals(3000_000, bi.computeBatteryRealtime(3100_000, STATS_SINCE_CHARGED));
651         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(3100_000, STATS_SINCE_CHARGED));
652         assertEquals(1100_000, bi.getScreenOnTime(3100_000, STATS_SINCE_CHARGED));
653         assertEquals(1510_000, bi.getScreenDozeTime(3100_000, STATS_SINCE_CHARGED));
654         assertEquals(290_000, bi.getDisplayScreenOnTime(0, 3100_000));
655         assertEquals(1800_000, bi.getDisplayScreenDozeTime(0, 3100_000));
656         assertEquals(900_000, bi.getDisplayScreenOnTime(1, 3100_000));
657         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 3100_000));
658     }
659 
660 
661     /**
662      * Test BatteryStatsImpl.noteScreenBrightnessLocked updates timers correctly.
663      */
664     @SmallTest
testScreenBrightnessLocked_multiDisplay()665     public void testScreenBrightnessLocked_multiDisplay() throws Exception {
666         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
667         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
668 
669         final int numDisplay = 2;
670         bi.setDisplayCountLocked(numDisplay);
671 
672 
673         final long[] overallExpected = new long[NUM_SCREEN_BRIGHTNESS_BINS];
674         final long[][] perDisplayExpected = new long[numDisplay][NUM_SCREEN_BRIGHTNESS_BINS];
675         class Bookkeeper {
676             public long currentTimeMs = 100;
677             public int overallActiveBin = -1;
678             public int[] perDisplayActiveBin = new int[numDisplay];
679         }
680         final Bookkeeper bk = new Bookkeeper();
681         Arrays.fill(bk.perDisplayActiveBin, -1);
682 
683         IntConsumer incrementTime = inc -> {
684             bk.currentTimeMs += inc;
685             if (bk.overallActiveBin >= 0) {
686                 overallExpected[bk.overallActiveBin] += inc;
687             }
688             for (int i = 0; i < numDisplay; i++) {
689                 final int bin = bk.perDisplayActiveBin[i];
690                 if (bin >= 0) {
691                     perDisplayExpected[i][bin] += inc;
692                 }
693             }
694             clocks.realtime = clocks.uptime = bk.currentTimeMs;
695         };
696 
697         bi.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
698         bi.noteScreenStateLocked(0, Display.STATE_ON);
699         bi.noteScreenStateLocked(1, Display.STATE_ON);
700 
701         incrementTime.accept(100);
702         bi.noteScreenBrightnessLocked(0, 25);
703         bi.noteScreenBrightnessLocked(1, 25);
704         // floor(25/256*5) = bin 0
705         bk.overallActiveBin = 0;
706         bk.perDisplayActiveBin[0] = 0;
707         bk.perDisplayActiveBin[1] = 0;
708 
709         incrementTime.accept(50);
710         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
711 
712         incrementTime.accept(13);
713         bi.noteScreenBrightnessLocked(0, 100);
714         // floor(25/256*5) = bin 1
715         bk.overallActiveBin = 1;
716         bk.perDisplayActiveBin[0] = 1;
717 
718         incrementTime.accept(44);
719         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
720 
721         incrementTime.accept(22);
722         bi.noteScreenBrightnessLocked(1, 200);
723         // floor(200/256*5) = bin 3
724         bk.overallActiveBin = 3;
725         bk.perDisplayActiveBin[1] = 3;
726 
727         incrementTime.accept(33);
728         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
729 
730         incrementTime.accept(77);
731         bi.noteScreenBrightnessLocked(0, 150);
732         // floor(150/256*5) = bin 2
733         // Overall active bin should not change
734         bk.perDisplayActiveBin[0] = 2;
735 
736         incrementTime.accept(88);
737         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
738 
739         incrementTime.accept(11);
740         bi.noteScreenStateLocked(1, Display.STATE_OFF);
741         // Display 1 should timers should stop incrementing
742         // Overall active bin should fallback to display 0's bin
743         bk.overallActiveBin = 2;
744         bk.perDisplayActiveBin[1] = -1;
745 
746         incrementTime.accept(99);
747         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
748 
749         incrementTime.accept(200);
750         bi.noteScreenBrightnessLocked(0, 255);
751         // floor(150/256*5) = bin 4
752         bk.overallActiveBin = 4;
753         bk.perDisplayActiveBin[0] = 4;
754 
755         incrementTime.accept(300);
756         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
757 
758         incrementTime.accept(200);
759         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
760         // No displays are on. No brightness timers should be active.
761         bk.overallActiveBin = -1;
762         bk.perDisplayActiveBin[0] = -1;
763 
764         incrementTime.accept(300);
765         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
766 
767         incrementTime.accept(400);
768         bi.noteScreenStateLocked(1, Display.STATE_ON);
769         // Display 1 turned back on.
770         bk.overallActiveBin = 3;
771         bk.perDisplayActiveBin[1] = 3;
772 
773         incrementTime.accept(500);
774         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
775 
776         incrementTime.accept(600);
777         bi.noteScreenStateLocked(0, Display.STATE_ON);
778         // Display 0 turned back on.
779         bk.overallActiveBin = 4;
780         bk.perDisplayActiveBin[0] = 4;
781 
782         incrementTime.accept(700);
783         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
784     }
785 
786     @SmallTest
787     @SkipPresubmit("b/180015146")
testAlarmStartAndFinishLocked()788     public void testAlarmStartAndFinishLocked() throws Exception {
789         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
790         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
791         bi.setRecordAllHistoryLocked(true);
792         bi.forceRecordAllHistory();
793 
794         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
795         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
796 
797         clocks.realtime = clocks.uptime = 100;
798         bi.noteAlarmStartLocked("foo", null, UID);
799         clocks.realtime = clocks.uptime = 5000;
800         bi.noteAlarmFinishLocked("foo", null, UID);
801 
802         HistoryItem item = new HistoryItem();
803         assertTrue(bi.startIteratingHistoryLocked());
804 
805         assertTrue(bi.getNextHistoryLocked(item));
806         assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
807         assertEquals("foo", item.eventTag.string);
808         assertEquals(UID, item.eventTag.uid);
809 
810         // TODO(narayan): Figure out why this event is written to the history buffer. See
811         // test below where it is being interspersed between multiple START events too.
812         assertTrue(bi.getNextHistoryLocked(item));
813         assertEquals(HistoryItem.EVENT_NONE, item.eventCode);
814 
815         assertTrue(bi.getNextHistoryLocked(item));
816         assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
817         assertTrue(item.isDeltaData());
818         assertEquals("foo", item.eventTag.string);
819         assertEquals(UID, item.eventTag.uid);
820 
821         assertFalse(bi.getNextHistoryLocked(item));
822     }
823 
824     @SmallTest
825     @SkipPresubmit("b/180015146")
testAlarmStartAndFinishLocked_workSource()826     public void testAlarmStartAndFinishLocked_workSource() throws Exception {
827         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
828         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
829         bi.setRecordAllHistoryLocked(true);
830         bi.forceRecordAllHistory();
831 
832         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
833         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
834 
835         WorkSource ws = new WorkSource();
836         ws.add(100);
837         ws.createWorkChain().addNode(500, "tag");
838         bi.noteAlarmStartLocked("foo", ws, UID);
839         clocks.realtime = clocks.uptime = 5000;
840         bi.noteAlarmFinishLocked("foo", ws, UID);
841 
842         HistoryItem item = new HistoryItem();
843         assertTrue(bi.startIteratingHistoryLocked());
844 
845         assertTrue(bi.getNextHistoryLocked(item));
846         assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
847         assertEquals("foo", item.eventTag.string);
848         assertEquals(100, item.eventTag.uid);
849 
850         assertTrue(bi.getNextHistoryLocked(item));
851         assertEquals(HistoryItem.EVENT_NONE, item.eventCode);
852 
853         assertTrue(bi.getNextHistoryLocked(item));
854         assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
855         assertEquals("foo", item.eventTag.string);
856         assertEquals(500, item.eventTag.uid);
857 
858         assertTrue(bi.getNextHistoryLocked(item));
859         assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
860         assertEquals("foo", item.eventTag.string);
861         assertEquals(100, item.eventTag.uid);
862 
863         assertTrue(bi.getNextHistoryLocked(item));
864         assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
865         assertEquals("foo", item.eventTag.string);
866         assertEquals(500, item.eventTag.uid);
867     }
868 
869     @SmallTest
testNoteWakupAlarmLocked()870     public void testNoteWakupAlarmLocked() {
871         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
872         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
873         bi.setRecordAllHistoryLocked(true);
874         bi.forceRecordAllHistory();
875         bi.mForceOnBattery = true;
876 
877         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
878         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
879 
880         bi.noteWakupAlarmLocked("com.foo.bar", UID, null, "tag");
881 
882         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
883         assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_SINCE_CHARGED));
884         assertEquals(1, pkg.getWakeupAlarmStats().size());
885     }
886 
887     @SmallTest
testNoteWakupAlarmLocked_workSource_uid()888     public void testNoteWakupAlarmLocked_workSource_uid() {
889         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
890         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
891         bi.setRecordAllHistoryLocked(true);
892         bi.forceRecordAllHistory();
893         bi.mForceOnBattery = true;
894 
895         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
896         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
897 
898         WorkSource ws = new WorkSource();
899         ws.add(100);
900 
901         // When a WorkSource is present, "UID" should not be used - only the uids present in the
902         // WorkSource should be reported.
903         bi.noteWakupAlarmLocked("com.foo.bar", UID, ws, "tag");
904         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
905         assertEquals(0, pkg.getWakeupAlarmStats().size());
906         pkg = bi.getPackageStatsLocked(100, "com.foo.bar");
907         assertEquals(1, pkg.getWakeupAlarmStats().size());
908 
909         // If the WorkSource contains a "name", it should be interpreted as a package name and
910         // the packageName supplied as an argument must be ignored.
911         ws = new WorkSource();
912         ws.add(100, "com.foo.baz_alternate");
913         bi.noteWakupAlarmLocked("com.foo.baz", UID, ws, "tag");
914         pkg = bi.getPackageStatsLocked(100, "com.foo.baz");
915         assertEquals(0, pkg.getWakeupAlarmStats().size());
916         pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate");
917         assertEquals(1, pkg.getWakeupAlarmStats().size());
918     }
919 
920     @SmallTest
testNoteWakupAlarmLocked_workSource_workChain()921     public void testNoteWakupAlarmLocked_workSource_workChain() {
922         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
923         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
924         bi.setRecordAllHistoryLocked(true);
925         bi.forceRecordAllHistory();
926         bi.mForceOnBattery = true;
927 
928         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
929         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
930 
931         WorkSource ws = new WorkSource();
932         ws.createWorkChain().addNode(100, "com.foo.baz_alternate");
933         bi.noteWakupAlarmLocked("com.foo.bar", UID, ws, "tag");
934 
935         // For WorkChains, again we must only attribute to the uids present in the WorkSource
936         // (and not to "UID"). However, unlike the older "tags" we do not change the packagename
937         // supplied as an argument, given that we're logging the entire attribution chain.
938         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
939         assertEquals(0, pkg.getWakeupAlarmStats().size());
940         pkg = bi.getPackageStatsLocked(100, "com.foo.bar");
941         assertEquals(1, pkg.getWakeupAlarmStats().size());
942         pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate");
943         assertEquals(0, pkg.getWakeupAlarmStats().size());
944     }
945 
946     @SmallTest
testNoteGpsChanged()947     public void testNoteGpsChanged() {
948         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
949         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
950         bi.setRecordAllHistoryLocked(true);
951         bi.forceRecordAllHistory();
952         bi.mForceOnBattery = true;
953 
954         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
955         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
956 
957         WorkSource ws = new WorkSource();
958         ws.add(UID);
959 
960         bi.noteGpsChangedLocked(new WorkSource(), ws);
961         DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
962         assertNotNull(t);
963         assertTrue(t.isRunningLocked());
964 
965         bi.noteGpsChangedLocked(ws, new WorkSource());
966         t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
967         assertFalse(t.isRunningLocked());
968     }
969 
970     @SmallTest
testNoteGpsChanged_workSource()971     public void testNoteGpsChanged_workSource() {
972         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
973         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
974         bi.setRecordAllHistoryLocked(true);
975         bi.forceRecordAllHistory();
976         bi.mForceOnBattery = true;
977 
978         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
979         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
980 
981         WorkSource ws = new WorkSource();
982         ws.createWorkChain().addNode(UID, "com.foo");
983 
984         bi.noteGpsChangedLocked(new WorkSource(), ws);
985         DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
986         assertNotNull(t);
987         assertTrue(t.isRunningLocked());
988 
989         bi.noteGpsChangedLocked(ws, new WorkSource());
990         t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
991         assertFalse(t.isRunningLocked());
992     }
993 
994     @SmallTest
testUpdateDisplayMeasuredEnergyStatsLocked()995     public void testUpdateDisplayMeasuredEnergyStatsLocked() {
996         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
997         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
998         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
999 
1000         clocks.realtime = 0;
1001         int[] screen = new int[]{Display.STATE_OFF};
1002         boolean battery = false;
1003 
1004         final int uid1 = 10500;
1005         final int uid2 = 10501;
1006         long blame1 = 0;
1007         long blame2 = 0;
1008         long globalDoze = 0;
1009 
1010         // Case A: uid1 off, uid2 off, battery off, screen off
1011         bi.updateTimeBasesLocked(battery, screen[0], clocks.realtime * 1000, 0);
1012         bi.setOnBatteryInternal(battery);
1013         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{500_000}, screen, clocks.realtime);
1014         checkMeasuredCharge("A", uid1, blame1, uid2, blame2, globalDoze, bi);
1015 
1016         // Case B: uid1 off, uid2 off, battery ON,  screen off
1017         clocks.realtime += 17;
1018         battery = true;
1019         bi.updateTimeBasesLocked(battery, screen[0], clocks.realtime * 1000, 0);
1020         bi.setOnBatteryInternal(battery);
1021         clocks.realtime += 19;
1022         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{510_000}, screen, clocks.realtime);
1023         checkMeasuredCharge("B", uid1, blame1, uid2, blame2, globalDoze, bi);
1024 
1025         // Case C: uid1 ON,  uid2 off, battery on,  screen off
1026         clocks.realtime += 18;
1027         setFgState(uid1, true, bi);
1028         clocks.realtime += 18;
1029         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{520_000}, screen, clocks.realtime);
1030         checkMeasuredCharge("C", uid1, blame1, uid2, blame2, globalDoze, bi);
1031 
1032         // Case D: uid1 on,  uid2 off, battery on,  screen ON
1033         clocks.realtime += 17;
1034         screen[0] = Display.STATE_ON;
1035         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{521_000}, screen, clocks.realtime);
1036         blame1 += 0; // Screen had been off during the measurement period
1037         checkMeasuredCharge("D.1", uid1, blame1, uid2, blame2, globalDoze, bi);
1038         clocks.realtime += 101;
1039         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{530_000}, screen, clocks.realtime);
1040         blame1 += 530_000;
1041         checkMeasuredCharge("D.2", uid1, blame1, uid2, blame2, globalDoze, bi);
1042 
1043         // Case E: uid1 on,  uid2 ON,  battery on,  screen on
1044         clocks.realtime += 20;
1045         setFgState(uid2, true, bi);
1046         clocks.realtime += 40;
1047         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{540_000}, screen, clocks.realtime);
1048         // In the past 60ms, sum of fg is 20+40+40=100ms. uid1 is blamed for 60/100; uid2 for 40/100
1049         blame1 += 540_000 * (20 + 40) / (20 + 40 + 40);
1050         blame2 += 540_000 * (0 + 40) / (20 + 40 + 40);
1051         checkMeasuredCharge("E", uid1, blame1, uid2, blame2, globalDoze, bi);
1052 
1053         // Case F: uid1 on,  uid2 OFF, battery on,  screen on
1054         clocks.realtime += 40;
1055         setFgState(uid2, false, bi);
1056         clocks.realtime += 120;
1057         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{550_000}, screen, clocks.realtime);
1058         // In the past 160ms, sum f fg is 200ms. uid1 is blamed for 40+120 of it; uid2 for 40 of it.
1059         blame1 += 550_000 * (40 + 120) / (40 + 40 + 120);
1060         blame2 += 550_000 * (40 + 0) / (40 + 40 + 120);
1061         checkMeasuredCharge("F", uid1, blame1, uid2, blame2, globalDoze, bi);
1062 
1063         // Case G: uid1 on,  uid2 off,  battery on, screen DOZE
1064         clocks.realtime += 5;
1065         screen[0] = Display.STATE_DOZE;
1066         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{570_000}, screen, clocks.realtime);
1067         blame1 += 570_000; // All of this pre-doze time is blamed on uid1.
1068         checkMeasuredCharge("G", uid1, blame1, uid2, blame2, globalDoze, bi);
1069 
1070         // Case H: uid1 on,  uid2 off,  battery on, screen ON
1071         clocks.realtime += 6;
1072         screen[0] = Display.STATE_ON;
1073         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{580_000}, screen, clocks.realtime);
1074         blame1 += 0; // The screen had been doze during the energy period
1075         globalDoze += 580_000;
1076         checkMeasuredCharge("H", uid1, blame1, uid2, blame2, globalDoze, bi);
1077     }
1078 
1079     @SmallTest
testUpdateCustomMeasuredEnergyStatsLocked_neverCalled()1080     public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() {
1081         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
1082         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1083         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
1084         bi.setOnBatteryInternal(true);
1085 
1086         final int uid1 = 11500;
1087         final int uid2 = 11501;
1088 
1089         // Initially, all custom buckets report charge of 0.
1090         checkCustomBatteryConsumption("0", 0, 0, uid1, 0, 0, uid2, 0, 0, bi);
1091     }
1092 
1093     @SmallTest
testUpdateCustomMeasuredEnergyStatsLocked()1094     public void testUpdateCustomMeasuredEnergyStatsLocked() {
1095         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
1096         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1097         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
1098 
1099         final int bucketA = 0; // Custom bucket 0
1100         final int bucketB = 1; // Custom bucket 1
1101 
1102         long totalBlameA = 0; // Total charge consumption for bucketA (may exceed sum of uids)
1103         long totalBlameB = 0; // Total charge consumption for bucketB (may exceed sum of uids)
1104 
1105         final int uid1 = 10500;
1106         long blame1A = 0; // Blame for uid1 in bucketA
1107         long blame1B = 0; // Blame for uid1 in bucketB
1108 
1109         final int uid2 = 10501;
1110         long blame2A = 0; // Blame for uid2 in bucketA
1111         long blame2B = 0; // Blame for uid2 in bucketB
1112 
1113         final SparseLongArray newChargesA = new SparseLongArray(2);
1114         final SparseLongArray newChargesB = new SparseLongArray(2);
1115 
1116 
1117         // ----- Case A: battery off (so blame does not increase)
1118         bi.setOnBatteryInternal(false);
1119 
1120         newChargesA.put(uid1, 20_000);
1121         // Implicit newChargesA.put(uid2, 0);
1122         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 500_000, newChargesA);
1123 
1124         newChargesB.put(uid1, 60_000);
1125         // Implicit newChargesB.put(uid2, 0);
1126         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 700_000, newChargesB);
1127 
1128         checkCustomBatteryConsumption(
1129                 "A", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1130 
1131 
1132         // ----- Case B: battery on
1133         bi.setOnBatteryInternal(true);
1134 
1135         newChargesA.put(uid1, 7_000); blame1A += 7_000;
1136         // Implicit newChargesA.put(uid2, 0); blame2A += 0;
1137         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 310_000, newChargesA);
1138         totalBlameA += 310_000;
1139 
1140         newChargesB.put(uid1, 63_000); blame1B += 63_000;
1141         newChargesB.put(uid2, 15_000); blame2B += 15_000;
1142         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 790_000, newChargesB);
1143         totalBlameB += 790_000;
1144 
1145         checkCustomBatteryConsumption(
1146                 "B", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1147 
1148 
1149         // ----- Case C: battery still on
1150         newChargesA.delete(uid1); blame1A += 0;
1151         newChargesA.put(uid2, 16_000); blame2A += 16_000;
1152         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 560_000, newChargesA);
1153         totalBlameA += 560_000;
1154 
1155         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 10_000, null);
1156         totalBlameB += 10_000;
1157 
1158         checkCustomBatteryConsumption(
1159                 "C", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1160 
1161 
1162         // ----- Case D: battery still on
1163         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 0, newChargesA);
1164         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 15_000, new SparseLongArray(1));
1165         totalBlameB += 15_000;
1166         checkCustomBatteryConsumption(
1167                 "D", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1168     }
1169 
setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi)1170     private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
1171         // Note that noteUidProcessStateLocked uses ActivityManager process states.
1172         if (fgOn) {
1173             bi.noteActivityResumedLocked(uid);
1174             bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_TOP);
1175         } else {
1176             bi.noteActivityPausedLocked(uid);
1177             bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
1178         }
1179     }
1180 
checkMeasuredCharge(String caseName, int uid1, long blame1, int uid2, long blame2, long globalDoze, MockBatteryStatsImpl bi)1181     private void checkMeasuredCharge(String caseName, int uid1, long blame1, int uid2, long blame2,
1182             long globalDoze, MockBatteryStatsImpl bi) {
1183         final int bucket = MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON;
1184 
1185         assertEquals("Wrong uid1 blame for Case " + caseName, blame1,
1186                 bi.getUidStatsLocked(uid1).getMeasuredBatteryConsumptionUC(bucket));
1187 
1188         assertEquals("Wrong uid2 blame for Case " + caseName, blame2,
1189                 bi.getUidStatsLocked(uid2).getMeasuredBatteryConsumptionUC(bucket));
1190 
1191         assertEquals("Wrong total blame for Case " + caseName, blame1 + blame2,
1192                 bi.getScreenOnMeasuredBatteryConsumptionUC());
1193 
1194         assertEquals("Wrong doze for Case " + caseName, globalDoze,
1195                 bi.getScreenDozeMeasuredBatteryConsumptionUC());
1196     }
1197 
checkCustomBatteryConsumption(String caseName, long totalBlameA, long totalBlameB, int uid1, long blame1A, long blame1B, int uid2, long blame2A, long blame2B, MockBatteryStatsImpl bi)1198     private void checkCustomBatteryConsumption(String caseName,
1199             long totalBlameA, long totalBlameB,
1200             int uid1, long blame1A, long blame1B,
1201             int uid2, long blame2A, long blame2B,
1202             MockBatteryStatsImpl bi) {
1203 
1204         final long[] actualTotal = bi.getCustomConsumerMeasuredBatteryConsumptionUC();
1205         final long[] actualUid1 =
1206                 bi.getUidStatsLocked(uid1).getCustomConsumerMeasuredBatteryConsumptionUC();
1207         final long[] actualUid2 =
1208                 bi.getUidStatsLocked(uid2).getCustomConsumerMeasuredBatteryConsumptionUC();
1209 
1210         assertNotNull(actualTotal);
1211         assertNotNull(actualUid1);
1212         assertNotNull(actualUid2);
1213 
1214         assertEquals("Wrong total blame in bucket 0 for Case " + caseName, totalBlameA,
1215                 actualTotal[0]);
1216 
1217         assertEquals("Wrong total blame in bucket 1 for Case " + caseName, totalBlameB,
1218                 actualTotal[1]);
1219 
1220         assertEquals("Wrong uid1 blame in bucket 0 for Case " + caseName, blame1A, actualUid1[0]);
1221 
1222         assertEquals("Wrong uid1 blame in bucket 1 for Case " + caseName, blame1B, actualUid1[1]);
1223 
1224         assertEquals("Wrong uid2 blame in bucket 0 for Case " + caseName, blame2A, actualUid2[0]);
1225 
1226         assertEquals("Wrong uid2 blame in bucket 1 for Case " + caseName, blame2B, actualUid2[1]);
1227     }
1228 
checkScreenBrightnesses(long[] overallExpected, long[][] perDisplayExpected, BatteryStatsImpl bi, long currentTimeMs)1229     private void checkScreenBrightnesses(long[] overallExpected, long[][] perDisplayExpected,
1230             BatteryStatsImpl bi, long currentTimeMs) {
1231         final int numDisplay = bi.getDisplayCount();
1232         for (int bin = 0; bin < NUM_SCREEN_BRIGHTNESS_BINS; bin++) {
1233             for (int display = 0; display < numDisplay; display++) {
1234                 assertEquals("Failure for display " + display + " screen brightness bin " + bin,
1235                         perDisplayExpected[display][bin] * 1000,
1236                         bi.getDisplayScreenBrightnessTime(display, bin, currentTimeMs * 1000));
1237             }
1238             assertEquals("Failure for overall screen brightness bin " + bin,
1239                     overallExpected[bin] * 1000,
1240                     bi.getScreenBrightnessTime(bin, currentTimeMs * 1000, STATS_SINCE_CHARGED));
1241         }
1242     }
1243 }
1244