• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.POWER_DATA_UNAVAILABLE;
21 import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
22 import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
23 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
24 import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
25 
26 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
27 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
28 
29 import static com.google.common.truth.Truth.assertThat;
30 
31 import static org.mockito.Mockito.mock;
32 
33 import android.app.ActivityManager;
34 import android.app.usage.NetworkStatsManager;
35 import android.hardware.radio.V1_5.AccessNetwork;
36 import android.os.BatteryStats;
37 import android.os.BatteryStats.HistoryItem;
38 import android.os.BatteryStats.Uid.Sensor;
39 import android.os.Process;
40 import android.os.UserHandle;
41 import android.os.WorkSource;
42 import android.telephony.AccessNetworkConstants;
43 import android.telephony.ActivityStatsTechSpecificInfo;
44 import android.telephony.Annotation;
45 import android.telephony.CellSignalStrength;
46 import android.telephony.DataConnectionRealTimeInfo;
47 import android.telephony.ModemActivityInfo;
48 import android.telephony.ServiceState;
49 import android.telephony.TelephonyManager;
50 import android.util.Log;
51 import android.util.MutableInt;
52 import android.util.SparseIntArray;
53 import android.util.SparseLongArray;
54 import android.view.Display;
55 
56 import androidx.test.filters.SmallTest;
57 
58 import com.android.internal.os.BatteryStatsImpl.DualTimer;
59 import com.android.internal.os.BatteryStatsImpl.Uid;
60 import com.android.internal.power.MeasuredEnergyStats;
61 
62 import junit.framework.TestCase;
63 
64 import org.mockito.Mock;
65 
66 import java.util.ArrayList;
67 import java.util.Arrays;
68 import java.util.HashMap;
69 import java.util.List;
70 import java.util.Map;
71 import java.util.function.IntConsumer;
72 
73 /**
74  * Test various BatteryStatsImpl noteStart methods.
75  *
76  * Build/Install/Run: bit FrameworksCoreTests:com.android.internal.os.BatteryStatsNoteTest
77  *
78  * Alternatively,
79  * Build: m FrameworksCoreTests
80  * Install: adb install -r \
81  *      ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
82  * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsNoteTest -w \
83  *      com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
84  */
85 public class BatteryStatsNoteTest extends TestCase {
86     private static final String TAG = BatteryStatsNoteTest.class.getSimpleName();
87 
88     private static final int UID = 10500;
89     private static final int ISOLATED_APP_ID = Process.FIRST_ISOLATED_UID + 23;
90     private static final int ISOLATED_UID = UserHandle.getUid(0, ISOLATED_APP_ID);
91     private static final WorkSource WS = new WorkSource(UID);
92 
93     enum ModemState {
94         SLEEP, IDLE, RECEIVING, TRANSMITTING
95     }
96 
97     @Mock
98     NetworkStatsManager mNetworkStatsManager;
99 
100     /**
101      * Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
102      */
103     @SmallTest
testNoteBluetoothScanResultLocked()104     public void testNoteBluetoothScanResultLocked() throws Exception {
105         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClock());
106         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
107         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
108 
109         bi.noteBluetoothScanResultsFromSourceLocked(WS, 1);
110         bi.noteBluetoothScanResultsFromSourceLocked(WS, 100);
111         assertEquals(101,
112                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
113                         .getCountLocked(STATS_SINCE_CHARGED));
114         BatteryStats.Counter bgCntr = bi.getUidStats().get(UID).getBluetoothScanResultBgCounter();
115         if (bgCntr != null) {
116             assertEquals(0, bgCntr.getCountLocked(STATS_SINCE_CHARGED));
117         }
118 
119         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
120         bi.noteBluetoothScanResultsFromSourceLocked(WS, 17);
121         assertEquals(101 + 17,
122                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
123                         .getCountLocked(STATS_SINCE_CHARGED));
124         assertEquals(17,
125                 bi.getUidStats().get(UID).getBluetoothScanResultBgCounter()
126                         .getCountLocked(STATS_SINCE_CHARGED));
127     }
128 
129     /**
130      * Test BatteryStatsImpl.Uid.noteStartWakeLocked.
131      */
132     @SmallTest
testNoteStartWakeLocked()133     public void testNoteStartWakeLocked() throws Exception {
134         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
135         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
136 
137         int pid = 10;
138         String name = "name";
139 
140         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
141         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
142         bi.getUidStatsLocked(UID)
143                 .noteStartWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
144 
145         clocks.realtime = clocks.uptime = 100;
146         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
147 
148         clocks.realtime = clocks.uptime = 220;
149         bi.getUidStatsLocked(UID).noteStopWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
150 
151         BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
152                 .getAggregatedPartialWakelockTimer();
153         long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
154         long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
155         assertEquals(220_000, actualTime);
156         assertEquals(120_000, bgTime);
157     }
158 
159     /**
160      * Test BatteryStatsImpl.Uid.noteStartWakeLocked for an isolated uid.
161      */
162     @SmallTest
testNoteStartWakeLocked_isolatedUid()163     public void testNoteStartWakeLocked_isolatedUid() throws Exception {
164         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
165         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
166 
167         int pid = 10;
168         String name = "name";
169         String historyName = "historyName";
170 
171         WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain();
172         isolatedWorkChain.addNode(ISOLATED_UID, name);
173 
174         // Map ISOLATED_UID to UID.
175         bi.addIsolatedUidLocked(ISOLATED_UID, UID);
176 
177         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
178         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
179         bi.noteStartWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
180                 WAKE_TYPE_PARTIAL, false);
181 
182         clocks.realtime = clocks.uptime = 100;
183         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
184 
185         clocks.realtime = clocks.uptime = 220;
186         bi.noteStopWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
187                 WAKE_TYPE_PARTIAL);
188 
189         // ISOLATED_UID wakelock time should be attributed to UID.
190         BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
191                 .getAggregatedPartialWakelockTimer();
192         long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
193         long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
194         assertEquals(220_000, actualTime);
195         assertEquals(120_000, bgTime);
196     }
197 
198     /**
199      * Test BatteryStatsImpl.Uid.noteStartWakeLocked for an isolated uid, with a race where the
200      * isolated uid is removed from batterystats before the wakelock has been stopped.
201      */
202     @SmallTest
testNoteStartWakeLocked_isolatedUidRace()203     public void testNoteStartWakeLocked_isolatedUidRace() throws Exception {
204         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
205         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
206 
207         int pid = 10;
208         String name = "name";
209         String historyName = "historyName";
210 
211         WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain();
212         isolatedWorkChain.addNode(ISOLATED_UID, name);
213 
214         // Map ISOLATED_UID to UID.
215         bi.addIsolatedUidLocked(ISOLATED_UID, UID);
216 
217         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
218         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
219         bi.noteStartWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
220                 WAKE_TYPE_PARTIAL, false);
221 
222         clocks.realtime = clocks.uptime = 100;
223         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
224 
225         clocks.realtime = clocks.uptime = 150;
226         bi.maybeRemoveIsolatedUidLocked(ISOLATED_UID, clocks.realtime, clocks.uptime);
227 
228         clocks.realtime = clocks.uptime = 220;
229         bi.noteStopWakeLocked(ISOLATED_UID, pid, isolatedWorkChain, name, historyName,
230                 WAKE_TYPE_PARTIAL);
231 
232         // ISOLATED_UID wakelock time should be attributed to UID.
233         BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
234                 .getAggregatedPartialWakelockTimer();
235         long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
236         long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
237         assertEquals(220_000, actualTime);
238         assertEquals(120_000, bgTime);
239     }
240 
241     /**
242      * Test BatteryStatsImpl.Uid.noteLongPartialWakelockStart for an isolated uid.
243      */
244     @SmallTest
testNoteLongPartialWakelockStart_isolatedUid()245     public void testNoteLongPartialWakelockStart_isolatedUid() throws Exception {
246         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
247         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
248 
249 
250         bi.setRecordAllHistoryLocked(true);
251         bi.forceRecordAllHistory();
252 
253         int pid = 10;
254         String name = "name";
255         String historyName = "historyName";
256 
257         WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain();
258         isolatedWorkChain.addNode(ISOLATED_UID, name);
259 
260         // Map ISOLATED_UID to UID.
261         bi.addIsolatedUidLocked(ISOLATED_UID, UID);
262 
263         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
264         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
265         bi.noteLongPartialWakelockStart(name, historyName, ISOLATED_UID);
266 
267         clocks.realtime = clocks.uptime = 100;
268         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
269 
270         clocks.realtime = clocks.uptime = 220;
271         bi.noteLongPartialWakelockFinish(name, historyName, ISOLATED_UID);
272 
273         final BatteryStatsHistoryIterator iterator =
274                 bi.createBatteryStatsHistoryIterator();
275 
276         BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
277 
278         while (iterator.next(item)) {
279             if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_START) break;
280         }
281         assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_START);
282         assertThat(item.eventTag).isNotNull();
283         assertThat(item.eventTag.string).isEqualTo(historyName);
284         assertThat(item.eventTag.uid).isEqualTo(UID);
285 
286         while (iterator.next(item)) {
287             if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH) break;
288         }
289         assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH);
290         assertThat(item.eventTag).isNotNull();
291         assertThat(item.eventTag.string).isEqualTo(historyName);
292         assertThat(item.eventTag.uid).isEqualTo(UID);
293     }
294 
295     /**
296      * Test BatteryStatsImpl.Uid.noteLongPartialWakelockStart for an isolated uid.
297      */
298     @SmallTest
testNoteLongPartialWakelockStart_isolatedUidRace()299     public void testNoteLongPartialWakelockStart_isolatedUidRace() throws Exception {
300         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
301         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
302 
303 
304         bi.setRecordAllHistoryLocked(true);
305         bi.forceRecordAllHistory();
306 
307         int pid = 10;
308         String name = "name";
309         String historyName = "historyName";
310 
311         WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain();
312         isolatedWorkChain.addNode(ISOLATED_UID, name);
313 
314         // Map ISOLATED_UID to UID.
315         bi.addIsolatedUidLocked(ISOLATED_UID, UID);
316 
317         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
318         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
319         bi.noteLongPartialWakelockStart(name, historyName, ISOLATED_UID);
320 
321         clocks.realtime = clocks.uptime = 100;
322         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
323 
324         clocks.realtime = clocks.uptime = 150;
325         bi.maybeRemoveIsolatedUidLocked(ISOLATED_UID, clocks.realtime, clocks.uptime);
326 
327         clocks.realtime = clocks.uptime = 220;
328         bi.noteLongPartialWakelockFinish(name, historyName, ISOLATED_UID);
329 
330         final BatteryStatsHistoryIterator iterator =
331                 bi.createBatteryStatsHistoryIterator();
332 
333         BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
334 
335         while (iterator.next(item)) {
336             if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_START) break;
337         }
338         assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_START);
339         assertThat(item.eventTag).isNotNull();
340         assertThat(item.eventTag.string).isEqualTo(historyName);
341         assertThat(item.eventTag.uid).isEqualTo(UID);
342 
343         while (iterator.next(item)) {
344             if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH) break;
345         }
346         assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH);
347         assertThat(item.eventTag).isNotNull();
348         assertThat(item.eventTag.string).isEqualTo(historyName);
349         assertThat(item.eventTag.uid).isEqualTo(UID);
350     }
351 
352     /**
353      * Test BatteryStatsImpl.noteUidProcessStateLocked.
354      */
355     @SmallTest
testNoteUidProcessStateLocked()356     public void testNoteUidProcessStateLocked() throws Exception {
357         final MockClock clocks = new MockClock();
358         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
359 
360         // map of ActivityManager process states and how long to simulate run time in each state
361         Map<Integer, Integer> stateRuntimeMap = new HashMap<Integer, Integer>();
362         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TOP, 1111);
363         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BOUND_TOP, 7382);
364         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 1234);
365         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 2468);
366         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TOP_SLEEPING, 7531);
367         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 4455);
368         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 1337);
369         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BACKUP, 90210);
370         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_HEAVY_WEIGHT, 911);
371         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_SERVICE, 404);
372         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_RECEIVER, 31459);
373         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_HOME, 1123);
374         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_LAST_ACTIVITY, 5813);
375         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 867);
376         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT, 5309);
377         stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_EMPTY, 42);
378 
379         bi.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
380 
381         for (Map.Entry<Integer, Integer> entry : stateRuntimeMap.entrySet()) {
382             bi.noteUidProcessStateLocked(UID, entry.getKey());
383             clocks.realtime += entry.getValue();
384             clocks.uptime = clocks.realtime;
385         }
386 
387         long actualRunTimeUs;
388         long expectedRunTimeMs;
389         long elapsedTimeUs = clocks.realtime * 1000;
390         BatteryStats.Uid uid = bi.getUidStats().get(UID);
391 
392         // compare runtime of process states to the Uid process states they map to
393         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP, elapsedTimeUs,
394                 STATS_SINCE_CHARGED);
395         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP);
396         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
397 
398         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
399                 elapsedTimeUs, STATS_SINCE_CHARGED);
400         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE)
401                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
402         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
403 
404         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
405                 elapsedTimeUs, STATS_SINCE_CHARGED);
406         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
407         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
408 
409         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND,
410                 elapsedTimeUs, STATS_SINCE_CHARGED);
411         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
412         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
413 
414         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND,
415                 elapsedTimeUs, STATS_SINCE_CHARGED);
416         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND)
417                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BACKUP)
418                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_SERVICE)
419                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_RECEIVER)
420                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BOUND_TOP);
421         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
422 
423         actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_CACHED,
424                 elapsedTimeUs, STATS_SINCE_CHARGED);
425         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_HOME)
426                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_LAST_ACTIVITY)
427                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY)
428                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT)
429                 + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
430         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
431 
432         // Special check for foreground service timer
433         actualRunTimeUs = uid.getForegroundServiceTimer().getTotalTimeLocked(elapsedTimeUs,
434                 STATS_SINCE_CHARGED);
435         expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
436         assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
437     }
438 
439     /**
440      * Test BatteryStatsImpl.updateTimeBasesLocked.
441      */
442     @SmallTest
testUpdateTimeBasesLocked()443     public void testUpdateTimeBasesLocked() throws Exception {
444         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
445         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
446 
447         bi.updateTimeBasesLocked(false, Display.STATE_OFF, 0, 0);
448         assertFalse(bi.getOnBatteryTimeBase().isRunning());
449         bi.updateTimeBasesLocked(false, Display.STATE_DOZE, 10, 10);
450         assertFalse(bi.getOnBatteryTimeBase().isRunning());
451         bi.updateTimeBasesLocked(false, Display.STATE_ON, 20, 20);
452         assertFalse(bi.getOnBatteryTimeBase().isRunning());
453 
454         bi.updateTimeBasesLocked(true, Display.STATE_ON, 30, 30);
455         assertTrue(bi.getOnBatteryTimeBase().isRunning());
456         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
457         bi.updateTimeBasesLocked(true, Display.STATE_DOZE, 40, 40);
458         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
459         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 40, 40);
460         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
461     }
462 
463     /**
464      * Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly.
465      */
466     @SmallTest
testNoteScreenStateLocked()467     public void testNoteScreenStateLocked() throws Exception {
468         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
469         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
470         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
471 
472         bi.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
473         bi.noteScreenStateLocked(0, Display.STATE_ON);
474 
475         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
476         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
477         assertEquals(Display.STATE_DOZE, bi.getScreenState());
478         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
479 
480         bi.noteScreenStateLocked(0, Display.STATE_ON);
481         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
482         assertEquals(Display.STATE_ON, bi.getScreenState());
483         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
484 
485         bi.noteScreenStateLocked(0, Display.STATE_OFF);
486         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
487         assertEquals(Display.STATE_OFF, bi.getScreenState());
488         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
489 
490         bi.noteScreenStateLocked(0, Display.STATE_DOZE_SUSPEND);
491         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
492         assertEquals(Display.STATE_DOZE_SUSPEND, bi.getScreenState());
493         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
494 
495         // STATE_VR note should map to STATE_ON.
496         bi.noteScreenStateLocked(0, Display.STATE_VR);
497         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
498         assertEquals(Display.STATE_ON, bi.getScreenState());
499         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
500 
501         // STATE_ON_SUSPEND note should map to STATE_ON.
502         bi.noteScreenStateLocked(0, Display.STATE_ON_SUSPEND);
503         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
504         assertEquals(Display.STATE_ON, bi.getScreenState());
505         // Transition from ON to ON state should not cause an External Sync
506         assertEquals(0, bi.getAndClearExternalStatsSyncFlags());
507     }
508 
509     /**
510      * Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly for
511      * multi display devices
512      */
513     @SmallTest
testNoteScreenStateLocked_multiDisplay()514     public void testNoteScreenStateLocked_multiDisplay() throws Exception {
515         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
516         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
517         bi.setDisplayCountLocked(2);
518         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
519 
520         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
521         bi.noteScreenStateLocked(0, Display.STATE_OFF);
522         bi.noteScreenStateLocked(1, Display.STATE_OFF);
523 
524         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
525         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
526         assertEquals(Display.STATE_DOZE, bi.getScreenState());
527         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
528 
529         bi.noteScreenStateLocked(0, Display.STATE_ON);
530         assertEquals(Display.STATE_ON, bi.getScreenState());
531         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
532         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
533 
534         bi.noteScreenStateLocked(0, Display.STATE_OFF);
535         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
536         assertEquals(Display.STATE_OFF, bi.getScreenState());
537         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
538 
539         bi.noteScreenStateLocked(0, Display.STATE_DOZE_SUSPEND);
540         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
541         assertEquals(Display.STATE_DOZE_SUSPEND, bi.getScreenState());
542         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
543 
544         // STATE_VR note should map to STATE_ON.
545         bi.noteScreenStateLocked(0, Display.STATE_VR);
546         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
547         assertEquals(Display.STATE_ON, bi.getScreenState());
548         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
549 
550         // STATE_ON_SUSPEND note should map to STATE_ON.
551         bi.noteScreenStateLocked(0, Display.STATE_ON_SUSPEND);
552         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
553         assertEquals(Display.STATE_ON, bi.getScreenState());
554         // Transition from ON to ON state should not cause an External Sync
555         assertEquals(0, bi.getAndClearExternalStatsSyncFlags());
556 
557         bi.noteScreenStateLocked(1, Display.STATE_DOZE);
558         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
559         // Should remain STATE_ON since display0 is still on.
560         assertEquals(Display.STATE_ON, bi.getScreenState());
561         // Overall screen state did not change, so no need to sync CPU stats.
562         assertEquals(UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
563 
564         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
565         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
566         assertEquals(Display.STATE_DOZE, bi.getScreenState());
567         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
568 
569         bi.noteScreenStateLocked(0, Display.STATE_ON);
570         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
571         assertEquals(Display.STATE_ON, bi.getScreenState());
572         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
573 
574         bi.noteScreenStateLocked(0, Display.STATE_OFF);
575         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
576         assertEquals(Display.STATE_DOZE, bi.getScreenState());
577         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
578 
579         bi.noteScreenStateLocked(0, Display.STATE_DOZE_SUSPEND);
580         assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
581         assertEquals(Display.STATE_DOZE, bi.getScreenState());
582         // Overall screen state did not change, so no need to sync CPU stats.
583         assertEquals(UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
584 
585         bi.noteScreenStateLocked(0, Display.STATE_VR);
586         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
587         assertEquals(Display.STATE_ON, bi.getScreenState());
588         assertEquals(UPDATE_CPU | UPDATE_DISPLAY, bi.getAndClearExternalStatsSyncFlags());
589 
590         bi.noteScreenStateLocked(0, Display.STATE_ON_SUSPEND);
591         assertFalse(bi.getOnBatteryScreenOffTimeBase().isRunning());
592         assertEquals(Display.STATE_ON, bi.getScreenState());
593         assertEquals(0, bi.getAndClearExternalStatsSyncFlags());
594     }
595 
596     /*
597      * Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly.
598      *
599      * Unknown and doze should both be subset of off state
600      *
601      * Timeline 0----100----200----310----400------------1000
602      * Unknown         -------
603      * On                     -------
604      * Off             -------       ----------------------
605      * Doze                                ----------------
606      */
607     @SmallTest
testNoteScreenStateTimersLocked()608     public void testNoteScreenStateTimersLocked() throws Exception {
609         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
610         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
611 
612         clocks.realtime = clocks.uptime = 100;
613         // Device startup, setOnBatteryLocked calls updateTimebases
614         bi.updateTimeBasesLocked(true, Display.STATE_UNKNOWN, 100_000, 100_000);
615         // Turn on display at 200us
616         clocks.realtime = clocks.uptime = 200;
617         bi.noteScreenStateLocked(0, Display.STATE_ON);
618         assertEquals(150_000, bi.computeBatteryRealtime(250_000, STATS_SINCE_CHARGED));
619         assertEquals(100_000, bi.computeBatteryScreenOffRealtime(250_000, STATS_SINCE_CHARGED));
620         assertEquals(50_000, bi.getScreenOnTime(250_000, STATS_SINCE_CHARGED));
621         assertEquals(0, bi.getScreenDozeTime(250_000, STATS_SINCE_CHARGED));
622         assertEquals(50_000, bi.getDisplayScreenOnTime(0, 250_000));
623         assertEquals(0, bi.getDisplayScreenDozeTime(0, 250_000));
624 
625         clocks.realtime = clocks.uptime = 310;
626         bi.noteScreenStateLocked(0, Display.STATE_OFF);
627         assertEquals(250_000, bi.computeBatteryRealtime(350_000, STATS_SINCE_CHARGED));
628         assertEquals(140_000, bi.computeBatteryScreenOffRealtime(350_000, STATS_SINCE_CHARGED));
629         assertEquals(110_000, bi.getScreenOnTime(350_000, STATS_SINCE_CHARGED));
630         assertEquals(0, bi.getScreenDozeTime(350_000, STATS_SINCE_CHARGED));
631         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 350_000));
632         assertEquals(0, bi.getDisplayScreenDozeTime(0, 350_000));
633 
634         clocks.realtime = clocks.uptime = 400;
635         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
636         assertEquals(400_000, bi.computeBatteryRealtime(500_000, STATS_SINCE_CHARGED));
637         assertEquals(290_000, bi.computeBatteryScreenOffRealtime(500_000, STATS_SINCE_CHARGED));
638         assertEquals(110_000, bi.getScreenOnTime(500_000, STATS_SINCE_CHARGED));
639         assertEquals(100_000, bi.getScreenDozeTime(500_000, STATS_SINCE_CHARGED));
640         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 500_000));
641         assertEquals(100_000, bi.getDisplayScreenDozeTime(0, 500_000));
642 
643         clocks.realtime = clocks.uptime = 1000;
644         bi.noteScreenStateLocked(0, Display.STATE_OFF);
645         assertEquals(1400_000, bi.computeBatteryRealtime(1500_000, STATS_SINCE_CHARGED));
646         assertEquals(1290_000, bi.computeBatteryScreenOffRealtime(1500_000, STATS_SINCE_CHARGED));
647         assertEquals(110_000, bi.getScreenOnTime(1500_000, STATS_SINCE_CHARGED));
648         assertEquals(600_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
649         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 1500_000));
650         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1500_000));
651     }
652 
653     /*
654      * Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly for multi display
655      * devices.
656      */
657     @SmallTest
testNoteScreenStateTimersLocked_multiDisplay()658     public void testNoteScreenStateTimersLocked_multiDisplay() throws Exception {
659         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
660         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
661         bi.setDisplayCountLocked(2);
662 
663         clocks.realtime = clocks.uptime = 100;
664         // Device startup, setOnBatteryLocked calls updateTimebases
665         bi.updateTimeBasesLocked(true, Display.STATE_UNKNOWN, 100_000, 100_000);
666         // Turn on display at 200us
667         clocks.realtime = clocks.uptime = 200;
668         bi.noteScreenStateLocked(0, Display.STATE_ON);
669         bi.noteScreenStateLocked(1, Display.STATE_OFF);
670         assertEquals(150_000, bi.computeBatteryRealtime(250_000, STATS_SINCE_CHARGED));
671         assertEquals(100_000, bi.computeBatteryScreenOffRealtime(250_000, STATS_SINCE_CHARGED));
672         assertEquals(50_000, bi.getScreenOnTime(250_000, STATS_SINCE_CHARGED));
673         assertEquals(0, bi.getScreenDozeTime(250_000, STATS_SINCE_CHARGED));
674         assertEquals(50_000, bi.getDisplayScreenOnTime(0, 250_000));
675         assertEquals(0, bi.getDisplayScreenDozeTime(0, 250_000));
676         assertEquals(0, bi.getDisplayScreenOnTime(1, 250_000));
677         assertEquals(0, bi.getDisplayScreenDozeTime(1, 250_000));
678 
679         clocks.realtime = clocks.uptime = 310;
680         bi.noteScreenStateLocked(0, Display.STATE_OFF);
681         assertEquals(250_000, bi.computeBatteryRealtime(350_000, STATS_SINCE_CHARGED));
682         assertEquals(140_000, bi.computeBatteryScreenOffRealtime(350_000, STATS_SINCE_CHARGED));
683         assertEquals(110_000, bi.getScreenOnTime(350_000, STATS_SINCE_CHARGED));
684         assertEquals(0, bi.getScreenDozeTime(350_000, STATS_SINCE_CHARGED));
685         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 350_000));
686         assertEquals(0, bi.getDisplayScreenDozeTime(0, 350_000));
687         assertEquals(0, bi.getDisplayScreenOnTime(1, 350_000));
688         assertEquals(0, bi.getDisplayScreenDozeTime(1, 350_000));
689 
690         clocks.realtime = clocks.uptime = 400;
691         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
692         assertEquals(400_000, bi.computeBatteryRealtime(500_000, STATS_SINCE_CHARGED));
693         assertEquals(290_000, bi.computeBatteryScreenOffRealtime(500_000, STATS_SINCE_CHARGED));
694         assertEquals(110_000, bi.getScreenOnTime(500_000, STATS_SINCE_CHARGED));
695         assertEquals(100_000, bi.getScreenDozeTime(500_000, STATS_SINCE_CHARGED));
696         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 500_000));
697         assertEquals(100_000, bi.getDisplayScreenDozeTime(0, 500_000));
698         assertEquals(0, bi.getDisplayScreenOnTime(1, 500_000));
699         assertEquals(0, bi.getDisplayScreenDozeTime(1, 500_000));
700 
701         clocks.realtime = clocks.uptime = 1000;
702         bi.noteScreenStateLocked(0, Display.STATE_OFF);
703         assertEquals(1000_000, bi.computeBatteryRealtime(1100_000, STATS_SINCE_CHARGED));
704         assertEquals(890_000, bi.computeBatteryScreenOffRealtime(1100_000, STATS_SINCE_CHARGED));
705         assertEquals(110_000, bi.getScreenOnTime(1100_000, STATS_SINCE_CHARGED));
706         assertEquals(600_000, bi.getScreenDozeTime(1100_000, STATS_SINCE_CHARGED));
707         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 1100_000));
708         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1100_000));
709         assertEquals(0, bi.getDisplayScreenOnTime(1, 1100_000));
710         assertEquals(0, bi.getDisplayScreenDozeTime(1, 1100_000));
711 
712         clocks.realtime = clocks.uptime = 1200;
713         // Change state of second display to doze
714         bi.noteScreenStateLocked(1, Display.STATE_DOZE);
715         assertEquals(1150_000, bi.computeBatteryRealtime(1250_000, STATS_SINCE_CHARGED));
716         assertEquals(1040_000, bi.computeBatteryScreenOffRealtime(1250_000, STATS_SINCE_CHARGED));
717         assertEquals(110_000, bi.getScreenOnTime(1250_000, STATS_SINCE_CHARGED));
718         assertEquals(650_000, bi.getScreenDozeTime(1250_000, STATS_SINCE_CHARGED));
719         assertEquals(110_000, bi.getDisplayScreenOnTime(0, 1250_000));
720         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1250_000));
721         assertEquals(0, bi.getDisplayScreenOnTime(1, 1250_000));
722         assertEquals(50_000, bi.getDisplayScreenDozeTime(1, 1250_000));
723 
724         clocks.realtime = clocks.uptime = 1310;
725         bi.noteScreenStateLocked(0, Display.STATE_ON);
726         assertEquals(1250_000, bi.computeBatteryRealtime(1350_000, STATS_SINCE_CHARGED));
727         assertEquals(1100_000, bi.computeBatteryScreenOffRealtime(1350_000, STATS_SINCE_CHARGED));
728         assertEquals(150_000, bi.getScreenOnTime(1350_000, STATS_SINCE_CHARGED));
729         assertEquals(710_000, bi.getScreenDozeTime(1350_000, STATS_SINCE_CHARGED));
730         assertEquals(150_000, bi.getDisplayScreenOnTime(0, 1350_000));
731         assertEquals(600_000, bi.getDisplayScreenDozeTime(0, 1350_000));
732         assertEquals(0, bi.getDisplayScreenOnTime(1, 1350_000));
733         assertEquals(150_000, bi.getDisplayScreenDozeTime(1, 1350_000));
734 
735         clocks.realtime = clocks.uptime = 1400;
736         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
737         assertEquals(1400_000, bi.computeBatteryRealtime(1500_000, STATS_SINCE_CHARGED));
738         assertEquals(1200_000, bi.computeBatteryScreenOffRealtime(1500_000, STATS_SINCE_CHARGED));
739         assertEquals(200_000, bi.getScreenOnTime(1500_000, STATS_SINCE_CHARGED));
740         assertEquals(810_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
741         assertEquals(200_000, bi.getDisplayScreenOnTime(0, 1500_000));
742         assertEquals(700_000, bi.getDisplayScreenDozeTime(0, 1500_000));
743         assertEquals(0, bi.getDisplayScreenOnTime(1, 1500_000));
744         assertEquals(300_000, bi.getDisplayScreenDozeTime(1, 1500_000));
745 
746         clocks.realtime = clocks.uptime = 2000;
747         bi.noteScreenStateLocked(0, Display.STATE_OFF);
748         assertEquals(2000_000, bi.computeBatteryRealtime(2100_000, STATS_SINCE_CHARGED));
749         assertEquals(1800_000, bi.computeBatteryScreenOffRealtime(2100_000, STATS_SINCE_CHARGED));
750         assertEquals(200_000, bi.getScreenOnTime(2100_000, STATS_SINCE_CHARGED));
751         assertEquals(1410_000, bi.getScreenDozeTime(2100_000, STATS_SINCE_CHARGED));
752         assertEquals(200_000, bi.getDisplayScreenOnTime(0, 2100_000));
753         assertEquals(1200_000, bi.getDisplayScreenDozeTime(0, 2100_000));
754         assertEquals(0, bi.getDisplayScreenOnTime(1, 2100_000));
755         assertEquals(900_000, bi.getDisplayScreenDozeTime(1, 2100_000));
756 
757 
758         clocks.realtime = clocks.uptime = 2200;
759         // Change state of second display to on
760         bi.noteScreenStateLocked(1, Display.STATE_ON);
761         assertEquals(2150_000, bi.computeBatteryRealtime(2250_000, STATS_SINCE_CHARGED));
762         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(2250_000, STATS_SINCE_CHARGED));
763         assertEquals(250_000, bi.getScreenOnTime(2250_000, STATS_SINCE_CHARGED));
764         assertEquals(1510_000, bi.getScreenDozeTime(2250_000, STATS_SINCE_CHARGED));
765         assertEquals(200_000, bi.getDisplayScreenOnTime(0, 2250_000));
766         assertEquals(1200_000, bi.getDisplayScreenDozeTime(0, 2250_000));
767         assertEquals(50_000, bi.getDisplayScreenOnTime(1, 2250_000));
768         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 2250_000));
769 
770         clocks.realtime = clocks.uptime = 2310;
771         bi.noteScreenStateLocked(0, Display.STATE_ON);
772         assertEquals(2250_000, bi.computeBatteryRealtime(2350_000, STATS_SINCE_CHARGED));
773         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(2350_000, STATS_SINCE_CHARGED));
774         assertEquals(350_000, bi.getScreenOnTime(2350_000, STATS_SINCE_CHARGED));
775         assertEquals(1510_000, bi.getScreenDozeTime(2350_000, STATS_SINCE_CHARGED));
776         assertEquals(240_000, bi.getDisplayScreenOnTime(0, 2350_000));
777         assertEquals(1200_000, bi.getDisplayScreenDozeTime(0, 2350_000));
778         assertEquals(150_000, bi.getDisplayScreenOnTime(1, 2350_000));
779         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 2350_000));
780 
781         clocks.realtime = clocks.uptime = 2400;
782         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
783         assertEquals(2400_000, bi.computeBatteryRealtime(2500_000, STATS_SINCE_CHARGED));
784         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(2500_000, STATS_SINCE_CHARGED));
785         assertEquals(500_000, bi.getScreenOnTime(2500_000, STATS_SINCE_CHARGED));
786         assertEquals(1510_000, bi.getScreenDozeTime(2500_000, STATS_SINCE_CHARGED));
787         assertEquals(290_000, bi.getDisplayScreenOnTime(0, 2500_000));
788         assertEquals(1300_000, bi.getDisplayScreenDozeTime(0, 2500_000));
789         assertEquals(300_000, bi.getDisplayScreenOnTime(1, 2500_000));
790         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 2500_000));
791 
792         clocks.realtime = clocks.uptime = 3000;
793         bi.noteScreenStateLocked(0, Display.STATE_OFF);
794         assertEquals(3000_000, bi.computeBatteryRealtime(3100_000, STATS_SINCE_CHARGED));
795         assertEquals(1900_000, bi.computeBatteryScreenOffRealtime(3100_000, STATS_SINCE_CHARGED));
796         assertEquals(1100_000, bi.getScreenOnTime(3100_000, STATS_SINCE_CHARGED));
797         assertEquals(1510_000, bi.getScreenDozeTime(3100_000, STATS_SINCE_CHARGED));
798         assertEquals(290_000, bi.getDisplayScreenOnTime(0, 3100_000));
799         assertEquals(1800_000, bi.getDisplayScreenDozeTime(0, 3100_000));
800         assertEquals(900_000, bi.getDisplayScreenOnTime(1, 3100_000));
801         assertEquals(1000_000, bi.getDisplayScreenDozeTime(1, 3100_000));
802     }
803 
804 
805     /**
806      * Test BatteryStatsImpl.noteScreenBrightnessLocked updates timers correctly.
807      */
808     @SmallTest
testScreenBrightnessLocked_multiDisplay()809     public void testScreenBrightnessLocked_multiDisplay() throws Exception {
810         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
811         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
812 
813         final int numDisplay = 2;
814         bi.setDisplayCountLocked(numDisplay);
815 
816 
817         final long[] overallExpected = new long[NUM_SCREEN_BRIGHTNESS_BINS];
818         final long[][] perDisplayExpected = new long[numDisplay][NUM_SCREEN_BRIGHTNESS_BINS];
819         class Bookkeeper {
820             public long currentTimeMs = 100;
821             public int overallActiveBin = -1;
822             public int[] perDisplayActiveBin = new int[numDisplay];
823         }
824         final Bookkeeper bk = new Bookkeeper();
825         Arrays.fill(bk.perDisplayActiveBin, -1);
826 
827         IntConsumer incrementTime = inc -> {
828             bk.currentTimeMs += inc;
829             if (bk.overallActiveBin >= 0) {
830                 overallExpected[bk.overallActiveBin] += inc;
831             }
832             for (int i = 0; i < numDisplay; i++) {
833                 final int bin = bk.perDisplayActiveBin[i];
834                 if (bin >= 0) {
835                     perDisplayExpected[i][bin] += inc;
836                 }
837             }
838             clocks.realtime = clocks.uptime = bk.currentTimeMs;
839         };
840 
841         bi.updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
842         bi.noteScreenStateLocked(0, Display.STATE_ON);
843         bi.noteScreenStateLocked(1, Display.STATE_ON);
844 
845         incrementTime.accept(100);
846         bi.noteScreenBrightnessLocked(0, 25);
847         bi.noteScreenBrightnessLocked(1, 25);
848         // floor(25/256*5) = bin 0
849         bk.overallActiveBin = 0;
850         bk.perDisplayActiveBin[0] = 0;
851         bk.perDisplayActiveBin[1] = 0;
852 
853         incrementTime.accept(50);
854         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
855 
856         incrementTime.accept(13);
857         bi.noteScreenBrightnessLocked(0, 100);
858         // floor(25/256*5) = bin 1
859         bk.overallActiveBin = 1;
860         bk.perDisplayActiveBin[0] = 1;
861 
862         incrementTime.accept(44);
863         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
864 
865         incrementTime.accept(22);
866         bi.noteScreenBrightnessLocked(1, 200);
867         // floor(200/256*5) = bin 3
868         bk.overallActiveBin = 3;
869         bk.perDisplayActiveBin[1] = 3;
870 
871         incrementTime.accept(33);
872         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
873 
874         incrementTime.accept(77);
875         bi.noteScreenBrightnessLocked(0, 150);
876         // floor(150/256*5) = bin 2
877         // Overall active bin should not change
878         bk.perDisplayActiveBin[0] = 2;
879 
880         incrementTime.accept(88);
881         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
882 
883         incrementTime.accept(11);
884         bi.noteScreenStateLocked(1, Display.STATE_OFF);
885         // Display 1 should timers should stop incrementing
886         // Overall active bin should fallback to display 0's bin
887         bk.overallActiveBin = 2;
888         bk.perDisplayActiveBin[1] = -1;
889 
890         incrementTime.accept(99);
891         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
892 
893         incrementTime.accept(200);
894         bi.noteScreenBrightnessLocked(0, 255);
895         // floor(150/256*5) = bin 4
896         bk.overallActiveBin = 4;
897         bk.perDisplayActiveBin[0] = 4;
898 
899         incrementTime.accept(300);
900         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
901 
902         incrementTime.accept(200);
903         bi.noteScreenStateLocked(0, Display.STATE_DOZE);
904         // No displays are on. No brightness timers should be active.
905         bk.overallActiveBin = -1;
906         bk.perDisplayActiveBin[0] = -1;
907 
908         incrementTime.accept(300);
909         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
910 
911         incrementTime.accept(400);
912         bi.noteScreenStateLocked(1, Display.STATE_ON);
913         // Display 1 turned back on.
914         bk.overallActiveBin = 3;
915         bk.perDisplayActiveBin[1] = 3;
916 
917         incrementTime.accept(500);
918         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
919 
920         incrementTime.accept(600);
921         bi.noteScreenStateLocked(0, Display.STATE_ON);
922         // Display 0 turned back on.
923         bk.overallActiveBin = 4;
924         bk.perDisplayActiveBin[0] = 4;
925 
926         incrementTime.accept(700);
927         checkScreenBrightnesses(overallExpected, perDisplayExpected, bi, bk.currentTimeMs);
928     }
929 
930     @SmallTest
testAlarmStartAndFinishLocked()931     public void testAlarmStartAndFinishLocked() throws Exception {
932         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
933         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
934         bi.setRecordAllHistoryLocked(true);
935         bi.forceRecordAllHistory();
936 
937         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
938         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
939 
940         clocks.realtime = clocks.uptime = 100;
941         bi.noteAlarmStartLocked("foo", null, UID);
942         clocks.realtime = clocks.uptime = 5000;
943         bi.noteAlarmFinishLocked("foo", null, UID);
944 
945         HistoryItem item = new HistoryItem();
946         assertTrue(bi.startIteratingHistoryLocked());
947 
948         assertTrue(bi.getNextHistoryLocked(item));
949         assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
950         assertEquals("foo", item.eventTag.string);
951         assertEquals(UID, item.eventTag.uid);
952 
953         // TODO(narayan): Figure out why this event is written to the history buffer. See
954         // test below where it is being interspersed between multiple START events too.
955         assertTrue(bi.getNextHistoryLocked(item));
956         assertEquals(HistoryItem.EVENT_NONE, item.eventCode);
957 
958         assertTrue(bi.getNextHistoryLocked(item));
959         assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
960         assertTrue(item.isDeltaData());
961         assertEquals("foo", item.eventTag.string);
962         assertEquals(UID, item.eventTag.uid);
963 
964         assertFalse(bi.getNextHistoryLocked(item));
965     }
966 
967     @SmallTest
testAlarmStartAndFinishLocked_workSource()968     public void testAlarmStartAndFinishLocked_workSource() throws Exception {
969         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
970         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
971         bi.setRecordAllHistoryLocked(true);
972         bi.forceRecordAllHistory();
973 
974         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
975         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
976 
977         WorkSource ws = new WorkSource();
978         ws.add(100);
979         ws.createWorkChain().addNode(500, "tag");
980         bi.noteAlarmStartLocked("foo", ws, UID);
981         clocks.realtime = clocks.uptime = 5000;
982         bi.noteAlarmFinishLocked("foo", ws, UID);
983 
984         HistoryItem item = new HistoryItem();
985         assertTrue(bi.startIteratingHistoryLocked());
986 
987         assertTrue(bi.getNextHistoryLocked(item));
988         assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
989         assertEquals("foo", item.eventTag.string);
990         assertEquals(100, item.eventTag.uid);
991 
992         assertTrue(bi.getNextHistoryLocked(item));
993         assertEquals(HistoryItem.EVENT_NONE, item.eventCode);
994 
995         assertTrue(bi.getNextHistoryLocked(item));
996         assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
997         assertEquals("foo", item.eventTag.string);
998         assertEquals(500, item.eventTag.uid);
999 
1000         assertTrue(bi.getNextHistoryLocked(item));
1001         assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
1002         assertEquals("foo", item.eventTag.string);
1003         assertEquals(100, item.eventTag.uid);
1004 
1005         assertTrue(bi.getNextHistoryLocked(item));
1006         assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
1007         assertEquals("foo", item.eventTag.string);
1008         assertEquals(500, item.eventTag.uid);
1009     }
1010 
1011     @SmallTest
testNoteWakupAlarmLocked()1012     public void testNoteWakupAlarmLocked() {
1013         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1014         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1015         bi.setRecordAllHistoryLocked(true);
1016         bi.forceRecordAllHistory();
1017         bi.mForceOnBattery = true;
1018 
1019         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1020         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
1021 
1022         bi.noteWakupAlarmLocked("com.foo.bar", UID, null, "tag");
1023 
1024         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
1025         assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_SINCE_CHARGED));
1026         assertEquals(1, pkg.getWakeupAlarmStats().size());
1027     }
1028 
1029     @SmallTest
testNoteWakupAlarmLocked_workSource_uid()1030     public void testNoteWakupAlarmLocked_workSource_uid() {
1031         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1032         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1033         bi.setRecordAllHistoryLocked(true);
1034         bi.forceRecordAllHistory();
1035         bi.mForceOnBattery = true;
1036 
1037         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1038         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
1039 
1040         WorkSource ws = new WorkSource();
1041         ws.add(100);
1042 
1043         // When a WorkSource is present, "UID" should not be used - only the uids present in the
1044         // WorkSource should be reported.
1045         bi.noteWakupAlarmLocked("com.foo.bar", UID, ws, "tag");
1046         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
1047         assertEquals(0, pkg.getWakeupAlarmStats().size());
1048         pkg = bi.getPackageStatsLocked(100, "com.foo.bar");
1049         assertEquals(1, pkg.getWakeupAlarmStats().size());
1050 
1051         // If the WorkSource contains a "name", it should be interpreted as a package name and
1052         // the packageName supplied as an argument must be ignored.
1053         ws = new WorkSource();
1054         ws.add(100, "com.foo.baz_alternate");
1055         bi.noteWakupAlarmLocked("com.foo.baz", UID, ws, "tag");
1056         pkg = bi.getPackageStatsLocked(100, "com.foo.baz");
1057         assertEquals(0, pkg.getWakeupAlarmStats().size());
1058         pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate");
1059         assertEquals(1, pkg.getWakeupAlarmStats().size());
1060     }
1061 
1062     @SmallTest
testNoteWakupAlarmLocked_workSource_workChain()1063     public void testNoteWakupAlarmLocked_workSource_workChain() {
1064         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1065         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1066         bi.setRecordAllHistoryLocked(true);
1067         bi.forceRecordAllHistory();
1068         bi.mForceOnBattery = true;
1069 
1070         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1071         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
1072 
1073         WorkSource ws = new WorkSource();
1074         ws.createWorkChain().addNode(100, "com.foo.baz_alternate");
1075         bi.noteWakupAlarmLocked("com.foo.bar", UID, ws, "tag");
1076 
1077         // For WorkChains, again we must only attribute to the uids present in the WorkSource
1078         // (and not to "UID"). However, unlike the older "tags" we do not change the packagename
1079         // supplied as an argument, given that we're logging the entire attribution chain.
1080         Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
1081         assertEquals(0, pkg.getWakeupAlarmStats().size());
1082         pkg = bi.getPackageStatsLocked(100, "com.foo.bar");
1083         assertEquals(1, pkg.getWakeupAlarmStats().size());
1084         pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate");
1085         assertEquals(0, pkg.getWakeupAlarmStats().size());
1086     }
1087 
1088     @SmallTest
testNoteGpsChanged()1089     public void testNoteGpsChanged() {
1090         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1091         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1092         bi.setRecordAllHistoryLocked(true);
1093         bi.forceRecordAllHistory();
1094         bi.mForceOnBattery = true;
1095 
1096         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1097         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
1098 
1099         WorkSource ws = new WorkSource();
1100         ws.add(UID);
1101 
1102         bi.noteGpsChangedLocked(new WorkSource(), ws);
1103         DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
1104         assertNotNull(t);
1105         assertTrue(t.isRunningLocked());
1106 
1107         bi.noteGpsChangedLocked(ws, new WorkSource());
1108         t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
1109         assertFalse(t.isRunningLocked());
1110     }
1111 
1112     @SmallTest
testNoteGpsChanged_workSource()1113     public void testNoteGpsChanged_workSource() {
1114         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1115         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1116         bi.setRecordAllHistoryLocked(true);
1117         bi.forceRecordAllHistory();
1118         bi.mForceOnBattery = true;
1119 
1120         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1121         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
1122 
1123         WorkSource ws = new WorkSource();
1124         ws.createWorkChain().addNode(UID, "com.foo");
1125 
1126         bi.noteGpsChangedLocked(new WorkSource(), ws);
1127         DualTimer t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
1128         assertNotNull(t);
1129         assertTrue(t.isRunningLocked());
1130 
1131         bi.noteGpsChangedLocked(ws, new WorkSource());
1132         t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
1133         assertFalse(t.isRunningLocked());
1134     }
1135 
1136     @SmallTest
testUpdateDisplayMeasuredEnergyStatsLocked()1137     public void testUpdateDisplayMeasuredEnergyStatsLocked() {
1138         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1139         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1140         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
1141 
1142         clocks.realtime = 0;
1143         int[] screen = new int[]{Display.STATE_OFF};
1144         boolean battery = false;
1145 
1146         final int uid1 = 10500;
1147         final int uid2 = 10501;
1148         long blame1 = 0;
1149         long blame2 = 0;
1150         long globalDoze = 0;
1151 
1152         // Case A: uid1 off, uid2 off, battery off, screen off
1153         bi.updateTimeBasesLocked(battery, screen[0], clocks.realtime * 1000, 0);
1154         bi.setOnBatteryInternal(battery);
1155         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{500_000}, screen, clocks.realtime);
1156         checkMeasuredCharge("A", uid1, blame1, uid2, blame2, globalDoze, bi);
1157 
1158         // Case B: uid1 off, uid2 off, battery ON,  screen off
1159         clocks.realtime += 17;
1160         battery = true;
1161         bi.updateTimeBasesLocked(battery, screen[0], clocks.realtime * 1000, 0);
1162         bi.setOnBatteryInternal(battery);
1163         clocks.realtime += 19;
1164         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{510_000}, screen, clocks.realtime);
1165         checkMeasuredCharge("B", uid1, blame1, uid2, blame2, globalDoze, bi);
1166 
1167         // Case C: uid1 ON,  uid2 off, battery on,  screen off
1168         clocks.realtime += 18;
1169         setFgState(uid1, true, bi);
1170         clocks.realtime += 18;
1171         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{520_000}, screen, clocks.realtime);
1172         checkMeasuredCharge("C", uid1, blame1, uid2, blame2, globalDoze, bi);
1173 
1174         // Case D: uid1 on,  uid2 off, battery on,  screen ON
1175         clocks.realtime += 17;
1176         screen[0] = Display.STATE_ON;
1177         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{521_000}, screen, clocks.realtime);
1178         blame1 += 0; // Screen had been off during the measurement period
1179         checkMeasuredCharge("D.1", uid1, blame1, uid2, blame2, globalDoze, bi);
1180         clocks.realtime += 101;
1181         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{530_000}, screen, clocks.realtime);
1182         blame1 += 530_000;
1183         checkMeasuredCharge("D.2", uid1, blame1, uid2, blame2, globalDoze, bi);
1184 
1185         // Case E: uid1 on,  uid2 ON,  battery on,  screen on
1186         clocks.realtime += 20;
1187         setFgState(uid2, true, bi);
1188         clocks.realtime += 40;
1189         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{540_000}, screen, clocks.realtime);
1190         // In the past 60ms, sum of fg is 20+40+40=100ms. uid1 is blamed for 60/100; uid2 for 40/100
1191         blame1 += 540_000 * (20 + 40) / (20 + 40 + 40);
1192         blame2 += 540_000 * (0 + 40) / (20 + 40 + 40);
1193         checkMeasuredCharge("E", uid1, blame1, uid2, blame2, globalDoze, bi);
1194 
1195         // Case F: uid1 on,  uid2 OFF, battery on,  screen on
1196         clocks.realtime += 40;
1197         setFgState(uid2, false, bi);
1198         clocks.realtime += 120;
1199         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{550_000}, screen, clocks.realtime);
1200         // In the past 160ms, sum f fg is 200ms. uid1 is blamed for 40+120 of it; uid2 for 40 of it.
1201         blame1 += 550_000 * (40 + 120) / (40 + 40 + 120);
1202         blame2 += 550_000 * (40 + 0) / (40 + 40 + 120);
1203         checkMeasuredCharge("F", uid1, blame1, uid2, blame2, globalDoze, bi);
1204 
1205         // Case G: uid1 on,  uid2 off,  battery on, screen DOZE
1206         clocks.realtime += 5;
1207         screen[0] = Display.STATE_DOZE;
1208         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{570_000}, screen, clocks.realtime);
1209         blame1 += 570_000; // All of this pre-doze time is blamed on uid1.
1210         checkMeasuredCharge("G", uid1, blame1, uid2, blame2, globalDoze, bi);
1211 
1212         // Case H: uid1 on,  uid2 off,  battery on, screen ON
1213         clocks.realtime += 6;
1214         screen[0] = Display.STATE_ON;
1215         bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{580_000}, screen, clocks.realtime);
1216         blame1 += 0; // The screen had been doze during the energy period
1217         globalDoze += 580_000;
1218         checkMeasuredCharge("H", uid1, blame1, uid2, blame2, globalDoze, bi);
1219     }
1220 
1221     @SmallTest
testUpdateCustomMeasuredEnergyStatsLocked_neverCalled()1222     public void testUpdateCustomMeasuredEnergyStatsLocked_neverCalled() {
1223         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1224         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1225         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
1226         bi.setOnBatteryInternal(true);
1227 
1228         final int uid1 = 11500;
1229         final int uid2 = 11501;
1230 
1231         // Initially, all custom buckets report charge of 0.
1232         checkCustomBatteryConsumption("0", 0, 0, uid1, 0, 0, uid2, 0, 0, bi);
1233     }
1234 
1235     @SmallTest
testUpdateCustomMeasuredEnergyStatsLocked()1236     public void testUpdateCustomMeasuredEnergyStatsLocked() {
1237         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
1238         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
1239         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
1240 
1241         final int bucketA = 0; // Custom bucket 0
1242         final int bucketB = 1; // Custom bucket 1
1243 
1244         long totalBlameA = 0; // Total charge consumption for bucketA (may exceed sum of uids)
1245         long totalBlameB = 0; // Total charge consumption for bucketB (may exceed sum of uids)
1246 
1247         final int uid1 = 10500;
1248         long blame1A = 0; // Blame for uid1 in bucketA
1249         long blame1B = 0; // Blame for uid1 in bucketB
1250 
1251         final int uid2 = 10501;
1252         long blame2A = 0; // Blame for uid2 in bucketA
1253         long blame2B = 0; // Blame for uid2 in bucketB
1254 
1255         final SparseLongArray newChargesA = new SparseLongArray(2);
1256         final SparseLongArray newChargesB = new SparseLongArray(2);
1257 
1258 
1259         // ----- Case A: battery off (so blame does not increase)
1260         bi.setOnBatteryInternal(false);
1261 
1262         newChargesA.put(uid1, 20_000);
1263         // Implicit newChargesA.put(uid2, 0);
1264         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 500_000, newChargesA);
1265 
1266         newChargesB.put(uid1, 60_000);
1267         // Implicit newChargesB.put(uid2, 0);
1268         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 700_000, newChargesB);
1269 
1270         checkCustomBatteryConsumption(
1271                 "A", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1272 
1273 
1274         // ----- Case B: battery on
1275         bi.setOnBatteryInternal(true);
1276 
1277         newChargesA.put(uid1, 7_000); blame1A += 7_000;
1278         // Implicit newChargesA.put(uid2, 0); blame2A += 0;
1279         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 310_000, newChargesA);
1280         totalBlameA += 310_000;
1281 
1282         newChargesB.put(uid1, 63_000); blame1B += 63_000;
1283         newChargesB.put(uid2, 15_000); blame2B += 15_000;
1284         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 790_000, newChargesB);
1285         totalBlameB += 790_000;
1286 
1287         checkCustomBatteryConsumption(
1288                 "B", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1289 
1290 
1291         // ----- Case C: battery still on
1292         newChargesA.delete(uid1); blame1A += 0;
1293         newChargesA.put(uid2, 16_000); blame2A += 16_000;
1294         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 560_000, newChargesA);
1295         totalBlameA += 560_000;
1296 
1297         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 10_000, null);
1298         totalBlameB += 10_000;
1299 
1300         checkCustomBatteryConsumption(
1301                 "C", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1302 
1303 
1304         // ----- Case D: battery still on
1305         bi.updateCustomMeasuredEnergyStatsLocked(bucketA, 0, newChargesA);
1306         bi.updateCustomMeasuredEnergyStatsLocked(bucketB, 15_000, new SparseLongArray(1));
1307         totalBlameB += 15_000;
1308         checkCustomBatteryConsumption(
1309                 "D", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
1310     }
1311 
1312     @SmallTest
testGetPerStateActiveRadioDurationMs_noModemActivity()1313     public void testGetPerStateActiveRadioDurationMs_noModemActivity() {
1314         final MockClock clock = new MockClock(); // holds realtime and uptime in ms
1315         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
1316         final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
1317         final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
1318         final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
1319 
1320         final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
1321         final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
1322         final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
1323         for (int rat = 0; rat < ratCount; rat++) {
1324             for (int freq = 0; freq < frequencyCount; freq++) {
1325                 // Should have no RX data without Modem Activity Info
1326                 expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
1327                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
1328                     expectedDurationsMs[rat][freq][txLvl] = 0;
1329                     // Should have no TX data without Modem Activity Info
1330                     expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
1331                 }
1332             }
1333         }
1334 
1335         final ModemAndBatteryState state = new ModemAndBatteryState(bi, null, null);
1336 
1337         IntConsumer incrementTime = inc -> {
1338             state.currentTimeMs += inc;
1339             clock.realtime = clock.uptime = state.currentTimeMs;
1340 
1341             // If the device is not on battery, no timers should increment.
1342             if (!state.onBattery) return;
1343             // If the modem is not active, no timers should increment.
1344             if (!state.modemActive) return;
1345 
1346             final int currentRat = state.currentRat;
1347             final int currentFrequencyRange =
1348                     currentRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
1349             int currentSignalStrength = state.currentSignalStrengths.get(currentRat);
1350             expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
1351         };
1352 
1353 
1354         state.setOnBattery(false);
1355         state.setModemActive(false);
1356         state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
1357                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
1358         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
1359         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1360                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
1361         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1362                 expectedTxDurationsMs, bi, state.currentTimeMs);
1363 
1364         // While not on battery, the timers should not increase.
1365         state.setModemActive(true);
1366         incrementTime.accept(100);
1367         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1368                 expectedTxDurationsMs, bi, state.currentTimeMs);
1369 
1370         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
1371         incrementTime.accept(200);
1372         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1373                 expectedTxDurationsMs, bi, state.currentTimeMs);
1374 
1375         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
1376                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
1377         incrementTime.accept(500);
1378         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1379                 expectedTxDurationsMs, bi, state.currentTimeMs);
1380 
1381         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
1382         incrementTime.accept(300);
1383         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1384                 expectedTxDurationsMs, bi, state.currentTimeMs);
1385 
1386         state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
1387                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
1388         incrementTime.accept(400);
1389         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1390                 expectedTxDurationsMs, bi, state.currentTimeMs);
1391 
1392         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1393                 CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
1394         incrementTime.accept(500);
1395         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1396                 expectedTxDurationsMs, bi, state.currentTimeMs);
1397 
1398         // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
1399         // start counting up.
1400         state.setOnBattery(true);
1401         incrementTime.accept(600);
1402         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1403                 expectedTxDurationsMs, bi, state.currentTimeMs);
1404         // Changing LTE signal strength should be tracked.
1405         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1406                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
1407         incrementTime.accept(700);
1408         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1409                 expectedTxDurationsMs, bi, state.currentTimeMs);
1410 
1411         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1412                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
1413         incrementTime.accept(800);
1414         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1415                 expectedTxDurationsMs, bi, state.currentTimeMs);
1416 
1417         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1418                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
1419         incrementTime.accept(900);
1420         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1421                 expectedTxDurationsMs, bi, state.currentTimeMs);
1422 
1423         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1424                 CellSignalStrength.SIGNAL_STRENGTH_GREAT);
1425         incrementTime.accept(1000);
1426         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1427                 expectedTxDurationsMs, bi, state.currentTimeMs);
1428 
1429         // Change in the signal strength of nonactive RAT should not affect anything.
1430         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1431                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
1432         incrementTime.accept(1100);
1433         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1434                 expectedTxDurationsMs, bi, state.currentTimeMs);
1435 
1436         // Changing to OTHER Rat should start tracking the poor signal strength.
1437         state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
1438                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
1439         incrementTime.accept(1200);
1440         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1441                 expectedTxDurationsMs, bi, state.currentTimeMs);
1442 
1443         // Noting frequency change should not affect non NR Rat.
1444         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
1445         incrementTime.accept(1300);
1446         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1447                 expectedTxDurationsMs, bi, state.currentTimeMs);
1448 
1449         // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
1450         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
1451         incrementTime.accept(1400);
1452         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1453                 expectedTxDurationsMs, bi, state.currentTimeMs);
1454 
1455         // Noting frequency change should not affect non NR Rat.
1456         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
1457         incrementTime.accept(1500);
1458         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1459                 expectedTxDurationsMs, bi, state.currentTimeMs);
1460 
1461         // Modem no longer active, should not be tracking any more.
1462         state.setModemActive(false);
1463         incrementTime.accept(1500);
1464         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1465                 expectedTxDurationsMs, bi, state.currentTimeMs);
1466     }
1467 
1468     @SmallTest
testGetPerStateActiveRadioDurationMs_withModemActivity()1469     public void testGetPerStateActiveRadioDurationMs_withModemActivity() {
1470         final MockClock clock = new MockClock(); // holds realtime and uptime in ms
1471         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
1472         bi.setPowerProfile(mock(PowerProfile.class));
1473         final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
1474         final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
1475         final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
1476 
1477         final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
1478         final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
1479         final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
1480         for (int rat = 0; rat < ratCount; rat++) {
1481             for (int freq = 0; freq < frequencyCount; freq++) {
1482                 expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
1483 
1484                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
1485                     expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
1486                 }
1487             }
1488         }
1489 
1490         final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
1491         final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai, null);
1492 
1493         IntConsumer incrementTime = inc -> {
1494             state.currentTimeMs += inc;
1495             clock.realtime = clock.uptime = state.currentTimeMs;
1496 
1497             // If the device is not on battery, no timers should increment.
1498             if (!state.onBattery) return;
1499             // If the modem is not active, no timers should increment.
1500             if (!state.modemActive) return;
1501 
1502             final int currRat = state.currentRat;
1503             final int currFreqRange =
1504                     currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
1505             int currSignalStrength = state.currentSignalStrengths.get(currRat);
1506 
1507             expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
1508 
1509             // Evaluate the HAL provided time in states.
1510             switch (state.modemState) {
1511                 case SLEEP:
1512                     long sleepMs = state.modemActivityInfo.getSleepTimeMillis();
1513                     state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc);
1514                     break;
1515                 case IDLE:
1516                     long idleMs = state.modemActivityInfo.getIdleTimeMillis();
1517                     state.modemActivityInfo.setIdleTimeMillis(idleMs + inc);
1518                     break;
1519                 case RECEIVING:
1520                     long rxMs = state.modemActivityInfo.getReceiveTimeMillis();
1521                     state.modemActivityInfo.setReceiveTimeMillis(rxMs + inc);
1522                     expectedRxDurationsMs[currRat][currFreqRange] += inc;
1523                     break;
1524                 case TRANSMITTING:
1525                     int[] txMs = state.modemActivityInfo.getTransmitTimeMillis();
1526                     txMs[currSignalStrength] += inc;
1527                     state.modemActivityInfo.setTransmitTimeMillis(txMs);
1528                     expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
1529                     break;
1530             }
1531         };
1532 
1533         state.setOnBattery(false);
1534         state.setModemActive(false);
1535         state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
1536                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
1537         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
1538         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1539                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
1540         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1541                 expectedTxDurationsMs, bi, state.currentTimeMs);
1542 
1543         // While not on battery, the timers should not increase.
1544         state.setModemActive(true);
1545         incrementTime.accept(100);
1546         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1547                 expectedTxDurationsMs, bi, state.currentTimeMs);
1548 
1549         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
1550         incrementTime.accept(200);
1551         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1552                 expectedTxDurationsMs, bi, state.currentTimeMs);
1553 
1554         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
1555                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
1556         incrementTime.accept(500);
1557         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1558                 expectedTxDurationsMs, bi, state.currentTimeMs);
1559 
1560         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
1561         incrementTime.accept(300);
1562         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1563                 expectedTxDurationsMs, bi, state.currentTimeMs);
1564 
1565         state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
1566                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
1567         incrementTime.accept(400);
1568         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1569                 expectedTxDurationsMs, bi, state.currentTimeMs);
1570 
1571         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1572                 CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
1573         incrementTime.accept(500);
1574         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1575                 expectedTxDurationsMs, bi, state.currentTimeMs);
1576 
1577         // Data will now be available.
1578         for (int rat = 0; rat < ratCount; rat++) {
1579             for (int freq = 0; freq < frequencyCount; freq++) {
1580                 if (rat == RADIO_ACCESS_TECHNOLOGY_NR
1581                         || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
1582                     // Only the NR RAT should have per frequency data.
1583                     expectedRxDurationsMs[rat][freq] = 0;
1584                 }
1585                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
1586                     if (rat == RADIO_ACCESS_TECHNOLOGY_NR
1587                             || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
1588                         // Only the NR RAT should have per frequency data.
1589                         expectedTxDurationsMs[rat][freq][txLvl] = 0;
1590                     }
1591                 }
1592             }
1593         }
1594 
1595         // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
1596         // start counting up.
1597         state.setOnBattery(true);
1598         incrementTime.accept(300);
1599         state.setModemState(ModemState.RECEIVING);
1600         incrementTime.accept(500);
1601         state.setModemState(ModemState.TRANSMITTING);
1602         incrementTime.accept(600);
1603         state.noteModemControllerActivity();
1604         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1605                 expectedTxDurationsMs, bi, state.currentTimeMs);
1606         // Changing LTE signal strength should be tracked.
1607         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1608                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
1609         incrementTime.accept(300);
1610         state.setModemState(ModemState.SLEEP);
1611         incrementTime.accept(1000);
1612         state.setModemState(ModemState.RECEIVING);
1613         incrementTime.accept(700);
1614         state.noteModemControllerActivity();
1615         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1616                 expectedTxDurationsMs, bi, state.currentTimeMs);
1617 
1618         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1619                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
1620         incrementTime.accept(800);
1621         state.setModemState(ModemState.TRANSMITTING);
1622         incrementTime.accept(222);
1623         state.setModemState(ModemState.IDLE);
1624         incrementTime.accept(111);
1625         state.setModemState(ModemState.RECEIVING);
1626         incrementTime.accept(7777);
1627         state.noteModemControllerActivity();
1628         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1629                 expectedTxDurationsMs, bi, state.currentTimeMs);
1630 
1631         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1632                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
1633         incrementTime.accept(88);
1634         state.setModemState(ModemState.TRANSMITTING);
1635         incrementTime.accept(900);
1636         state.noteModemControllerActivity();
1637         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1638                 expectedTxDurationsMs, bi, state.currentTimeMs);
1639 
1640         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1641                 CellSignalStrength.SIGNAL_STRENGTH_GREAT);
1642         incrementTime.accept(123);
1643         state.setModemState(ModemState.RECEIVING);
1644         incrementTime.accept(333);
1645         state.setModemState(ModemState.TRANSMITTING);
1646         incrementTime.accept(1000);
1647         state.setModemState(ModemState.RECEIVING);
1648         incrementTime.accept(555);
1649         state.noteModemControllerActivity();
1650         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1651                 expectedTxDurationsMs, bi, state.currentTimeMs);
1652 
1653         // Change in the signal strength of nonactive RAT should not affect anything.
1654         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1655                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
1656         incrementTime.accept(631);
1657         state.setModemState(ModemState.TRANSMITTING);
1658         incrementTime.accept(321);
1659         state.setModemState(ModemState.RECEIVING);
1660         incrementTime.accept(99);
1661         state.noteModemControllerActivity();
1662         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1663                 expectedTxDurationsMs, bi, state.currentTimeMs);
1664 
1665         // Changing to OTHER Rat should start tracking the poor signal strength.
1666         state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
1667                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
1668         incrementTime.accept(1200);
1669         state.noteModemControllerActivity();
1670         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1671                 expectedTxDurationsMs, bi, state.currentTimeMs);
1672 
1673         // Noting frequency change should not affect non NR Rat.
1674         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
1675         incrementTime.accept(444);
1676         state.setModemState(ModemState.TRANSMITTING);
1677         incrementTime.accept(1300);
1678         state.noteModemControllerActivity();
1679         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1680                 expectedTxDurationsMs, bi, state.currentTimeMs);
1681 
1682         // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
1683         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
1684         incrementTime.accept(1400);
1685         state.noteModemControllerActivity();
1686         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1687                 expectedTxDurationsMs, bi, state.currentTimeMs);
1688 
1689         // Frequency changed to low.
1690         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
1691         incrementTime.accept(852);
1692         state.setModemState(ModemState.RECEIVING);
1693         incrementTime.accept(157);
1694         state.setModemState(ModemState.TRANSMITTING);
1695         incrementTime.accept(1500);
1696         state.noteModemControllerActivity();
1697         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1698                 expectedTxDurationsMs, bi, state.currentTimeMs);
1699 
1700         // Modem no longer active, should not be tracking any more.
1701         state.setModemActive(false);
1702         incrementTime.accept(1500);
1703         state.noteModemControllerActivity();
1704         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1705                 expectedTxDurationsMs, bi, state.currentTimeMs);
1706     }
1707 
1708     @SmallTest
testGetPerStateActiveRadioDurationMs_withSpecificInfoModemActivity()1709     public void testGetPerStateActiveRadioDurationMs_withSpecificInfoModemActivity() {
1710         final MockClock clock = new MockClock(); // holds realtime and uptime in ms
1711         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
1712         bi.setPowerProfile(mock(PowerProfile.class));
1713         final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
1714         final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
1715         final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
1716 
1717         List<ActivityStatsTechSpecificInfo> specificInfoList = new ArrayList();
1718 
1719         final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
1720         final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
1721         final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
1722         for (int rat = 0; rat < ratCount; rat++) {
1723             for (int freq = 0; freq < frequencyCount; freq++) {
1724                 if (rat == RADIO_ACCESS_TECHNOLOGY_NR
1725                         || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
1726                     // Initialize available specific Modem info
1727                     specificInfoList.add(
1728                             new ActivityStatsTechSpecificInfo(rat, freq, new int[txLevelCount], 0));
1729                 }
1730                 expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
1731 
1732                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
1733                     expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
1734                 }
1735             }
1736         }
1737 
1738         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.UNKNOWN,
1739                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1740         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.GERAN,
1741                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1742         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.UTRAN,
1743                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1744         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.EUTRAN,
1745                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1746         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.CDMA2000,
1747                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1748         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.IWLAN,
1749                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1750         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
1751                 ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
1752         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
1753                 ServiceState.FREQUENCY_RANGE_LOW, new int[txLevelCount], 0));
1754         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
1755                 ServiceState.FREQUENCY_RANGE_MID, new int[txLevelCount], 0));
1756         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
1757                 ServiceState.FREQUENCY_RANGE_HIGH, new int[txLevelCount], 0));
1758         specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
1759                 ServiceState.FREQUENCY_RANGE_MMWAVE, new int[txLevelCount], 0));
1760 
1761         final ActivityStatsTechSpecificInfo[] specificInfos = specificInfoList.toArray(
1762                 new ActivityStatsTechSpecificInfo[specificInfoList.size()]);
1763         final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, specificInfos);
1764         final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai, specificInfos);
1765 
1766         IntConsumer incrementTime = inc -> {
1767             state.currentTimeMs += inc;
1768             clock.realtime = clock.uptime = state.currentTimeMs;
1769 
1770             // If the device is not on battery, no timers should increment.
1771             if (!state.onBattery) return;
1772             // If the modem is not active, no timers should increment.
1773             if (!state.modemActive) return;
1774 
1775             final int currRat = state.currentRat;
1776             final int currRant = state.currentRadioAccessNetworkType;
1777             final int currFreqRange =
1778                     currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
1779             int currSignalStrength = state.currentSignalStrengths.get(currRat);
1780 
1781             expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
1782 
1783             // Evaluate the HAL provided time in states.
1784             final ActivityStatsTechSpecificInfo info = state.getSpecificInfo(currRant,
1785                     currFreqRange);
1786             switch (state.modemState) {
1787                 case SLEEP:
1788                     long sleepMs = state.modemActivityInfo.getSleepTimeMillis();
1789                     state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc);
1790                     break;
1791                 case IDLE:
1792                     long idleMs = state.modemActivityInfo.getIdleTimeMillis();
1793                     state.modemActivityInfo.setIdleTimeMillis(idleMs + inc);
1794                     break;
1795                 case RECEIVING:
1796                     long rxMs = info.getReceiveTimeMillis();
1797                     info.setReceiveTimeMillis(rxMs + inc);
1798                     expectedRxDurationsMs[currRat][currFreqRange] += inc;
1799                     break;
1800                 case TRANSMITTING:
1801                     int[] txMs = info.getTransmitTimeMillis().clone();
1802                     txMs[currSignalStrength] += inc;
1803                     info.setTransmitTimeMillis(txMs);
1804                     expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
1805                     break;
1806             }
1807         };
1808 
1809         state.setOnBattery(false);
1810         state.setModemActive(false);
1811         state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
1812                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1813                 AccessNetworkConstants.AccessNetworkType.UNKNOWN);
1814         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
1815         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1816                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
1817         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1818                 expectedTxDurationsMs, bi, state.currentTimeMs);
1819 
1820         // While not on battery, the timers should not increase.
1821         state.setModemActive(true);
1822         incrementTime.accept(100);
1823         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1824                 expectedTxDurationsMs, bi, state.currentTimeMs);
1825 
1826         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
1827                 AccessNetworkConstants.AccessNetworkType.NGRAN);
1828         incrementTime.accept(200);
1829         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1830                 expectedTxDurationsMs, bi, state.currentTimeMs);
1831 
1832         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
1833                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
1834         incrementTime.accept(500);
1835         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1836                 expectedTxDurationsMs, bi, state.currentTimeMs);
1837 
1838         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
1839         incrementTime.accept(300);
1840         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1841                 expectedTxDurationsMs, bi, state.currentTimeMs);
1842 
1843         state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
1844                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1845                 AccessNetworkConstants.AccessNetworkType.EUTRAN);
1846         incrementTime.accept(400);
1847         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1848                 expectedTxDurationsMs, bi, state.currentTimeMs);
1849 
1850         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1851                 CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
1852         incrementTime.accept(500);
1853         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1854                 expectedTxDurationsMs, bi, state.currentTimeMs);
1855 
1856         // Data will now be available.
1857         for (int rat = 0; rat < ratCount; rat++) {
1858             for (int freq = 0; freq < frequencyCount; freq++) {
1859                 if (rat == RADIO_ACCESS_TECHNOLOGY_NR
1860                         || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
1861                     // Only the NR RAT should have per frequency data.
1862                     expectedRxDurationsMs[rat][freq] = 0;
1863                 }
1864                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
1865                     if (rat == RADIO_ACCESS_TECHNOLOGY_NR
1866                             || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
1867                         // Only the NR RAT should have per frequency data.
1868                         expectedTxDurationsMs[rat][freq][txLvl] = 0;
1869                     }
1870                 }
1871             }
1872         }
1873 
1874         // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
1875         // start counting up.
1876         state.setOnBattery(true);
1877         state.noteModemControllerActivity();
1878         incrementTime.accept(300);
1879         state.setModemState(ModemState.RECEIVING);
1880         incrementTime.accept(500);
1881         state.setModemState(ModemState.TRANSMITTING);
1882         incrementTime.accept(600);
1883         state.noteModemControllerActivity();
1884         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1885                 expectedTxDurationsMs, bi, state.currentTimeMs);
1886         // Changing LTE signal strength should be tracked.
1887         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1888                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
1889         incrementTime.accept(300);
1890         state.setModemState(ModemState.SLEEP);
1891         incrementTime.accept(1000);
1892         state.setModemState(ModemState.RECEIVING);
1893         incrementTime.accept(700);
1894         state.noteModemControllerActivity();
1895         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1896                 expectedTxDurationsMs, bi, state.currentTimeMs);
1897 
1898         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1899                 CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
1900         incrementTime.accept(800);
1901         state.setModemState(ModemState.TRANSMITTING);
1902         incrementTime.accept(222);
1903         state.setModemState(ModemState.IDLE);
1904         incrementTime.accept(111);
1905         state.setModemState(ModemState.RECEIVING);
1906         incrementTime.accept(7777);
1907         state.noteModemControllerActivity();
1908         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1909                 expectedTxDurationsMs, bi, state.currentTimeMs);
1910 
1911         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1912                 CellSignalStrength.SIGNAL_STRENGTH_GOOD);
1913         incrementTime.accept(88);
1914         state.setModemState(ModemState.TRANSMITTING);
1915         incrementTime.accept(900);
1916         state.noteModemControllerActivity();
1917         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1918                 expectedTxDurationsMs, bi, state.currentTimeMs);
1919 
1920         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
1921                 CellSignalStrength.SIGNAL_STRENGTH_GREAT);
1922         incrementTime.accept(123);
1923         state.setModemState(ModemState.RECEIVING);
1924         incrementTime.accept(333);
1925         state.setModemState(ModemState.TRANSMITTING);
1926         incrementTime.accept(1000);
1927         state.setModemState(ModemState.RECEIVING);
1928         incrementTime.accept(555);
1929         state.noteModemControllerActivity();
1930         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1931                 expectedTxDurationsMs, bi, state.currentTimeMs);
1932 
1933         // Change in the signal strength of nonactive RAT should not affect anything.
1934         state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1935                 CellSignalStrength.SIGNAL_STRENGTH_POOR);
1936         incrementTime.accept(631);
1937         state.setModemState(ModemState.TRANSMITTING);
1938         incrementTime.accept(321);
1939         state.setModemState(ModemState.RECEIVING);
1940         incrementTime.accept(99);
1941         state.noteModemControllerActivity();
1942         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1943                 expectedTxDurationsMs, bi, state.currentTimeMs);
1944 
1945         // Changing to OTHER Rat should start tracking the poor signal strength.
1946         state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
1947                 BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
1948                 AccessNetworkConstants.AccessNetworkType.CDMA2000);
1949         incrementTime.accept(1200);
1950         state.noteModemControllerActivity();
1951         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1952                 expectedTxDurationsMs, bi, state.currentTimeMs);
1953 
1954         // Noting frequency change should not affect non NR Rat.
1955         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
1956         incrementTime.accept(444);
1957         state.setModemState(ModemState.TRANSMITTING);
1958         incrementTime.accept(1300);
1959         state.noteModemControllerActivity();
1960         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1961                 expectedTxDurationsMs, bi, state.currentTimeMs);
1962 
1963         // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
1964         state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
1965                 AccessNetworkConstants.AccessNetworkType.NGRAN);
1966         incrementTime.accept(1400);
1967         state.noteModemControllerActivity();
1968         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1969                 expectedTxDurationsMs, bi, state.currentTimeMs);
1970 
1971         // Frequency changed to low.
1972         state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
1973         incrementTime.accept(852);
1974         state.setModemState(ModemState.RECEIVING);
1975         incrementTime.accept(157);
1976         state.setModemState(ModemState.TRANSMITTING);
1977         incrementTime.accept(1500);
1978         state.noteModemControllerActivity();
1979         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1980                 expectedTxDurationsMs, bi, state.currentTimeMs);
1981 
1982         // Modem no longer active, should not be tracking any more.
1983         state.setModemActive(false);
1984         incrementTime.accept(1500);
1985         state.noteModemControllerActivity();
1986         checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
1987                 expectedTxDurationsMs, bi, state.currentTimeMs);
1988     }
1989 
1990     @SmallTest
1991     @SuppressWarnings("GuardedBy")
testProcStateSyncScheduling_mobileRadioActiveState()1992     public void testProcStateSyncScheduling_mobileRadioActiveState() {
1993         final MockClock clock = new MockClock(); // holds realtime and uptime in ms
1994         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
1995         final MutableInt lastProcStateChangeFlags = new MutableInt(0);
1996 
1997         MockBatteryStatsImpl.DummyExternalStatsSync externalStatsSync =
1998                 new MockBatteryStatsImpl.DummyExternalStatsSync() {
1999                     @Override
2000                     public void scheduleSyncDueToProcessStateChange(int flags,
2001                             long delayMillis) {
2002                         lastProcStateChangeFlags.value = flags;
2003                     }
2004                 };
2005 
2006         bi.setDummyExternalStatsSync(externalStatsSync);
2007 
2008         bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
2009 
2010         // Note mobile radio is on.
2011         long curr = 1000L * (clock.realtime = clock.uptime = 1001);
2012         bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
2013                 UID);
2014 
2015         lastProcStateChangeFlags.value = 0;
2016         clock.realtime = clock.uptime = 2002;
2017         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
2018 
2019         final int allProcFlags = BatteryStatsImpl.ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE;
2020         assertEquals(allProcFlags, lastProcStateChangeFlags.value);
2021 
2022         // Note mobile radio is off.
2023         curr = 1000L * (clock.realtime = clock.uptime = 3003);
2024         bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, curr,
2025                 UID);
2026 
2027         lastProcStateChangeFlags.value = 0;
2028         clock.realtime = clock.uptime = 4004;
2029         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2030 
2031         final int noRadioProcFlags = BatteryStatsImpl.ExternalStatsSync.UPDATE_ON_PROC_STATE_CHANGE
2032                 & ~BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO;
2033         assertEquals(
2034                 "An inactive radio should not be queried on proc state change",
2035                 noRadioProcFlags, lastProcStateChangeFlags.value);
2036     }
2037 
2038 
2039 
2040     @SmallTest
testNoteMobileRadioPowerStateLocked()2041     public void testNoteMobileRadioPowerStateLocked() {
2042         long curr;
2043         boolean update;
2044         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
2045         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
2046         bi.setOnBatteryInternal(true);
2047 
2048         // Note mobile radio is on.
2049         curr = 1000L * (clocks.realtime = clocks.uptime = 1001);
2050         bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
2051                 UID);
2052 
2053         // Note mobile radio is still on.
2054         curr = 1000L * (clocks.realtime = clocks.uptime = 2001);
2055         update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
2056                 curr, UID);
2057         assertFalse(
2058                 "noteMobileRadioPowerStateLocked should not request an update when the power "
2059                         + "state does not change from HIGH.",
2060                 update);
2061 
2062         // Note mobile radio is off.
2063         curr = 1000L * (clocks.realtime = clocks.uptime = 3001);
2064         update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
2065                 curr, UID);
2066         assertTrue(
2067                 "noteMobileRadioPowerStateLocked should request an update when the power state "
2068                         + "changes from HIGH to LOW.",
2069                 update);
2070 
2071         // Note mobile radio is still off.
2072         curr = 1000L * (clocks.realtime = clocks.uptime = 4001);
2073         update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
2074                 curr, UID);
2075         assertFalse(
2076                 "noteMobileRadioPowerStateLocked should not request an update when the power "
2077                         + "state does not change from LOW.",
2078                 update);
2079 
2080         // Note mobile radio is on.
2081         curr = 1000L * (clocks.realtime = clocks.uptime = 5001);
2082         update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
2083                 curr, UID);
2084         assertFalse(
2085                 "noteMobileRadioPowerStateLocked should not request an update when the power "
2086                         + "state changes from LOW to HIGH.",
2087                 update);
2088     }
2089 
2090     @SmallTest
testNoteMobileRadioPowerStateLocked_rateLimited()2091     public void testNoteMobileRadioPowerStateLocked_rateLimited() {
2092         long curr;
2093         boolean update;
2094         final MockClock clocks = new MockClock(); // holds realtime and uptime in ms
2095         final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
2096         bi.setPowerProfile(mock(PowerProfile.class));
2097 
2098         final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
2099         final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
2100 
2101         final long rateLimit = bi.getMobileRadioPowerStateUpdateRateLimit();
2102         if (rateLimit < 0) {
2103             Log.w(TAG, "Skipping testNoteMobileRadioPowerStateLocked_rateLimited, rateLimit = "
2104                     + rateLimit);
2105             return;
2106         }
2107         bi.setOnBatteryInternal(true);
2108 
2109         // Note mobile radio is on.
2110         curr = 1000L * (clocks.realtime = clocks.uptime = 1001);
2111         bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
2112                 UID);
2113 
2114         clocks.realtime = clocks.uptime = 2001;
2115         mai.setTimestamp(clocks.realtime);
2116         bi.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE,
2117                 clocks.realtime, clocks.uptime, mNetworkStatsManager);
2118 
2119         // Note mobile radio is off within the rate limit duration.
2120         clocks.realtime = clocks.uptime = clocks.realtime + (long) (rateLimit * 0.7);
2121         curr = 1000L * clocks.realtime;
2122         update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
2123                 curr, UID);
2124         assertFalse(
2125                 "noteMobileRadioPowerStateLocked should not request an update when the power "
2126                         + "state so soon after a noteModemControllerActivity",
2127                 update);
2128 
2129         // Note mobile radio is on.
2130         clocks.realtime = clocks.uptime = clocks.realtime + (long) (rateLimit * 0.7);
2131         curr = 1000L * clocks.realtime;
2132         bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, curr,
2133                 UID);
2134 
2135         // Note mobile radio is off much later
2136         clocks.realtime = clocks.uptime = clocks.realtime + rateLimit;
2137         curr = 1000L * clocks.realtime;
2138         update = bi.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
2139                 curr, UID);
2140         assertTrue(
2141                 "noteMobileRadioPowerStateLocked should request an update when the power state "
2142                         + "changes from HIGH to LOW much later after a "
2143                         + "noteModemControllerActivity.",
2144                 update);
2145     }
2146 
setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi)2147     private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
2148         // Note that noteUidProcessStateLocked uses ActivityManager process states.
2149         if (fgOn) {
2150             bi.noteActivityResumedLocked(uid);
2151             bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_TOP);
2152         } else {
2153             bi.noteActivityPausedLocked(uid);
2154             bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2155         }
2156     }
2157 
checkMeasuredCharge(String caseName, int uid1, long blame1, int uid2, long blame2, long globalDoze, MockBatteryStatsImpl bi)2158     private void checkMeasuredCharge(String caseName, int uid1, long blame1, int uid2, long blame2,
2159             long globalDoze, MockBatteryStatsImpl bi) {
2160         final int bucket = MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON;
2161 
2162         assertEquals("Wrong uid1 blame for Case " + caseName, blame1,
2163                 bi.getUidStatsLocked(uid1).getMeasuredBatteryConsumptionUC(bucket));
2164 
2165         assertEquals("Wrong uid2 blame for Case " + caseName, blame2,
2166                 bi.getUidStatsLocked(uid2).getMeasuredBatteryConsumptionUC(bucket));
2167 
2168         assertEquals("Wrong total blame for Case " + caseName, blame1 + blame2,
2169                 bi.getScreenOnMeasuredBatteryConsumptionUC());
2170 
2171         assertEquals("Wrong doze for Case " + caseName, globalDoze,
2172                 bi.getScreenDozeMeasuredBatteryConsumptionUC());
2173     }
2174 
checkCustomBatteryConsumption(String caseName, long totalBlameA, long totalBlameB, int uid1, long blame1A, long blame1B, int uid2, long blame2A, long blame2B, MockBatteryStatsImpl bi)2175     private void checkCustomBatteryConsumption(String caseName,
2176             long totalBlameA, long totalBlameB,
2177             int uid1, long blame1A, long blame1B,
2178             int uid2, long blame2A, long blame2B,
2179             MockBatteryStatsImpl bi) {
2180 
2181         final long[] actualTotal = bi.getCustomConsumerMeasuredBatteryConsumptionUC();
2182         final long[] actualUid1 =
2183                 bi.getUidStatsLocked(uid1).getCustomConsumerMeasuredBatteryConsumptionUC();
2184         final long[] actualUid2 =
2185                 bi.getUidStatsLocked(uid2).getCustomConsumerMeasuredBatteryConsumptionUC();
2186 
2187         assertNotNull(actualTotal);
2188         assertNotNull(actualUid1);
2189         assertNotNull(actualUid2);
2190 
2191         assertEquals("Wrong total blame in bucket 0 for Case " + caseName, totalBlameA,
2192                 actualTotal[0]);
2193 
2194         assertEquals("Wrong total blame in bucket 1 for Case " + caseName, totalBlameB,
2195                 actualTotal[1]);
2196 
2197         assertEquals("Wrong uid1 blame in bucket 0 for Case " + caseName, blame1A, actualUid1[0]);
2198 
2199         assertEquals("Wrong uid1 blame in bucket 1 for Case " + caseName, blame1B, actualUid1[1]);
2200 
2201         assertEquals("Wrong uid2 blame in bucket 0 for Case " + caseName, blame2A, actualUid2[0]);
2202 
2203         assertEquals("Wrong uid2 blame in bucket 1 for Case " + caseName, blame2B, actualUid2[1]);
2204     }
2205 
checkScreenBrightnesses(long[] overallExpected, long[][] perDisplayExpected, BatteryStatsImpl bi, long currentTimeMs)2206     private void checkScreenBrightnesses(long[] overallExpected, long[][] perDisplayExpected,
2207             BatteryStatsImpl bi, long currentTimeMs) {
2208         final int numDisplay = bi.getDisplayCount();
2209         for (int bin = 0; bin < NUM_SCREEN_BRIGHTNESS_BINS; bin++) {
2210             for (int display = 0; display < numDisplay; display++) {
2211                 assertEquals("Failure for display " + display + " screen brightness bin " + bin,
2212                         perDisplayExpected[display][bin] * 1000,
2213                         bi.getDisplayScreenBrightnessTime(display, bin, currentTimeMs * 1000));
2214             }
2215             assertEquals("Failure for overall screen brightness bin " + bin,
2216                     overallExpected[bin] * 1000,
2217                     bi.getScreenBrightnessTime(bin, currentTimeMs * 1000, STATS_SINCE_CHARGED));
2218         }
2219     }
2220 
checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs, long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs, BatteryStatsImpl bi, long currentTimeMs)2221     private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
2222             long[][] expectedRxDurationsMs, long[][][] expectedTxDurationsMs,
2223             BatteryStatsImpl bi, long currentTimeMs) {
2224         for (int rat = 0; rat < expectedDurationsMs.length; rat++) {
2225             final long[][] expectedRatDurationsMs = expectedDurationsMs[rat];
2226             for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) {
2227                 final long expectedRxDurationMs = expectedRxDurationsMs[rat][freq];
2228 
2229                 // Build a verbose fail message, just in case.
2230                 final StringBuilder rxFailSb = new StringBuilder();
2231                 rxFailSb.append("Wrong time in Rx state for RAT:");
2232                 rxFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
2233                 rxFailSb.append(", frequency:");
2234                 rxFailSb.append(ServiceState.frequencyRangeToString(freq));
2235                 assertEquals(rxFailSb.toString(), expectedRxDurationMs,
2236                         bi.getActiveRxRadioDurationMs(rat, freq, currentTimeMs));
2237 
2238                 final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
2239                 for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
2240                     final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength];
2241                     final long expectedTxDurationMs = expectedTxDurationsMs[rat][freq][strength];
2242                     final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq,
2243                             strength, currentTimeMs);
2244 
2245                     final StringBuilder failSb = new StringBuilder();
2246                     failSb.append("Wrong time in state for RAT:");
2247                     failSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
2248                     failSb.append(", frequency:");
2249                     failSb.append(ServiceState.frequencyRangeToString(freq));
2250                     failSb.append(", strength:");
2251                     failSb.append(strength);
2252                     assertEquals(failSb.toString(), expectedSignalStrengthDurationMs,
2253                             actualDurationMs);
2254 
2255                     final StringBuilder txFailSb = new StringBuilder();
2256                     txFailSb.append("Wrong time in Tx state for RAT:");
2257                     txFailSb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
2258                     txFailSb.append(", frequency:");
2259                     txFailSb.append(ServiceState.frequencyRangeToString(freq));
2260                     txFailSb.append(", strength:");
2261                     txFailSb.append(strength);
2262                     assertEquals(txFailSb.toString(), expectedTxDurationMs,
2263                             bi.getActiveTxRadioDurationMs(rat, freq, strength, currentTimeMs));
2264                 }
2265             }
2266         }
2267     }
2268 
2269     private class ModemAndBatteryState {
2270         public long currentTimeMs = 100;
2271         public boolean onBattery = false;
2272         public boolean modemActive = false;
2273         @Annotation.NetworkType
2274         public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
2275         @BatteryStats.RadioAccessTechnology
2276         public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
2277         @AccessNetworkConstants.RadioAccessNetworkType
2278         public int currentRadioAccessNetworkType = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
2279         @ServiceState.FrequencyRange
2280         public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
2281         public SparseIntArray currentSignalStrengths = new SparseIntArray();
2282         public ModemState modemState = ModemState.SLEEP;
2283         public ModemActivityInfo modemActivityInfo;
2284         public ActivityStatsTechSpecificInfo[] specificInfo;
2285 
2286         private final MockBatteryStatsImpl mBsi;
2287 
ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai, ActivityStatsTechSpecificInfo[] astsi)2288         ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai,
2289                 ActivityStatsTechSpecificInfo[] astsi) {
2290             mBsi = bsi;
2291             modemActivityInfo = mai;
2292             specificInfo = astsi;
2293         }
2294 
setOnBattery(boolean onBattery)2295         void setOnBattery(boolean onBattery) {
2296             this.onBattery = onBattery;
2297             mBsi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
2298                     currentTimeMs * 1000);
2299             mBsi.setOnBatteryInternal(onBattery);
2300             noteModemControllerActivity();
2301         }
2302 
setModemActive(boolean active)2303         void setModemActive(boolean active) {
2304             modemActive = active;
2305             final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
2306                     : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
2307             mBsi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
2308             noteModemControllerActivity();
2309         }
2310 
setRatType(@nnotation.NetworkType int dataType, @BatteryStats.RadioAccessTechnology int rat, @AccessNetworkConstants.RadioAccessNetworkType int halDataType)2311         void setRatType(@Annotation.NetworkType int dataType,
2312                 @BatteryStats.RadioAccessTechnology int rat,
2313                 @AccessNetworkConstants.RadioAccessNetworkType int halDataType) {
2314             currentRadioAccessNetworkType = halDataType;
2315             setRatType(dataType, rat);
2316         }
2317 
setRatType(@nnotation.NetworkType int dataType, @BatteryStats.RadioAccessTechnology int rat)2318         void setRatType(@Annotation.NetworkType int dataType,
2319                 @BatteryStats.RadioAccessTechnology int rat) {
2320             currentNetworkDataType = dataType;
2321             currentRat = rat;
2322             mBsi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
2323                     currentFrequencyRange);
2324         }
2325 
setFrequencyRange(@erviceState.FrequencyRange int frequency)2326         void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
2327             currentFrequencyRange = frequency;
2328             mBsi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
2329                     ServiceState.STATE_IN_SERVICE, frequency);
2330         }
2331 
setSignalStrength(@atteryStats.RadioAccessTechnology int rat, int strength)2332         void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
2333             currentSignalStrengths.put(rat, strength);
2334             final int size = currentSignalStrengths.size();
2335             final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
2336             mBsi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
2337         }
2338 
setModemState(ModemState state)2339         void setModemState(ModemState state) {
2340             modemState = state;
2341         }
2342 
getSpecificInfo(@atteryStats.RadioAccessTechnology int rat, @ServiceState.FrequencyRange int frequency)2343         ActivityStatsTechSpecificInfo getSpecificInfo(@BatteryStats.RadioAccessTechnology int rat,
2344                 @ServiceState.FrequencyRange int frequency) {
2345             if (specificInfo == null) return null;
2346             for (ActivityStatsTechSpecificInfo info : specificInfo) {
2347                 if (info.getRat() == rat && info.getFrequencyRange() == frequency) {
2348                     return info;
2349                 }
2350             }
2351             return null;
2352         }
2353 
noteModemControllerActivity()2354         void noteModemControllerActivity() {
2355             if (modemActivityInfo == null) return;
2356             modemActivityInfo.setTimestamp(currentTimeMs);
2357             final ModemActivityInfo copy;
2358             if (specificInfo == null) {
2359                 copy = new ModemActivityInfo(
2360                         modemActivityInfo.getTimestampMillis(),
2361                         modemActivityInfo.getSleepTimeMillis(),
2362                         modemActivityInfo.getIdleTimeMillis(),
2363                         modemActivityInfo.getTransmitTimeMillis().clone(),
2364                         modemActivityInfo.getReceiveTimeMillis());
2365             } else {
2366                 // Deep copy specificInfo
2367                 final ActivityStatsTechSpecificInfo[] infoCopies =
2368                         new ActivityStatsTechSpecificInfo[specificInfo.length];
2369                 for (int i = 0; i < specificInfo.length; i++) {
2370                     final ActivityStatsTechSpecificInfo info = specificInfo[i];
2371                     infoCopies[i] = new ActivityStatsTechSpecificInfo(info.getRat(),
2372                             info.getFrequencyRange(), info.getTransmitTimeMillis().clone(),
2373                             (int) info.getReceiveTimeMillis());
2374                 }
2375 
2376                 copy = new ModemActivityInfo(
2377                         modemActivityInfo.getTimestampMillis(),
2378                         modemActivityInfo.getSleepTimeMillis(),
2379                         modemActivityInfo.getIdleTimeMillis(),
2380                         infoCopies);
2381             }
2382             mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE,
2383                     currentTimeMs, currentTimeMs, mNetworkStatsManager);
2384         }
2385     }
2386 }
2387