1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.power.stats;
18 
19 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
20 import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
21 import static android.os.Process.FIRST_APPLICATION_UID;
22 import static android.os.Process.FIRST_ISOLATED_UID;
23 
24 import static com.android.server.power.stats.BatteryStatsImpl.WAKE_LOCK_WEIGHT;
25 
26 import static org.junit.Assert.assertArrayEquals;
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertNull;
30 import static org.junit.Assert.assertTrue;
31 import static org.mockito.ArgumentMatchers.any;
32 import static org.mockito.ArgumentMatchers.anyBoolean;
33 import static org.mockito.ArgumentMatchers.isNull;
34 import static org.mockito.Mockito.doAnswer;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.verifyNoMoreInteractions;
37 import static org.mockito.Mockito.when;
38 
39 import android.os.BatteryStats;
40 import android.os.Handler;
41 import android.os.Looper;
42 import android.os.UserHandle;
43 import android.platform.test.ravenwood.RavenwoodRule;
44 import android.util.SparseArray;
45 import android.util.SparseLongArray;
46 import android.view.Display;
47 
48 import androidx.test.filters.SmallTest;
49 import androidx.test.runner.AndroidJUnit4;
50 
51 import com.android.internal.os.CpuScalingPolicies;
52 import com.android.internal.os.KernelCpuSpeedReader;
53 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
54 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
55 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
56 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
57 import com.android.internal.util.ArrayUtils;
58 
59 import org.junit.Before;
60 import org.junit.Rule;
61 import org.junit.Test;
62 import org.junit.runner.RunWith;
63 import org.mockito.Mock;
64 import org.mockito.Mockito;
65 import org.mockito.MockitoAnnotations;
66 
67 import java.util.ArrayList;
68 import java.util.Arrays;
69 
70 /**
71  * To run the tests, use
72  *
73  * runtest -c BatteryStatsCpuTimesTest frameworks-core
74  *
75  * or
76  *
77  * Build: m FrameworksCoreTests
78  * Install: adb install -r \
79  * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
80  * Run: adb shell am instrument -e class BatteryStatsCpuTimesTest -w \
81  * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
82  *
83  * or
84  *
85  * atest FrameworksCoreTests:BatteryStatsCpuTimesTest
86  */
87 @SmallTest
88 @RunWith(AndroidJUnit4.class)
89 @SuppressWarnings("SynchronizeOnNonFinalField")
90 public class BatteryStatsCpuTimesTest {
91     @Rule
92     public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
93             .setProvideMainThread(true)
94             .build();
95 
96     @Mock
97     KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
98     @Mock
99     KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
100     @Mock
101     KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
102     @Mock
103     KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
104     @Mock
105     SystemServerCpuThreadReader mSystemServerCpuThreadReader;
106     @Mock
107     BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
108 
109     private MockClock mClocks;
110     private PowerStatsUidResolver mPowerStatsUidResolver;
111     private MockBatteryStatsImpl mBatteryStatsImpl;
112     private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
113 
114     @Before
setUp()115     public void setUp() {
116         MockitoAnnotations.initMocks(this);
117 
118         mClocks = new MockClock();
119         Handler handler = new Handler(Looper.getMainLooper());
120         mPowerStatsUidResolver = new PowerStatsUidResolver();
121         mBatteryStatsImpl = new MockBatteryStatsImpl(MockBatteryStatsImpl.DEFAULT_CONFIG,
122                 mClocks, null, handler, mPowerStatsUidResolver)
123                 .setTestCpuScalingPolicies()
124                 .setKernelCpuUidUserSysTimeReader(mCpuUidUserSysTimeReader)
125                 .setKernelCpuUidFreqTimeReader(mCpuUidFreqTimeReader)
126                 .setKernelCpuUidActiveTimeReader(mCpuUidActiveTimeReader)
127                 .setKernelCpuUidClusterTimeReader(mCpuUidClusterTimeReader)
128                 .setSystemServerCpuThreadReader(mSystemServerCpuThreadReader)
129                 .setUserInfoProvider(mUserInfoProvider);
130     }
131 
132     @Test
testUpdateCpuTimeLocked()133     public void testUpdateCpuTimeLocked() {
134         // PRECONDITIONS
135         mBatteryStatsImpl.setOnBatteryInternal(false);
136         final int numClusters = 3;
137         initKernelCpuSpeedReaders(numClusters);
138 
139         // RUN
140         synchronized (mBatteryStatsImpl) {
141             mBatteryStatsImpl.updateCpuTimeLocked(false, false, null);
142         }
143 
144         // VERIFY
145         verify(mCpuUidUserSysTimeReader).readDelta(anyBoolean(), isNull());
146         verify(mCpuUidFreqTimeReader).readDelta(anyBoolean(), isNull());
147         for (int i = 0; i < numClusters; ++i) {
148             verify(mKernelCpuSpeedReaders[i]).readDelta();
149         }
150 
151         // Prepare for next test
152         Mockito.reset(mUserInfoProvider, mCpuUidFreqTimeReader, mCpuUidUserSysTimeReader);
153         for (int i = 0; i < numClusters; ++i) {
154             Mockito.reset(mKernelCpuSpeedReaders[i]);
155         }
156 
157         // PRECONDITIONS
158         mBatteryStatsImpl.setOnBatteryInternal(true);
159 
160         // RUN
161         synchronized (mBatteryStatsImpl) {
162             mBatteryStatsImpl.updateCpuTimeLocked(true, false, null);
163         }
164 
165         // VERIFY
166         verify(mUserInfoProvider).refreshUserIds();
167         verify(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
168                 any(KernelCpuUidUserSysTimeReader.Callback.class));
169         verify(mCpuUidFreqTimeReader).perClusterTimesAvailable();
170         verify(mCpuUidFreqTimeReader).allUidTimesAvailable();
171         verify(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
172                 any(KernelCpuUidFreqTimeReader.Callback.class));
173         verify(mCpuUidActiveTimeReader).readAbsolute(
174                 any(KernelCpuUidActiveTimeReader.Callback.class));
175         verify(mCpuUidClusterTimeReader).readDelta(anyBoolean(),
176                 any(KernelCpuUidClusterTimeReader.Callback.class));
177         verifyNoMoreInteractions(mCpuUidFreqTimeReader);
178         for (int i = 0; i < numClusters; ++i) {
179             verify(mKernelCpuSpeedReaders[i]).readDelta();
180         }
181     }
182 
183     @Test
testMarkPartialTimersAsEligible()184     public void testMarkPartialTimersAsEligible() {
185         // PRECONDITIONS
186         final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers = getPartialTimers(
187                 10032, 10042, 10052);
188         final ArrayList<BatteryStatsImpl.StopwatchTimer> lastPartialTimers
189                 = new ArrayList<>(partialTimers);
190         mBatteryStatsImpl.setPartialTimers(partialTimers);
191         mBatteryStatsImpl.setLastPartialTimers(lastPartialTimers);
192         final boolean[] inList = {false, true, false};
193         for (int i = 0; i < partialTimers.size(); ++i) {
194             partialTimers.get(i).mInList = inList[i];
195         }
196 
197         // RUN
198         mBatteryStatsImpl.markPartialTimersAsEligible();
199 
200         // VERIFY
201         assertTrue(ArrayUtils.referenceEquals(partialTimers, lastPartialTimers));
202         for (int i = 0; i < partialTimers.size(); ++i) {
203             assertTrue("Timer id=" + i, partialTimers.get(i).mInList);
204         }
205 
206         // PRECONDITIONS
207         partialTimers.addAll(getPartialTimers(10077, 10099));
208         partialTimers.remove(1 /* index */);
209 
210         // RUN
211         mBatteryStatsImpl.markPartialTimersAsEligible();
212 
213         // VERIFY
214         assertTrue(ArrayUtils.referenceEquals(partialTimers, lastPartialTimers));
215         for (int i = 0; i < partialTimers.size(); ++i) {
216             assertTrue("Timer id=" + i, partialTimers.get(i).mInList);
217         }
218     }
219 
220     @Test
testUpdateClusterSpeedTimes()221     public void testUpdateClusterSpeedTimes() {
222         // PRECONDITIONS
223         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
224         final long[][] clusterSpeedTimesMs = {{20, 30}, {40, 50, 60}};
225 
226         CpuScalingPolicies scalingPolicies = new CpuScalingPolicies(
227                 new SparseArray<>() {{
228                     for (int i = 0; i < clusterSpeedTimesMs.length; i++) {
229                         put(i, new int[]{i});
230                     }
231                 }},
232                 new SparseArray<>() {{
233                     for (int i = 0; i < clusterSpeedTimesMs.length; i++) {
234                         put(i, new int[clusterSpeedTimesMs[i].length]);
235                     }
236                 }});
237         mBatteryStatsImpl.setCpuScalingPolicies(scalingPolicies);
238 
239         initKernelCpuSpeedReaders(clusterSpeedTimesMs.length);
240         for (int i = 0; i < clusterSpeedTimesMs.length; ++i) {
241             when(mKernelCpuSpeedReaders[i].readDelta()).thenReturn(clusterSpeedTimesMs[i]);
242         }
243 
244         final SparseLongArray updatedUids = new SparseLongArray();
245         final int[] testUids = {10012, 10014, 10016};
246         final int[] cpuTimeUs = {89, 31, 43};
247         for (int i = 0; i < testUids.length; ++i) {
248             updatedUids.put(testUids[i], cpuTimeUs[i]);
249         }
250 
251         // RUN
252         mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids, true, null);
253 
254         // VERIFY
255         long totalClustersTimeMs = 0;
256         for (int i = 0; i < clusterSpeedTimesMs.length; ++i) {
257             for (int j = 0; j < clusterSpeedTimesMs[i].length; ++j) {
258                 totalClustersTimeMs += clusterSpeedTimesMs[i][j];
259             }
260         }
261         for (int i = 0; i < testUids.length; ++i) {
262             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
263             assertNotNull("No entry for uid=" + testUids[i], u);
264             for (int cluster = 0; cluster < clusterSpeedTimesMs.length; ++cluster) {
265                 for (int speed = 0; speed < clusterSpeedTimesMs[cluster].length; ++speed) {
266                     assertEquals("Uid=" + testUids[i] + ", cluster=" + cluster + ", speed=" + speed,
267                             cpuTimeUs[i] * clusterSpeedTimesMs[cluster][speed]
268                                     / totalClustersTimeMs,
269                             u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
270                 }
271             }
272         }
273     }
274 
275     @Test
testReadKernelUidCpuTimesLocked()276     public void testReadKernelUidCpuTimesLocked() {
277         //PRECONDITIONS
278         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
279         final int testUserId = 11;
280         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
281         final int[] testUids = getUids(testUserId, new int[]{
282                 FIRST_APPLICATION_UID + 22,
283                 FIRST_APPLICATION_UID + 27,
284                 FIRST_APPLICATION_UID + 33
285         });
286         final long[][] uidTimesUs = {
287                 {12, 34}, {34897394, 3123983}, {79775429834L, 8430434903489L}
288         };
289         doAnswer(invocation -> {
290             final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
291                     invocation.getArgument(1);
292             for (int i = 0; i < testUids.length; ++i) {
293                 callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
294             }
295             return null;
296         }).when(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
297                 any(KernelCpuUidUserSysTimeReader.Callback.class));
298 
299         // RUN
300         final SparseLongArray updatedUids = new SparseLongArray();
301         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids, true);
302 
303         // VERIFY
304         for (int i = 0; i < testUids.length; ++i) {
305             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
306             assertNotNull("No entry for uid=" + testUids[i], u);
307             assertEquals("Unexpected user cpu time for uid=" + testUids[i],
308                     uidTimesUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
309             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
310                     uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
311 
312             assertEquals("Unexpected entry in updated uids for uid=" + testUids[i],
313                     uidTimesUs[i][0] + uidTimesUs[i][1], updatedUids.get(testUids[i]));
314             updatedUids.delete(testUids[i]);
315         }
316         assertEquals("Updated uids: " + updatedUids, 0, updatedUids.size());
317 
318         // Repeat the test with a null updatedUids
319 
320         // PRECONDITIONS
321         final long[][] deltasUs = {
322                 {9379, 3332409833484L}, {493247, 723234}, {3247819, 123348}
323         };
324         doAnswer(invocation -> {
325             final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
326                     invocation.getArgument(1);
327             for (int i = 0; i < testUids.length; ++i) {
328                 callback.onUidCpuTime(testUids[i], deltasUs[i]);
329             }
330             return null;
331         }).when(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
332                 any(KernelCpuUidUserSysTimeReader.Callback.class));
333 
334         // RUN
335         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
336 
337         // VERIFY
338         for (int i = 0; i < testUids.length; ++i) {
339             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
340             assertNotNull("No entry for uid=" + testUids[i], u);
341             assertEquals("Unexpected user cpu time for uid=" + testUids[i],
342                     uidTimesUs[i][0] + deltasUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
343             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
344                     uidTimesUs[i][1] + deltasUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
345         }
346     }
347 
348     @Test
testReadKernelUidCpuTimesLocked_isolatedUid()349     public void testReadKernelUidCpuTimesLocked_isolatedUid() {
350         //PRECONDITIONS
351         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
352         final int testUserId = 11;
353         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
354         final int isolatedAppId = FIRST_ISOLATED_UID + 27;
355         final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
356         final int[] testUids = getUids(testUserId, new int[]{
357                 FIRST_APPLICATION_UID + 22,
358                 isolatedAppId,
359                 FIRST_APPLICATION_UID + 33
360         });
361         final long[][] uidTimesUs = {
362                 {12, 34}, {34897394, 3123983}, {79775429834L, 8430434903489L}
363         };
364         doAnswer(invocation -> {
365             final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
366                     invocation.getArgument(1);
367             for (int i = 0; i < testUids.length; ++i) {
368                 callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
369             }
370             return null;
371         }).when(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
372                 any(KernelCpuUidUserSysTimeReader.Callback.class));
373 
374         // RUN
375         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
376 
377         // VERIFY
378         for (int i = 0; i < testUids.length; ++i) {
379             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
380             if (UserHandle.isIsolated(testUids[i])) {
381                 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
382                 continue;
383             }
384             assertNotNull("No entry for uid=" + testUids[i], u);
385             assertEquals("Unexpected user cpu time for uid=" + testUids[i],
386                     uidTimesUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
387             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
388                     uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
389         }
390 
391         // Add an isolated uid mapping and repeat the test.
392 
393         // PRECONDITIONS
394         final int ownerUid = UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 42);
395         mPowerStatsUidResolver.noteIsolatedUidAdded(isolatedUid, ownerUid);
396         final long[][] deltasUs = {
397                 {9379, 3332409833484L}, {493247, 723234}, {3247819, 123348}
398         };
399         doAnswer(invocation -> {
400             final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
401                     invocation.getArgument(1);
402             for (int i = 0; i < testUids.length; ++i) {
403                 callback.onUidCpuTime(testUids[i], deltasUs[i]);
404             }
405             return null;
406         }).when(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
407                 any(KernelCpuUidUserSysTimeReader.Callback.class));
408 
409         // RUN
410         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
411 
412         // VERIFY
413         for (int i = 0; i < testUids.length; ++i) {
414             BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
415             final long expectedUserTimeUs;
416             final long expectedSystemTimeUs;
417             if (UserHandle.isIsolated(testUids[i])) {
418                 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
419                 // Since we added a mapping, an entry should've been created for owner uid.
420                 u = mBatteryStatsImpl.getUidStats().get(ownerUid);
421                 expectedUserTimeUs = deltasUs[i][0];
422                 expectedSystemTimeUs = deltasUs[i][1];
423                 assertNotNull("No entry for owner uid=" + ownerUid, u);
424             } else {
425                 assertNotNull("No entry for uid=" + testUids[i], u);
426                 expectedUserTimeUs = uidTimesUs[i][0] + deltasUs[i][0];
427                 expectedSystemTimeUs = uidTimesUs[i][1] + deltasUs[i][1];
428             }
429             assertEquals("Unexpected user cpu time for uid=" + testUids[i],
430                     expectedUserTimeUs, u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
431             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
432                     expectedSystemTimeUs, u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
433         }
434     }
435 
436     @Test
testReadKernelUidCpuTimesLocked_invalidUid()437     public void testReadKernelUidCpuTimesLocked_invalidUid() {
438         //PRECONDITIONS
439         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
440         final int testUserId = 11;
441         final int invalidUserId = 15;
442         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
443         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
444         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
445         final int[] testUids = getUids(testUserId, new int[]{
446                 FIRST_APPLICATION_UID + 22,
447                 FIRST_APPLICATION_UID + 27,
448                 FIRST_APPLICATION_UID + 33
449         });
450         final long[][] uidTimesUs = {
451                 {12, 34}, {34897394, 3123983}, {79775429834L, 8430434903489L}
452         };
453         doAnswer(invocation -> {
454             final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
455                     invocation.getArgument(1);
456             for (int i = 0; i < testUids.length; ++i) {
457                 callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
458             }
459             // And one for the invalid uid
460             callback.onUidCpuTime(invalidUid, new long[]{3879, 239});
461             return null;
462         }).when(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
463                 any(KernelCpuUidUserSysTimeReader.Callback.class));
464 
465         // RUN
466         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
467 
468         // VERIFY
469         for (int i = 0; i < testUids.length; ++i) {
470             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
471             assertNotNull("No entry for uid=" + testUids[i], u);
472             assertEquals("Unexpected user cpu time for uid=" + testUids[i],
473                     uidTimesUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
474             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
475                     uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
476         }
477         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
478                 mBatteryStatsImpl.getUidStats().get(invalidUid));
479     }
480 
481     @Test
testReadKernelUidCpuTimesLocked_withPartialTimers()482     public void testReadKernelUidCpuTimesLocked_withPartialTimers() {
483         //PRECONDITIONS
484         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
485         final int testUserId = 11;
486         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
487         final int[] testUids = getUids(testUserId, new int[]{
488                 FIRST_APPLICATION_UID + 22,
489                 FIRST_APPLICATION_UID + 27,
490                 FIRST_APPLICATION_UID + 33
491         });
492         final int[] partialTimerUids = {
493                 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 48),
494                 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 10)
495         };
496         final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers
497                 = getPartialTimers(partialTimerUids);
498         final long[][] uidTimesUs = {
499                 {12, 34}, {3394, 3123}, {7977, 80434}
500         };
501         doAnswer(invocation -> {
502             final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
503                     invocation.getArgument(1);
504             for (int i = 0; i < testUids.length; ++i) {
505                 callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
506             }
507             return null;
508         }).when(mCpuUidUserSysTimeReader).readDelta(anyBoolean(),
509                 any(KernelCpuUidUserSysTimeReader.Callback.class));
510 
511         // RUN
512         final SparseLongArray updatedUids = new SparseLongArray();
513         mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids, true);
514 
515         // VERIFY
516         long totalUserTimeUs = 0;
517         long totalSystemTimeUs = 0;
518         for (int i = 0; i < testUids.length; ++i) {
519             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
520             assertNotNull("No entry for uid=" + testUids[i], u);
521             final long expectedUserTimeUs = uidTimesUs[i][0] * WAKE_LOCK_WEIGHT / 100;
522             final long expectedSystemTimeUs = uidTimesUs[i][1] * WAKE_LOCK_WEIGHT / 100;
523             assertEquals("Unexpected user cpu time for uid=" + testUids[i],
524                     expectedUserTimeUs, u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
525             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
526                     expectedSystemTimeUs, u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
527             assertEquals("Unexpected entry in updated uids for uid=" + testUids[i],
528                     expectedUserTimeUs + expectedSystemTimeUs, updatedUids.get(testUids[i]));
529             updatedUids.delete(testUids[i]);
530             totalUserTimeUs += uidTimesUs[i][0];
531             totalSystemTimeUs += uidTimesUs[i][1];
532         }
533 
534         totalUserTimeUs = totalUserTimeUs * (100 - WAKE_LOCK_WEIGHT) / 100;
535         totalSystemTimeUs = totalSystemTimeUs * (100 - WAKE_LOCK_WEIGHT) / 100;
536         for (int i = 0; i < partialTimerUids.length; ++i) {
537             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(partialTimerUids[i]);
538             assertNotNull("No entry for partial timer uid=" + partialTimerUids[i], u);
539             final long expectedUserTimeUs = totalUserTimeUs / (partialTimerUids.length - i);
540             final long expectedSystemTimeUs = totalSystemTimeUs / (partialTimerUids.length - i);
541             assertEquals("Unexpected user cpu time for partial timer uid=" + partialTimerUids[i],
542                     expectedUserTimeUs, u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
543             assertEquals("Unexpected system cpu time for partial timer uid=" + partialTimerUids[i],
544                     expectedSystemTimeUs, u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
545             assertEquals("Unexpected entry in updated uids for partial timer uid="
546                             + partialTimerUids[i],
547                     expectedUserTimeUs + expectedSystemTimeUs,
548                     updatedUids.get(partialTimerUids[i]));
549             updatedUids.delete(partialTimerUids[i]);
550             totalUserTimeUs -= expectedUserTimeUs;
551             totalSystemTimeUs -= expectedSystemTimeUs;
552 
553             final BatteryStats.Uid.Proc proc = u.getProcessStats().get("*wakelock*");
554             assertEquals("Unexpected user cpu time for *wakelock* in uid=" + partialTimerUids[i],
555                     expectedUserTimeUs / 1000, proc.getUserTime(STATS_SINCE_CHARGED));
556             assertEquals("Unexpected system cpu time for *wakelock* in uid=" + partialTimerUids[i],
557                     expectedSystemTimeUs / 1000, proc.getSystemTime(STATS_SINCE_CHARGED));
558         }
559         assertEquals(0, totalUserTimeUs);
560         assertEquals(0, totalSystemTimeUs);
561         assertEquals("Updated uids: " + updatedUids, 0, updatedUids.size());
562     }
563 
564     @Test
testReadKernelUidCpuFreqTimesLocked()565     public void testReadKernelUidCpuFreqTimesLocked() {
566         // PRECONDITIONS
567         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
568 
569         final int testUserId = 11;
570         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
571         final int[] testUids = getUids(testUserId, new int[]{
572                 FIRST_APPLICATION_UID + 22,
573                 FIRST_APPLICATION_UID + 27,
574                 FIRST_APPLICATION_UID + 33
575         });
576         final long[][] uidTimesMs = {
577                 {4, 10, 5, 9, 4},
578                 {5, 1, 12, 2, 10},
579                 {8, 25, 3, 0, 42}
580         };
581         doAnswer(invocation -> {
582             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
583                     invocation.getArgument(1);
584             for (int i = 0; i < testUids.length; ++i) {
585                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
586             }
587             return null;
588         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
589                 any(KernelCpuUidFreqTimeReader.Callback.class));
590 
591         // RUN
592         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null);
593 
594         // VERIFY
595         for (int i = 0; i < testUids.length; ++i) {
596             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
597             assertNotNull("No entry for uid=" + testUids[i], u);
598 
599             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
600                     uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
601             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
602                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
603         }
604 
605         // Repeat the test when the screen is off.
606 
607         // PRECONDITIONS
608         updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
609         final long[][] deltasMs = {
610                 {3, 12, 55, 100, 32},
611                 {3248327490475L, 232349349845043L, 123, 2398, 0},
612                 {43, 3345, 2143, 123, 4554}
613         };
614         doAnswer(invocation -> {
615             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
616                     invocation.getArgument(1);
617             for (int i = 0; i < testUids.length; ++i) {
618                 callback.onUidCpuTime(testUids[i], deltasMs[i]);
619             }
620             return null;
621         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
622                 any(KernelCpuUidFreqTimeReader.Callback.class));
623 
624         // RUN
625         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true, null);
626 
627         // VERIFY
628         for (int i = 0; i < testUids.length; ++i) {
629             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
630             assertNotNull("No entry for uid=" + testUids[i], u);
631 
632             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
633                     sum(uidTimesMs[i], deltasMs[i]), u.getCpuFreqTimes(STATS_SINCE_CHARGED));
634             assertArrayEquals("Unexpected screen-off cpu times for uid=" + testUids[i],
635                     deltasMs[i], u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
636         }
637     }
638 
639     @Test
testReadKernelUidCpuFreqTimesLocked_perClusterTimesAvailable()640     public void testReadKernelUidCpuFreqTimesLocked_perClusterTimesAvailable() {
641         // PRECONDITIONS
642         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
643 
644         final int testUserId = 11;
645         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
646         final int[] testUids = getUids(testUserId, new int[]{
647                 FIRST_APPLICATION_UID + 22,
648                 FIRST_APPLICATION_UID + 27,
649                 FIRST_APPLICATION_UID + 33
650         });
651         CpuScalingPolicies scalingPolicies = new CpuScalingPolicies(
652                 new SparseArray<>() {{
653                     put(0, new int[]{0});
654                     put(1, new int[]{1});
655                 }},
656                 new SparseArray<>() {{
657                     put(0, new int[]{1, 12, 123});
658                     put(1, new int[]{12, 1234});
659                 }});
660         mBatteryStatsImpl.setCpuScalingPolicies(scalingPolicies);
661         // Derived from freqs above, 2 clusters with {3, 2} freqs in each of them.
662         final int[] clusterFreqs = {3, 2};
663 
664         final long[][] uidTimesMs = {
665                 {4, 10, 5, 9, 4},
666                 {5, 1, 12, 2, 10},
667                 {8, 25, 3, 0, 42}
668         };
669         doAnswer(invocation -> {
670             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
671                     invocation.getArgument(1);
672             for (int i = 0; i < testUids.length; ++i) {
673                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
674             }
675             return null;
676         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
677                 any(KernelCpuUidFreqTimeReader.Callback.class));
678         when(mCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
679 
680         // RUN
681         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null);
682 
683         // VERIFY
684         for (int i = 0; i < testUids.length; ++i) {
685             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
686             assertNotNull("No entry for uid=" + testUids[i], u);
687 
688             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
689                     uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
690             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
691                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
692 
693             int idx = 0;
694             for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
695                 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
696                     assertEquals("Unexpected time at cluster=" + cluster + ", speed=" + speed,
697                             uidTimesMs[i][idx] * 1000,
698                             u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
699                     idx++;
700                 }
701             }
702         }
703 
704         // Repeat the test when the screen is off.
705 
706         // PRECONDITIONS
707         updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
708         final long[][] deltasMs = {
709                 {3, 12, 55, 100, 32},
710                 {3248327490475L, 232349349845043L, 123, 2398, 0},
711                 {43, 3345, 2143, 123, 4554}
712         };
713         doAnswer(invocation -> {
714             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
715                     invocation.getArgument(1);
716             for (int i = 0; i < testUids.length; ++i) {
717                 callback.onUidCpuTime(testUids[i], deltasMs[i]);
718             }
719             return null;
720         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
721                 any(KernelCpuUidFreqTimeReader.Callback.class));
722 
723         // RUN
724         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true, null);
725 
726         // VERIFY
727         for (int i = 0; i < testUids.length; ++i) {
728             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
729             assertNotNull("No entry for uid=" + testUids[i], u);
730 
731             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
732                     sum(uidTimesMs[i], deltasMs[i]), u.getCpuFreqTimes(STATS_SINCE_CHARGED));
733             assertArrayEquals("Unexpected screen-off cpu times for uid=" + testUids[i],
734                     deltasMs[i], u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
735 
736             int idx = 0;
737             for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
738                 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
739                     assertEquals("Unexpected time at cluster=" + cluster + ", speed=" + speed,
740                             (uidTimesMs[i][idx] + deltasMs[i][idx]) * 1000,
741                             u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
742                     idx++;
743                 }
744             }
745         }
746     }
747 
748     @Test
testReadKernelUidCpuFreqTimesLocked_partialTimers()749     public void testReadKernelUidCpuFreqTimesLocked_partialTimers() {
750         // PRECONDITIONS
751         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
752 
753         final int testUserId = 11;
754         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
755         final int[] testUids = getUids(testUserId, new int[]{
756                 FIRST_APPLICATION_UID + 22,
757                 FIRST_APPLICATION_UID + 27,
758                 FIRST_APPLICATION_UID + 33
759         });
760         final int[] partialTimerUids = {
761                 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 48),
762                 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 10)
763         };
764         final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers
765                 = getPartialTimers(partialTimerUids);
766 
767         CpuScalingPolicies scalingPolicies = new CpuScalingPolicies(
768                 new SparseArray<>() {{
769                     put(0, new int[]{0});
770                     put(1, new int[]{1});
771                 }},
772                 new SparseArray<>() {{
773                     put(0, new int[]{1, 12, 123});
774                     put(1, new int[]{12, 1234});
775                 }});
776         mBatteryStatsImpl.setCpuScalingPolicies(scalingPolicies);
777 
778         // Derived from freqs above, 2 clusters with {3, 2} freqs in each of them.
779         final int[] clusterFreqs = {3, 2};
780 
781         final long[][] uidTimesMs = {
782                 {4, 10, 5, 9, 4},
783                 {5, 1, 12, 2, 10},
784                 {8, 25, 3, 0, 42}
785         };
786         doAnswer(invocation -> {
787             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
788                     invocation.getArgument(1);
789             for (int i = 0; i < testUids.length; ++i) {
790                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
791             }
792             return null;
793         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
794                 any(KernelCpuUidFreqTimeReader.Callback.class));
795         when(mCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
796 
797         // RUN
798         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false, null);
799 
800         // VERIFY
801         final long[][] expectedWakeLockUidTimesUs = new long[2][];
802         for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
803             expectedWakeLockUidTimesUs[cluster] = new long[clusterFreqs[cluster]];
804         }
805         for (int i = 0; i < testUids.length; ++i) {
806             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
807             assertNotNull("No entry for uid=" + testUids[i], u);
808 
809             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
810                     uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
811             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
812                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
813 
814             int idx = 0;
815             for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
816                 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
817                     final long expectedTimeUs =
818                             (uidTimesMs[i][idx] * 1000 * WAKE_LOCK_WEIGHT) / 100;
819                     expectedWakeLockUidTimesUs[cluster][speed] += expectedTimeUs;
820                     assertEquals("Unexpected time for uid= " + testUids[i]
821                                     + " at cluster=" + cluster + ", speed=" + speed,
822                             expectedTimeUs,
823                             u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
824                     idx++;
825                 }
826             }
827         }
828         for (int i = 0; i < partialTimerUids.length; ++i) {
829             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(partialTimerUids[i]);
830             assertNotNull("No entry for partial timer uid=" + partialTimerUids[i], u);
831 
832             assertNull("Unexpected cpu times for partial timer uid=" + partialTimerUids[i],
833                     u.getCpuFreqTimes(STATS_SINCE_CHARGED));
834             assertNull("Unexpected screen-off cpu times for partial timer uid="
835                             + partialTimerUids[i],
836                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
837 
838             for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
839                 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
840                     final long expectedTimeUs = expectedWakeLockUidTimesUs[cluster][speed]
841                             / (partialTimerUids.length - i);
842                     assertEquals("Unexpected time for partial timer uid= " + partialTimerUids[i]
843                                     + " at cluster=" + cluster + ", speed=" + speed,
844                             expectedTimeUs,
845                             u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
846                     expectedWakeLockUidTimesUs[cluster][speed] -= expectedTimeUs;
847                 }
848             }
849         }
850         for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
851             for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
852                 assertEquals("There shouldn't be any left-overs: "
853                                 + Arrays.deepToString(expectedWakeLockUidTimesUs),
854                         0, expectedWakeLockUidTimesUs[cluster][speed]);
855             }
856         }
857     }
858 
859     @Test
testReadKernelUidCpuFreqTimesLocked_freqsChanged()860     public void testReadKernelUidCpuFreqTimesLocked_freqsChanged() {
861         // PRECONDITIONS
862         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
863 
864         final int testUserId = 11;
865         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
866         final int[] testUids = getUids(testUserId, new int[]{
867                 FIRST_APPLICATION_UID + 22,
868                 FIRST_APPLICATION_UID + 27,
869                 FIRST_APPLICATION_UID + 33
870         });
871         final long[][] uidTimesMs = {
872                 {4, 10, 5, 9, 4},
873                 {5, 1, 12, 2, 10},
874                 {8, 25, 3, 0, 42}
875         };
876         doAnswer(invocation -> {
877             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
878                     invocation.getArgument(1);
879             for (int i = 0; i < testUids.length; ++i) {
880                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
881             }
882             return null;
883         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
884                 any(KernelCpuUidFreqTimeReader.Callback.class));
885 
886         // RUN
887         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null);
888 
889         // VERIFY
890         for (int i = 0; i < testUids.length; ++i) {
891             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
892             assertNotNull("No entry for uid=" + testUids[i], u);
893 
894             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
895                     uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
896             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
897                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
898         }
899 
900         // Repeat the test with the freqs from proc file changed.
901 
902         // PRECONDITIONS
903         updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
904         final long[][] deltasMs = {
905                 {3, 12, 55, 100, 32, 34984, 27983},
906                 {3248327490475L, 232349349845043L, 123, 2398, 0, 398, 0},
907                 {43, 3345, 2143, 123, 4554, 9374983794839L, 979875}
908         };
909         doAnswer(invocation -> {
910             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
911                     invocation.getArgument(1);
912             for (int i = 0; i < testUids.length; ++i) {
913                 callback.onUidCpuTime(testUids[i], deltasMs[i]);
914             }
915             return null;
916         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
917                 any(KernelCpuUidFreqTimeReader.Callback.class));
918 
919         // RUN
920         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true, null);
921 
922         // VERIFY
923         for (int i = 0; i < testUids.length; ++i) {
924             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
925             assertNotNull("No entry for uid=" + testUids[i], u);
926 
927             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
928                     deltasMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
929             assertArrayEquals("Unexpected screen-off cpu times for uid=" + testUids[i],
930                     deltasMs[i], u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
931         }
932     }
933 
934     @Test
testReadKernelUidCpuFreqTimesLocked_isolatedUid()935     public void testReadKernelUidCpuFreqTimesLocked_isolatedUid() {
936         // PRECONDITIONS
937         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
938 
939         final int testUserId = 11;
940         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
941         final int isolatedAppId = FIRST_ISOLATED_UID + 27;
942         final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
943         final int[] testUids = getUids(testUserId, new int[]{
944                 FIRST_APPLICATION_UID + 22,
945                 isolatedAppId,
946                 FIRST_APPLICATION_UID + 33
947         });
948         final long[][] uidTimesMs = {
949                 {4, 10, 5, 9, 4},
950                 {5, 1, 12, 2, 10},
951                 {8, 25, 3, 0, 42}
952         };
953         doAnswer(invocation -> {
954             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
955                     invocation.getArgument(1);
956             for (int i = 0; i < testUids.length; ++i) {
957                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
958             }
959             return null;
960         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
961                 any(KernelCpuUidFreqTimeReader.Callback.class));
962 
963         // RUN
964         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null);
965 
966         // VERIFY
967         for (int i = 0; i < testUids.length; ++i) {
968             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
969             if (UserHandle.isIsolated(testUids[i])) {
970                 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
971                 continue;
972             }
973             assertNotNull("No entry for uid=" + testUids[i], u);
974 
975             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
976                     uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
977             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
978                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
979         }
980 
981 
982         // Add an isolated uid mapping and repeat the test.
983 
984         // PRECONDITIONS
985         final int ownerUid = UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 42);
986         mPowerStatsUidResolver.noteIsolatedUidAdded(isolatedUid, ownerUid);
987         final long[][] deltasMs = {
988                 {3, 12, 55, 100, 32},
989                 {32483274, 232349349, 123, 2398, 0},
990                 {43, 3345, 2143, 123, 4554}
991         };
992         doAnswer(invocation -> {
993             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
994                     invocation.getArgument(1);
995             for (int i = 0; i < testUids.length; ++i) {
996                 callback.onUidCpuTime(testUids[i], deltasMs[i]);
997             }
998             return null;
999         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
1000                 any(KernelCpuUidFreqTimeReader.Callback.class));
1001 
1002         // RUN
1003         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null);
1004 
1005         // VERIFY
1006         for (int i = 0; i < testUids.length; ++i) {
1007             BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1008             final long[] expectedTimes;
1009             if (UserHandle.isIsolated(testUids[i])) {
1010                 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
1011                 // Since we added a mapping, an entry should've been created for owner uid.
1012                 u = mBatteryStatsImpl.getUidStats().get(ownerUid);
1013                 expectedTimes = deltasMs[i];
1014                 assertNotNull("No entry for owner uid=" + ownerUid, u);
1015             } else {
1016                 assertNotNull("No entry for uid=" + testUids[i], u);
1017                 expectedTimes = sum(uidTimesMs[i], deltasMs[i]);
1018             }
1019 
1020             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
1021                     expectedTimes, u.getCpuFreqTimes(STATS_SINCE_CHARGED));
1022             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
1023                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
1024         }
1025     }
1026 
1027     @Test
testReadKernelUidCpuFreqTimesLocked_invalidUid()1028     public void testReadKernelUidCpuFreqTimesLocked_invalidUid() {
1029         // PRECONDITIONS
1030         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
1031 
1032         final int testUserId = 11;
1033         final int invalidUserId = 15;
1034         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
1035         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
1036         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
1037         final int[] testUids = getUids(testUserId, new int[]{
1038                 FIRST_APPLICATION_UID + 22,
1039                 FIRST_APPLICATION_UID + 27,
1040                 FIRST_APPLICATION_UID + 33
1041         });
1042         final long[][] uidTimesMs = {
1043                 {4, 10, 5, 9, 4},
1044                 {5, 1, 12, 2, 10},
1045                 {8, 25, 3, 0, 42}
1046         };
1047         doAnswer(invocation -> {
1048             final KernelCpuUidFreqTimeReader.Callback<long[]> callback =
1049                     invocation.getArgument(1);
1050             for (int i = 0; i < testUids.length; ++i) {
1051                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
1052             }
1053             // And one for the invalid uid
1054             callback.onUidCpuTime(invalidUid, new long[]{12, 839, 32, 34, 21});
1055             return null;
1056         }).when(mCpuUidFreqTimeReader).readDelta(anyBoolean(),
1057                 any(KernelCpuUidFreqTimeReader.Callback.class));
1058 
1059         // RUN
1060         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false, null);
1061 
1062         // VERIFY
1063         for (int i = 0; i < testUids.length; ++i) {
1064             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1065             assertNotNull("No entry for uid=" + testUids[i], u);
1066 
1067             assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
1068                     uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
1069             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
1070                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
1071         }
1072         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
1073                 mBatteryStatsImpl.getUidStats().get(invalidUid));
1074     }
1075 
1076     @Test
testReadKernelUidCpuActiveTimesLocked()1077     public void testReadKernelUidCpuActiveTimesLocked() {
1078         mClocks.realtime = 1000;
1079 
1080         // PRECONDITIONS
1081         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
1082 
1083         final int testUserId = 11;
1084         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
1085         final int[] testUids = getUids(testUserId, new int[]{
1086                 FIRST_APPLICATION_UID + 22,
1087                 FIRST_APPLICATION_UID + 27,
1088                 FIRST_APPLICATION_UID + 33
1089         });
1090         final long[] initialTimesMs = {8000, 25000, 3000, 0, 42000};
1091         doAnswer(invocation -> {
1092             final KernelCpuUidActiveTimeReader.Callback<Long> callback =
1093                     invocation.getArgument(0);
1094             for (int i = 0; i < testUids.length; ++i) {
1095                 callback.onUidCpuTime(testUids[i], initialTimesMs[i]);
1096             }
1097             return null;
1098         }).when(mCpuUidActiveTimeReader).readAbsolute(
1099                 any(KernelCpuUidActiveTimeReader.Callback.class));
1100 
1101         // RUN
1102         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
1103 
1104         // VERIFY
1105         for (int i = 0; i < testUids.length; ++i) {
1106             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1107             assertNotNull("No entry for uid=" + testUids[i], u);
1108             assertEquals("Unexpected cpu active time for uid=" + testUids[i], 0,
1109                     u.getCpuActiveTime());
1110         }
1111 
1112         // Some time passes
1113         mClocks.realtime = 2000;
1114 
1115         // PRECONDITIONS
1116         final long[] cpuTimesAt2000 = {43000, 3345000, 2143000, 123000, 4554000};
1117         doAnswer(invocation -> {
1118             final KernelCpuUidActiveTimeReader.Callback<Long> callback =
1119                     invocation.getArgument(0);
1120             for (int i = 0; i < testUids.length; ++i) {
1121                 callback.onUidCpuTime(testUids[i], cpuTimesAt2000[i]);
1122             }
1123             return null;
1124         }).when(mCpuUidActiveTimeReader).readAbsolute(
1125                 any(KernelCpuUidActiveTimeReader.Callback.class));
1126 
1127         // RUN
1128         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
1129 
1130         // VERIFY
1131         for (int i = 0; i < testUids.length; ++i) {
1132             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1133             assertNotNull("No entry for uid=" + testUids[i], u);
1134             assertEquals("Unexpected cpu active time for uid=" + testUids[i],
1135                     cpuTimesAt2000[i] - initialTimesMs[i], u.getCpuActiveTime());
1136         }
1137 
1138         // Give it another second
1139         mClocks.realtime = 3000;
1140 
1141         // Repeat the test when the screen is off.
1142 
1143         // PRECONDITIONS
1144         updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1145         final long[] cpuTimesAt3000 = {63000, 7345000, 8143000, 923000, 5554000};
1146         doAnswer(invocation -> {
1147             final KernelCpuUidActiveTimeReader.Callback<Long> callback =
1148                     invocation.getArgument(0);
1149             for (int i = 0; i < testUids.length; ++i) {
1150                 callback.onUidCpuTime(testUids[i], cpuTimesAt3000[i]);
1151             }
1152             return null;
1153         }).when(mCpuUidActiveTimeReader).readAbsolute(
1154                 any(KernelCpuUidActiveTimeReader.Callback.class));
1155 
1156         // RUN
1157         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
1158 
1159         // VERIFY
1160         for (int i = 0; i < testUids.length; ++i) {
1161             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1162             assertNotNull("No entry for uid=" + testUids[i], u);
1163             assertEquals("Unexpected cpu active time for uid=" + testUids[i],
1164                     cpuTimesAt3000[i] - initialTimesMs[i], u.getCpuActiveTime());
1165         }
1166     }
1167 
1168     @Test
testReadKernelUidCpuActiveTimesLocked_invalidUid()1169     public void testReadKernelUidCpuActiveTimesLocked_invalidUid() {
1170         mClocks.realtime = 1000;
1171 
1172         // PRECONDITIONS
1173         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
1174 
1175         final int testUserId = 11;
1176         final int invalidUserId = 15;
1177         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
1178         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
1179         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
1180         final int[] testUids = getUids(testUserId, new int[]{
1181                 FIRST_APPLICATION_UID + 22,
1182                 FIRST_APPLICATION_UID + 27,
1183                 FIRST_APPLICATION_UID + 33
1184         });
1185         final long[] cpuTimesAt1000 = {8000, 25000, 3000, 0, 42000};
1186         doAnswer(invocation -> {
1187             final KernelCpuUidActiveTimeReader.Callback<Long> callback =
1188                     invocation.getArgument(0);
1189             for (int i = 0; i < testUids.length; ++i) {
1190                 callback.onUidCpuTime(testUids[i], cpuTimesAt1000[i]);
1191             }
1192             // And one for the invalid uid
1193             callback.onUidCpuTime(invalidUid, 1200L);
1194             return null;
1195         }).when(mCpuUidActiveTimeReader).readAbsolute(
1196                 any(KernelCpuUidActiveTimeReader.Callback.class));
1197 
1198         // RUN
1199         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
1200 
1201         // Some time passes
1202         mClocks.realtime = 2000;
1203 
1204         // Run again to compute the delta
1205         final long[] cpuTimesAt2000 = {18000, 225000, 33000, 40, 542000};
1206         doAnswer(invocation -> {
1207             final KernelCpuUidActiveTimeReader.Callback<Long> callback =
1208                     invocation.getArgument(0);
1209             for (int i = 0; i < testUids.length; ++i) {
1210                 callback.onUidCpuTime(testUids[i], cpuTimesAt2000[i]);
1211             }
1212             // And one for the invalid uid
1213             callback.onUidCpuTime(invalidUid, 1200L);
1214             return null;
1215         }).when(mCpuUidActiveTimeReader).readAbsolute(
1216                 any(KernelCpuUidActiveTimeReader.Callback.class));
1217 
1218         // RUN
1219         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
1220 
1221         // VERIFY
1222         for (int i = 0; i < testUids.length; ++i) {
1223             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1224             assertNotNull("No entry for uid=" + testUids[i], u);
1225             assertEquals("Unexpected cpu active time for uid=" + testUids[i],
1226                     cpuTimesAt2000[i] - cpuTimesAt1000[i], u.getCpuActiveTime());
1227         }
1228         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
1229                 mBatteryStatsImpl.getUidStats().get(invalidUid));
1230     }
1231 
1232     @Test
testReadKernelUidCpuClusterTimesLocked()1233     public void testReadKernelUidCpuClusterTimesLocked() {
1234         // PRECONDITIONS
1235         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
1236 
1237         final int testUserId = 11;
1238         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
1239         final int[] testUids = getUids(testUserId, new int[]{
1240                 FIRST_APPLICATION_UID + 22,
1241                 FIRST_APPLICATION_UID + 27,
1242                 FIRST_APPLICATION_UID + 33
1243         });
1244         final long[][] uidTimesMs = {
1245                 {4000, 10000},
1246                 {5000, 1000},
1247                 {8000, 0}
1248         };
1249         doAnswer(invocation -> {
1250             final KernelCpuUidClusterTimeReader.Callback<long[]> callback =
1251                     invocation.getArgument(1);
1252             for (int i = 0; i < testUids.length; ++i) {
1253                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
1254             }
1255             return null;
1256         }).when(mCpuUidClusterTimeReader).readDelta(anyBoolean(),
1257                 any(KernelCpuUidClusterTimeReader.Callback.class));
1258 
1259         // RUN
1260         mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true, null);
1261 
1262         // VERIFY
1263         for (int i = 0; i < testUids.length; ++i) {
1264             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1265             assertNotNull("No entry for uid=" + testUids[i], u);
1266             assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], uidTimesMs[i],
1267                     u.getCpuClusterTimes());
1268         }
1269 
1270         // Repeat the test when the screen is off.
1271 
1272         // PRECONDITIONS
1273         updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
1274         final long[][] deltasMs = {
1275                 {3000, 12000},
1276                 {3248327490475L, 0},
1277                 {43000, 3345000}
1278         };
1279         doAnswer(invocation -> {
1280             final KernelCpuUidClusterTimeReader.Callback<long[]> callback =
1281                     invocation.getArgument(1);
1282             for (int i = 0; i < testUids.length; ++i) {
1283                 callback.onUidCpuTime(testUids[i], deltasMs[i]);
1284             }
1285             return null;
1286         }).when(mCpuUidClusterTimeReader).readDelta(anyBoolean(),
1287                 any(KernelCpuUidClusterTimeReader.Callback.class));
1288 
1289         // RUN
1290         mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true, null);
1291 
1292         // VERIFY
1293         for (int i = 0; i < testUids.length; ++i) {
1294             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1295             assertNotNull("No entry for uid=" + testUids[i], u);
1296             assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i],
1297                     sum(uidTimesMs[i], deltasMs[i]),
1298                     u.getCpuClusterTimes());
1299         }
1300     }
1301 
1302     @Test
testReadKernelUidCpuClusterTimesLocked_invalidUid()1303     public void testReadKernelUidCpuClusterTimesLocked_invalidUid() {
1304         // PRECONDITIONS
1305         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
1306 
1307         final int testUserId = 11;
1308         final int invalidUserId = 15;
1309         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
1310         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
1311         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
1312         final int[] testUids = getUids(testUserId, new int[]{
1313                 FIRST_APPLICATION_UID + 22,
1314                 FIRST_APPLICATION_UID + 27,
1315                 FIRST_APPLICATION_UID + 33
1316         });
1317         final long[][] uidTimesMs = {
1318                 {4000, 10000},
1319                 {5000, 1000},
1320                 {8000, 0}
1321         };
1322         doAnswer(invocation -> {
1323             final KernelCpuUidClusterTimeReader.Callback<long[]> callback =
1324                     invocation.getArgument(1);
1325             for (int i = 0; i < testUids.length; ++i) {
1326                 callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
1327             }
1328             // And one for the invalid uid
1329             callback.onUidCpuTime(invalidUid, new long[]{400, 1000});
1330             return null;
1331         }).when(mCpuUidClusterTimeReader).readDelta(anyBoolean(),
1332                 any(KernelCpuUidClusterTimeReader.Callback.class));
1333 
1334         // RUN
1335         mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true, null);
1336 
1337         // VERIFY
1338         for (int i = 0; i < testUids.length; ++i) {
1339             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
1340             assertNotNull("No entry for uid=" + testUids[i], u);
1341             assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], uidTimesMs[i],
1342                     u.getCpuClusterTimes());
1343         }
1344         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
1345                 mBatteryStatsImpl.getUidStats().get(invalidUid));
1346     }
1347 
1348     @Test
testRemoveUidCpuTimes()1349     public void testRemoveUidCpuTimes() {
1350         mClocks.realtime = mClocks.uptime = 0;
1351         mBatteryStatsImpl.getPendingRemovedUids().add(
1352                 mBatteryStatsImpl.new UidToRemove(1, mClocks.elapsedRealtime()));
1353         mBatteryStatsImpl.getPendingRemovedUids().add(
1354                 mBatteryStatsImpl.new UidToRemove(5, 10, mClocks.elapsedRealtime()));
1355         mBatteryStatsImpl.clearPendingRemovedUidsLocked();
1356         assertEquals(2, mBatteryStatsImpl.getPendingRemovedUids().size());
1357 
1358         mClocks.realtime = mClocks.uptime = 100_000;
1359         mBatteryStatsImpl.clearPendingRemovedUidsLocked();
1360         assertEquals(2, mBatteryStatsImpl.getPendingRemovedUids().size());
1361 
1362         mClocks.realtime = mClocks.uptime = 200_000;
1363         mBatteryStatsImpl.getPendingRemovedUids().add(
1364                 mBatteryStatsImpl.new UidToRemove(100, mClocks.elapsedRealtime()));
1365         mBatteryStatsImpl.clearPendingRemovedUidsLocked();
1366         assertEquals(3, mBatteryStatsImpl.getPendingRemovedUids().size());
1367 
1368         mClocks.realtime = mClocks.uptime = 400_000;
1369         mBatteryStatsImpl.clearPendingRemovedUidsLocked();
1370         assertEquals(1, mBatteryStatsImpl.getPendingRemovedUids().size());
1371         verify(mCpuUidActiveTimeReader).removeUid(1);
1372         verify(mCpuUidActiveTimeReader).removeUidsInRange(5, 10);
1373         verify(mCpuUidClusterTimeReader).removeUid(1);
1374         verify(mCpuUidClusterTimeReader).removeUidsInRange(5, 10);
1375         verify(mCpuUidFreqTimeReader).removeUid(1);
1376         verify(mCpuUidFreqTimeReader).removeUidsInRange(5, 10);
1377         verify(mCpuUidUserSysTimeReader).removeUid(1);
1378         verify(mCpuUidUserSysTimeReader).removeUidsInRange(5, 10);
1379 
1380         mClocks.realtime = mClocks.uptime = 800_000;
1381         mBatteryStatsImpl.clearPendingRemovedUidsLocked();
1382         assertEquals(0, mBatteryStatsImpl.getPendingRemovedUids().size());
1383         verify(mCpuUidActiveTimeReader).removeUid(100);
1384         verify(mCpuUidClusterTimeReader).removeUid(100);
1385         verify(mCpuUidFreqTimeReader).removeUid(100);
1386         verify(mCpuUidUserSysTimeReader).removeUid(100);
1387 
1388         verifyNoMoreInteractions(mCpuUidActiveTimeReader, mCpuUidClusterTimeReader,
1389                 mCpuUidFreqTimeReader, mCpuUidUserSysTimeReader);
1390     }
1391 
updateTimeBasesLocked(boolean unplugged, int screenState, long upTime, long realTime)1392     private void updateTimeBasesLocked(boolean unplugged, int screenState,
1393             long upTime, long realTime) {
1394         mBatteryStatsImpl.updateTimeBasesLocked(unplugged, screenState, upTime, realTime);
1395     }
1396 
initKernelCpuSpeedReaders(int count)1397     private void initKernelCpuSpeedReaders(int count) {
1398         mKernelCpuSpeedReaders = new KernelCpuSpeedReader[count];
1399         for (int i = 0; i < count; ++i) {
1400             mKernelCpuSpeedReaders[i] = Mockito.mock(KernelCpuSpeedReader.class);
1401         }
1402         mBatteryStatsImpl.setKernelCpuSpeedReaders(mKernelCpuSpeedReaders);
1403     }
1404 
getPartialTimers(int... uids)1405     private ArrayList<BatteryStatsImpl.StopwatchTimer> getPartialTimers(int... uids) {
1406         final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers = new ArrayList<>();
1407         final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
1408         for (int uid : uids) {
1409             final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(uid);
1410             final BatteryStatsImpl.StopwatchTimer timer = new BatteryStatsImpl.StopwatchTimer(
1411                     mClocks, u, WAKE_TYPE_PARTIAL, null, timeBase);
1412             partialTimers.add(timer);
1413         }
1414         return partialTimers;
1415     }
1416 
sum(long[] a, long[] b)1417     private long[] sum(long[] a, long[] b) {
1418         assertEquals("Arrays a: " + Arrays.toString(a) + ", b: " + Arrays.toString(b),
1419                 a.length, b.length);
1420         final long[] result = new long[a.length];
1421         for (int i = 0; i < a.length; ++i) {
1422             result[i] = a[i] + b[i];
1423         }
1424         return result;
1425     }
1426 
getUids(int userId, int[] appIds)1427     private int[] getUids(int userId, int[] appIds) {
1428         final int[] uids = new int[appIds.length];
1429         for (int i = appIds.length - 1; i >= 0; --i) {
1430             uids[i] = UserHandle.getUid(userId, appIds[i]);
1431         }
1432         return uids;
1433     }
1434 }
1435