blob: 97b54b13e1538a1fe89079b2d2965b8fa48a48c4 [file] [log] [blame]
Sudheer Shanka38383232017-07-25 09:55:03 -07001/*
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 */
16package com.android.internal.os;
17
18import static android.os.BatteryStats.STATS_SINCE_CHARGED;
19import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
20import static android.os.Process.FIRST_APPLICATION_UID;
21import static android.os.Process.FIRST_ISOLATED_UID;
22
23import static com.android.internal.os.BatteryStatsImpl.WAKE_LOCK_WEIGHT;
24
25import static org.junit.Assert.assertArrayEquals;
26import static org.junit.Assert.assertEquals;
27import static org.junit.Assert.assertNotNull;
28import static org.junit.Assert.assertNull;
29import static org.junit.Assert.assertTrue;
30import static org.mockito.ArgumentMatchers.any;
31import static org.mockito.Mockito.doAnswer;
Sudheer Shankab8ad5942017-08-08 12:16:09 -070032import static org.mockito.Mockito.times;
Sudheer Shanka38383232017-07-25 09:55:03 -070033import static org.mockito.Mockito.verify;
Sudheer Shankab8ad5942017-08-08 12:16:09 -070034import static org.mockito.Mockito.verifyNoMoreInteractions;
Sudheer Shanka38383232017-07-25 09:55:03 -070035import static org.mockito.Mockito.when;
36
37import android.os.BatteryStats;
Sudheer Shanka38383232017-07-25 09:55:03 -070038import android.os.UserHandle;
39import android.support.test.filters.SmallTest;
40import android.support.test.runner.AndroidJUnit4;
41import android.util.SparseLongArray;
42
43import com.android.internal.util.ArrayUtils;
44
45import org.junit.Before;
46import org.junit.Test;
47import org.junit.runner.RunWith;
48import org.mockito.Mock;
49import org.mockito.Mockito;
50import org.mockito.MockitoAnnotations;
51
52import java.util.ArrayList;
53import java.util.Arrays;
54
55/**
56 * To run the tests, use
57 *
58 * runtest -c com.android.internal.os.BatteryStatsCpuTimesTest frameworks-core
59 *
60 * or
61 *
62 * Build: m FrameworksCoreTests
63 * Install: adb install -r \
64 * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
65 * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsCpuTimesTest -w \
66 * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
67 *
68 * or
69 *
70 * bit FrameworksCoreTests:com.android.internal.os.BatteryStatsCpuTimesTest
71 */
72@SmallTest
73@RunWith(AndroidJUnit4.class)
74public class BatteryStatsCpuTimesTest {
75 @Mock KernelUidCpuTimeReader mKernelUidCpuTimeReader;
76 @Mock KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
77 @Mock BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
78 @Mock PowerProfile mPowerProfile;
79
80 private MockClocks mClocks;
81 private MockBatteryStatsImpl mBatteryStatsImpl;
82 private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
83
84 @Before
85 public void setUp() {
86 MockitoAnnotations.initMocks(this);
87
88 mClocks = new MockClocks();
89 mBatteryStatsImpl = new MockBatteryStatsImpl(mClocks)
90 .setKernelUidCpuTimeReader(mKernelUidCpuTimeReader)
91 .setKernelUidCpuFreqTimeReader(mKernelUidCpuFreqTimeReader)
92 .setUserInfoProvider(mUserInfoProvider);
93 }
94
95 @Test
96 public void testUpdateCpuTimeLocked() {
97 // PRECONDITIONS
98 mBatteryStatsImpl.setPowerProfile(mPowerProfile);
99 mBatteryStatsImpl.setOnBatteryInternal(false);
100 final int numClusters = 3;
101 initKernelCpuSpeedReaders(numClusters);
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700102 final long[] freqs = {1, 12, 123, 12, 1234};
103 when(mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs);
Sudheer Shanka38383232017-07-25 09:55:03 -0700104
105 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700106 mBatteryStatsImpl.updateCpuTimeLocked();
Sudheer Shanka38383232017-07-25 09:55:03 -0700107
108 // VERIFY
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700109 assertArrayEquals("Unexpected cpu freqs", freqs, mBatteryStatsImpl.getCpuFreqs());
Sudheer Shanka38383232017-07-25 09:55:03 -0700110 verify(mKernelUidCpuTimeReader).readDelta(null);
111 verify(mKernelUidCpuFreqTimeReader).readDelta(null);
112 for (int i = 0; i < numClusters; ++i) {
113 verify(mKernelCpuSpeedReaders[i]).readDelta();
114 }
115
116 // Prepare for next test
117 Mockito.reset(mUserInfoProvider, mKernelUidCpuFreqTimeReader, mKernelUidCpuTimeReader);
118 for (int i = 0; i < numClusters; ++i) {
119 Mockito.reset(mKernelCpuSpeedReaders[i]);
120 }
121
122 // PRECONDITIONS
123 mBatteryStatsImpl.setOnBatteryInternal(true);
124
125 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700126 mBatteryStatsImpl.updateCpuTimeLocked();
Sudheer Shanka38383232017-07-25 09:55:03 -0700127
128 // VERIFY
129 verify(mUserInfoProvider).refreshUserIds();
130 verify(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700131 // perClusterTimesAvailable is called twice, once in updateCpuTimeLocked() and the other
132 // in readKernelUidCpuFreqTimesLocked.
133 verify(mKernelUidCpuFreqTimeReader, times(2)).perClusterTimesAvailable();
Sudheer Shanka38383232017-07-25 09:55:03 -0700134 verify(mKernelUidCpuFreqTimeReader).readDelta(
135 any(KernelUidCpuFreqTimeReader.Callback.class));
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700136 verifyNoMoreInteractions(mKernelUidCpuFreqTimeReader);
Sudheer Shanka38383232017-07-25 09:55:03 -0700137 for (int i = 0; i < numClusters; ++i) {
138 verify(mKernelCpuSpeedReaders[i]).readDelta();
139 }
140 }
141
142 @Test
143 public void testMarkPartialTimersAsEligible() {
144 // PRECONDITIONS
145 final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers = getPartialTimers(
146 10032, 10042, 10052);
147 final ArrayList<BatteryStatsImpl.StopwatchTimer> lastPartialTimers
148 = new ArrayList<>(partialTimers);
149 mBatteryStatsImpl.setPartialTimers(partialTimers);
150 mBatteryStatsImpl.setLastPartialTimers(lastPartialTimers);
151 final boolean[] inList = {false, true, false};
152 for (int i = 0; i < partialTimers.size(); ++i) {
153 partialTimers.get(i).mInList = inList[i];
154 }
155
156 // RUN
157 mBatteryStatsImpl.markPartialTimersAsEligible();
158
159 // VERIFY
160 assertTrue(ArrayUtils.referenceEquals(partialTimers, lastPartialTimers));
161 for (int i = 0; i < partialTimers.size(); ++i) {
162 assertTrue("Timer id=" + i, partialTimers.get(i).mInList);
163 }
164
165 // PRECONDITIONS
166 partialTimers.addAll(getPartialTimers(10077, 10099));
167 partialTimers.remove(1 /* index */);
168
169 // RUN
170 mBatteryStatsImpl.markPartialTimersAsEligible();
171
172 // VERIFY
173 assertTrue(ArrayUtils.referenceEquals(partialTimers, lastPartialTimers));
174 for (int i = 0; i < partialTimers.size(); ++i) {
175 assertTrue("Timer id=" + i, partialTimers.get(i).mInList);
176 }
177 }
178
179 @Test
180 public void testUpdateClusterSpeedTimes() {
181 // PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700182 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700183 final long[][] clusterSpeedTimesMs = {{20, 30}, {40, 50, 60}};
184 initKernelCpuSpeedReaders(clusterSpeedTimesMs.length);
185 for (int i = 0; i < clusterSpeedTimesMs.length; ++i) {
186 when(mKernelCpuSpeedReaders[i].readDelta()).thenReturn(clusterSpeedTimesMs[i]);
187 }
188 when(mPowerProfile.getNumCpuClusters()).thenReturn(clusterSpeedTimesMs.length);
189 for (int i = 0; i < clusterSpeedTimesMs.length; ++i) {
190 when(mPowerProfile.getNumSpeedStepsInCpuCluster(i))
191 .thenReturn(clusterSpeedTimesMs[i].length);
192 }
193 final SparseLongArray updatedUids = new SparseLongArray();
194 final int[] testUids = {10012, 10014, 10016};
195 final int[] cpuTimeUs = {89, 31, 43};
196 for (int i = 0; i < testUids.length; ++i) {
197 updatedUids.put(testUids[i], cpuTimeUs[i]);
198 }
199
200 // RUN
201 mBatteryStatsImpl.updateClusterSpeedTimes(updatedUids);
202
203 // VERIFY
204 int totalClustersTimeMs = 0;
205 for (int i = 0; i < clusterSpeedTimesMs.length; ++i) {
206 for (int j = 0; j < clusterSpeedTimesMs[i].length; ++j) {
207 totalClustersTimeMs += clusterSpeedTimesMs[i][j];
208 }
209 }
210 for (int i = 0; i < testUids.length; ++i) {
211 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
212 assertNotNull("No entry for uid=" + testUids[i], u);
213 for (int cluster = 0; cluster < clusterSpeedTimesMs.length; ++cluster) {
214 for (int speed = 0; speed < clusterSpeedTimesMs[cluster].length; ++speed) {
215 assertEquals("Uid=" + testUids[i] + ", cluster=" + cluster + ", speed=" + speed,
216 cpuTimeUs[i] * clusterSpeedTimesMs[cluster][speed]
217 / totalClustersTimeMs,
218 u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
219 }
220 }
221 }
222 }
223
224 @Test
225 public void testReadKernelUidCpuTimesLocked() {
226 //PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700227 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700228 final int testUserId = 11;
229 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
230 final int[] testUids = getUids(testUserId, new int[] {
231 FIRST_APPLICATION_UID + 22,
232 FIRST_APPLICATION_UID + 27,
233 FIRST_APPLICATION_UID + 33
234 });
235 final long[][] uidTimesUs = {
236 {12, 34}, {34897394, 3123983}, {79775429834l, 8430434903489l}
237 };
238 doAnswer(invocation -> {
239 final KernelUidCpuTimeReader.Callback callback =
240 (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
241 for (int i = 0; i < testUids.length; ++i) {
242 callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
243 }
244 return null;
245 }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
246
247 // RUN
248 final SparseLongArray updatedUids = new SparseLongArray();
249 mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, updatedUids);
250
251 // VERIFY
252 for (int i = 0; i < testUids.length; ++i) {
253 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
254 assertNotNull("No entry for uid=" + testUids[i], u);
255 assertEquals("Unexpected user cpu time for uid=" + testUids[i],
256 uidTimesUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
257 assertEquals("Unexpected system cpu time for uid=" + testUids[i],
258 uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
259
260 assertEquals("Unexpected entry in updated uids for uid=" + testUids[i],
261 uidTimesUs[i][0] + uidTimesUs[i][1], updatedUids.get(testUids[i]));
262 updatedUids.delete(testUids[i]);
263 }
264 assertEquals("Updated uids: " + updatedUids, 0, updatedUids.size());
265
266 // Repeat the test with a null updatedUids
267
268 // PRECONDITIONS
269 final long[][] deltasUs = {
270 {9379, 3332409833484l}, {493247, 723234}, {3247819, 123348}
271 };
272 doAnswer(invocation -> {
273 final KernelUidCpuTimeReader.Callback callback =
274 (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
275 for (int i = 0; i < testUids.length; ++i) {
276 callback.onUidCpuTime(testUids[i], deltasUs[i][0], deltasUs[i][1]);
277 }
278 return null;
279 }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
280
281 // RUN
282 mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
283
284 // VERIFY
285 for (int i = 0; i < testUids.length; ++i) {
286 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
287 assertNotNull("No entry for uid=" + testUids[i], u);
288 assertEquals("Unexpected user cpu time for uid=" + testUids[i],
289 uidTimesUs[i][0] + deltasUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
290 assertEquals("Unexpected system cpu time for uid=" + testUids[i],
291 uidTimesUs[i][1] + deltasUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
292 }
293 }
294
295 @Test
296 public void testReadKernelUidCpuTimesLocked_isolatedUid() {
297 //PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700298 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700299 final int testUserId = 11;
300 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
301 final int isolatedAppId = FIRST_ISOLATED_UID + 27;
302 final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
303 final int[] testUids = getUids(testUserId, new int[] {
304 FIRST_APPLICATION_UID + 22,
305 isolatedAppId,
306 FIRST_APPLICATION_UID + 33
307 });
308 final long[][] uidTimesUs = {
309 {12, 34}, {34897394, 3123983}, {79775429834l, 8430434903489l}
310 };
311 doAnswer(invocation -> {
312 final KernelUidCpuTimeReader.Callback callback =
313 (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
314 for (int i = 0; i < testUids.length; ++i) {
315 callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
316 }
317 return null;
318 }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
319
320 // RUN
321 mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
322
323 // VERIFY
324 for (int i = 0; i < testUids.length; ++i) {
325 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
326 if (UserHandle.isIsolated(testUids[i])) {
327 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
328 continue;
329 }
330 assertNotNull("No entry for uid=" + testUids[i], u);
331 assertEquals("Unexpected user cpu time for uid=" + testUids[i],
332 uidTimesUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
333 assertEquals("Unexpected system cpu time for uid=" + testUids[i],
334 uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
335 }
336 verify(mKernelUidCpuTimeReader).removeUid(isolatedUid);
337
338 // Add an isolated uid mapping and repeat the test.
339
340 // PRECONDITIONS
341 final int ownerUid = UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 42);
342 mBatteryStatsImpl.addIsolatedUidLocked(isolatedUid, ownerUid);
343 final long[][] deltasUs = {
344 {9379, 3332409833484l}, {493247, 723234}, {3247819, 123348}
345 };
346 doAnswer(invocation -> {
347 final KernelUidCpuTimeReader.Callback callback =
348 (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
349 for (int i = 0; i < testUids.length; ++i) {
350 callback.onUidCpuTime(testUids[i], deltasUs[i][0], deltasUs[i][1]);
351 }
352 return null;
353 }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
354
355 // RUN
356 mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
357
358 // VERIFY
359 for (int i = 0; i < testUids.length; ++i) {
360 BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
361 final long expectedUserTimeUs;
362 final long expectedSystemTimeUs;
363 if (UserHandle.isIsolated(testUids[i])) {
364 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
365 // Since we added a mapping, an entry should've been created for owner uid.
366 u = mBatteryStatsImpl.getUidStats().get(ownerUid);
367 expectedUserTimeUs = deltasUs[i][0];
368 expectedSystemTimeUs = deltasUs[i][1];
369 assertNotNull("No entry for owner uid=" + ownerUid, u);
370 } else {
371 assertNotNull("No entry for uid=" + testUids[i], u);
372 expectedUserTimeUs = uidTimesUs[i][0] + deltasUs[i][0];
373 expectedSystemTimeUs = uidTimesUs[i][1] + deltasUs[i][1];
374 }
375 assertEquals("Unexpected user cpu time for uid=" + testUids[i],
376 expectedUserTimeUs, u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
377 assertEquals("Unexpected system cpu time for uid=" + testUids[i],
378 expectedSystemTimeUs, u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
379 }
380 }
381
382 @Test
383 public void testReadKernelUidCpuTimesLocked_invalidUid() {
384 //PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700385 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700386 final int testUserId = 11;
387 final int invalidUserId = 15;
388 final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
389 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
390 when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
391 final int[] testUids = getUids(testUserId, new int[] {
392 FIRST_APPLICATION_UID + 22,
393 FIRST_APPLICATION_UID + 27,
394 FIRST_APPLICATION_UID + 33
395 });
396 final long[][] uidTimesUs = {
397 {12, 34}, {34897394, 3123983}, {79775429834l, 8430434903489l}
398 };
399 doAnswer(invocation -> {
400 final KernelUidCpuTimeReader.Callback callback =
401 (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
402 for (int i = 0; i < testUids.length; ++i) {
403 callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
404 }
405 // And one for the invalid uid
406 callback.onUidCpuTime(invalidUid, 3879, 239);
407 return null;
408 }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
409
410 // RUN
411 mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null);
412
413 // VERIFY
414 for (int i = 0; i < testUids.length; ++i) {
415 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
416 assertNotNull("No entry for uid=" + testUids[i], u);
417 assertEquals("Unexpected user cpu time for uid=" + testUids[i],
418 uidTimesUs[i][0], u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
419 assertEquals("Unexpected system cpu time for uid=" + testUids[i],
420 uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
421 }
422 assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
423 mBatteryStatsImpl.getUidStats().get(invalidUid));
424 verify(mKernelUidCpuTimeReader).removeUid(invalidUid);
425 }
426
427 @Test
428 public void testReadKernelUidCpuTimesLocked_withPartialTimers() {
429 //PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700430 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700431 final int testUserId = 11;
432 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
433 final int[] testUids = getUids(testUserId, new int[] {
434 FIRST_APPLICATION_UID + 22,
435 FIRST_APPLICATION_UID + 27,
436 FIRST_APPLICATION_UID + 33
437 });
438 final int[] partialTimerUids = {
439 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 48),
440 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 10)
441 };
442 final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers
443 = getPartialTimers(partialTimerUids);
444 final long[][] uidTimesUs = {
445 {12, 34}, {3394, 3123}, {7977, 80434}
446 };
447 doAnswer(invocation -> {
448 final KernelUidCpuTimeReader.Callback callback =
449 (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
450 for (int i = 0; i < testUids.length; ++i) {
451 callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
452 }
453 return null;
454 }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
455
456 // RUN
457 final SparseLongArray updatedUids = new SparseLongArray();
458 mBatteryStatsImpl.readKernelUidCpuTimesLocked(partialTimers, updatedUids);
459
460 // VERIFY
461 long totalUserTimeUs = 0;
462 long totalSystemTimeUs = 0;
463 for (int i = 0; i < testUids.length; ++i) {
464 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
465 assertNotNull("No entry for uid=" + testUids[i], u);
466 final long expectedUserTimeUs = uidTimesUs[i][0] * WAKE_LOCK_WEIGHT / 100;
467 final long expectedSystemTimeUs = uidTimesUs[i][1] * WAKE_LOCK_WEIGHT / 100;
468 assertEquals("Unexpected user cpu time for uid=" + testUids[i],
469 expectedUserTimeUs, u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
470 assertEquals("Unexpected system cpu time for uid=" + testUids[i],
471 expectedSystemTimeUs, u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
472 assertEquals("Unexpected entry in updated uids for uid=" + testUids[i],
473 expectedUserTimeUs + expectedSystemTimeUs, updatedUids.get(testUids[i]));
474 updatedUids.delete(testUids[i]);
475 totalUserTimeUs += uidTimesUs[i][0];
476 totalSystemTimeUs += uidTimesUs[i][1];
477 }
478
479 totalUserTimeUs = totalUserTimeUs * (100 - WAKE_LOCK_WEIGHT) / 100;
480 totalSystemTimeUs = totalSystemTimeUs * (100 - WAKE_LOCK_WEIGHT) / 100;
481 for (int i = 0; i < partialTimerUids.length; ++i) {
482 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(partialTimerUids[i]);
483 assertNotNull("No entry for partial timer uid=" + partialTimerUids[i], u);
484 final long expectedUserTimeUs = totalUserTimeUs / (partialTimerUids.length - i);
485 final long expectedSystemTimeUs = totalSystemTimeUs / (partialTimerUids.length - i);
486 assertEquals("Unexpected user cpu time for partial timer uid=" + partialTimerUids[i],
487 expectedUserTimeUs, u.getUserCpuTimeUs(STATS_SINCE_CHARGED));
488 assertEquals("Unexpected system cpu time for partial timer uid=" + partialTimerUids[i],
489 expectedSystemTimeUs, u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
490 assertEquals("Unexpected entry in updated uids for partial timer uid="
491 + partialTimerUids[i],
492 expectedUserTimeUs + expectedSystemTimeUs,
493 updatedUids.get(partialTimerUids[i]));
494 updatedUids.delete(partialTimerUids[i]);
495 totalUserTimeUs -= expectedUserTimeUs;
496 totalSystemTimeUs -= expectedSystemTimeUs;
497
498 final BatteryStats.Uid.Proc proc = u.getProcessStats().get("*wakelock*");
499 assertEquals("Unexpected user cpu time for *wakelock* in uid=" + partialTimerUids[i],
500 expectedUserTimeUs / 1000, proc.getUserTime(STATS_SINCE_CHARGED));
501 assertEquals("Unexpected system cpu time for *wakelock* in uid=" + partialTimerUids[i],
502 expectedSystemTimeUs / 1000, proc.getSystemTime(STATS_SINCE_CHARGED));
503 }
504 assertEquals(0, totalUserTimeUs);
505 assertEquals(0, totalSystemTimeUs);
506 assertEquals("Updated uids: " + updatedUids, 0, updatedUids.size());
507 }
508
509 @Test
510 public void testReadKernelUidCpuFreqTimesLocked() {
511 // PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700512 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700513
514 final int testUserId = 11;
515 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
516 final int[] testUids = getUids(testUserId, new int[] {
517 FIRST_APPLICATION_UID + 22,
518 FIRST_APPLICATION_UID + 27,
519 FIRST_APPLICATION_UID + 33
520 });
Sudheer Shanka38383232017-07-25 09:55:03 -0700521 final long[][] uidTimesMs = {
522 {4, 10, 5, 9, 4},
523 {5, 1, 12, 2, 10},
524 {8, 25, 3, 0, 42}
525 };
526 doAnswer(invocation -> {
527 final KernelUidCpuFreqTimeReader.Callback callback =
528 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
Sudheer Shanka38383232017-07-25 09:55:03 -0700529 for (int i = 0; i < testUids.length; ++i) {
530 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
531 }
532 return null;
533 }).when(mKernelUidCpuFreqTimeReader).readDelta(
534 any(KernelUidCpuFreqTimeReader.Callback.class));
535
536 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700537 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
Sudheer Shanka38383232017-07-25 09:55:03 -0700538
539 // VERIFY
Sudheer Shanka38383232017-07-25 09:55:03 -0700540 for (int i = 0; i < testUids.length; ++i) {
541 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
542 assertNotNull("No entry for uid=" + testUids[i], u);
543
544 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
545 uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
546 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
547 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
548 }
549
550 // Repeat the test when the screen is off.
551
552 // PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700553 updateTimeBasesLocked(true, true, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700554 final long[][] deltasMs = {
555 {3, 12, 55, 100, 32},
556 {3248327490475l, 232349349845043l, 123, 2398, 0},
557 {43, 3345, 2143, 123, 4554}
558 };
559 doAnswer(invocation -> {
560 final KernelUidCpuFreqTimeReader.Callback callback =
561 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
Sudheer Shanka38383232017-07-25 09:55:03 -0700562 for (int i = 0; i < testUids.length; ++i) {
563 callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
564 }
565 return null;
566 }).when(mKernelUidCpuFreqTimeReader).readDelta(
567 any(KernelUidCpuFreqTimeReader.Callback.class));
568
569 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700570 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
Sudheer Shanka38383232017-07-25 09:55:03 -0700571
572 // VERIFY
Sudheer Shanka38383232017-07-25 09:55:03 -0700573 for (int i = 0; i < testUids.length; ++i) {
574 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
575 assertNotNull("No entry for uid=" + testUids[i], u);
576
577 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
578 sum(uidTimesMs[i], deltasMs[i]), u.getCpuFreqTimes(STATS_SINCE_CHARGED));
579 assertArrayEquals("Unexpected screen-off cpu times for uid=" + testUids[i],
580 deltasMs[i], u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
581 }
582 }
583
584 @Test
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700585 public void testReadKernelUidCpuFreqTimesLocked_perClusterTimesAvailable() {
586 // PRECONDITIONS
587 updateTimeBasesLocked(true, false, 0, 0);
588
589 final int testUserId = 11;
590 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
591 final int[] testUids = getUids(testUserId, new int[] {
592 FIRST_APPLICATION_UID + 22,
593 FIRST_APPLICATION_UID + 27,
594 FIRST_APPLICATION_UID + 33
595 });
596 final long[] freqs = {1, 12, 123, 12, 1234};
597 // Derived from freqs above, 2 clusters with {3, 2} freqs in each of them.
598 final int[] clusterFreqs = {3, 2};
599 when(mPowerProfile.getNumCpuClusters()).thenReturn(clusterFreqs.length);
600 for (int i = 0; i < clusterFreqs.length; ++i) {
601 when(mPowerProfile.getNumSpeedStepsInCpuCluster(i))
602 .thenReturn(clusterFreqs[i]);
603 }
604 final long[][] uidTimesMs = {
605 {4, 10, 5, 9, 4},
606 {5, 1, 12, 2, 10},
607 {8, 25, 3, 0, 42}
608 };
609 doAnswer(invocation -> {
610 final KernelUidCpuFreqTimeReader.Callback callback =
611 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
612 for (int i = 0; i < testUids.length; ++i) {
613 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
614 }
615 return null;
616 }).when(mKernelUidCpuFreqTimeReader).readDelta(
617 any(KernelUidCpuFreqTimeReader.Callback.class));
618 when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
619
620 // RUN
621 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
622
623 // VERIFY
624 for (int i = 0; i < testUids.length; ++i) {
625 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
626 assertNotNull("No entry for uid=" + testUids[i], u);
627
628 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
629 uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
630 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
631 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
632
633 int idx = 0;
634 for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
635 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
636 assertEquals("Unexpected time at cluster=" + cluster + ", speed=" + speed,
637 uidTimesMs[i][idx] * 1000,
638 u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
639 idx++;
640 }
641 }
642 }
643
644 // Repeat the test when the screen is off.
645
646 // PRECONDITIONS
647 updateTimeBasesLocked(true, true, 0, 0);
648 final long[][] deltasMs = {
649 {3, 12, 55, 100, 32},
650 {3248327490475l, 232349349845043l, 123, 2398, 0},
651 {43, 3345, 2143, 123, 4554}
652 };
653 doAnswer(invocation -> {
654 final KernelUidCpuFreqTimeReader.Callback callback =
655 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
656 for (int i = 0; i < testUids.length; ++i) {
657 callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
658 }
659 return null;
660 }).when(mKernelUidCpuFreqTimeReader).readDelta(
661 any(KernelUidCpuFreqTimeReader.Callback.class));
662
663 // RUN
664 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
665
666 // VERIFY
667 for (int i = 0; i < testUids.length; ++i) {
668 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
669 assertNotNull("No entry for uid=" + testUids[i], u);
670
671 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
672 sum(uidTimesMs[i], deltasMs[i]), u.getCpuFreqTimes(STATS_SINCE_CHARGED));
673 assertArrayEquals("Unexpected screen-off cpu times for uid=" + testUids[i],
674 deltasMs[i], u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
675
676 int idx = 0;
677 for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
678 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
679 assertEquals("Unexpected time at cluster=" + cluster + ", speed=" + speed,
680 (uidTimesMs[i][idx] + deltasMs[i][idx]) * 1000,
681 u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
682 idx++;
683 }
684 }
685 }
686 }
687
688 @Test
689 public void testReadKernelUidCpuFreqTimesLocked_partialTimers() {
690 // PRECONDITIONS
691 updateTimeBasesLocked(true, false, 0, 0);
692
693 final int testUserId = 11;
694 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
695 final int[] testUids = getUids(testUserId, new int[] {
696 FIRST_APPLICATION_UID + 22,
697 FIRST_APPLICATION_UID + 27,
698 FIRST_APPLICATION_UID + 33
699 });
700 final int[] partialTimerUids = {
701 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 48),
702 UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 10)
703 };
704 final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers
705 = getPartialTimers(partialTimerUids);
706 final long[] freqs = {1, 12, 123, 12, 1234};
707 // Derived from freqs above, 2 clusters with {3, 2} freqs in each of them.
708 final int[] clusterFreqs = {3, 2};
709 when(mPowerProfile.getNumCpuClusters()).thenReturn(clusterFreqs.length);
710 for (int i = 0; i < clusterFreqs.length; ++i) {
711 when(mPowerProfile.getNumSpeedStepsInCpuCluster(i))
712 .thenReturn(clusterFreqs[i]);
713 }
714 final long[][] uidTimesMs = {
715 {4, 10, 5, 9, 4},
716 {5, 1, 12, 2, 10},
717 {8, 25, 3, 0, 42}
718 };
719 doAnswer(invocation -> {
720 final KernelUidCpuFreqTimeReader.Callback callback =
721 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
722 for (int i = 0; i < testUids.length; ++i) {
723 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
724 }
725 return null;
726 }).when(mKernelUidCpuFreqTimeReader).readDelta(
727 any(KernelUidCpuFreqTimeReader.Callback.class));
728 when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
729
730 // RUN
731 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers);
732
733 // VERIFY
734 final long[][] expectedWakeLockUidTimesUs = new long[clusterFreqs.length][];
735 for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
736 expectedWakeLockUidTimesUs[cluster] = new long[clusterFreqs[cluster]];
737 }
738 for (int i = 0; i < testUids.length; ++i) {
739 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
740 assertNotNull("No entry for uid=" + testUids[i], u);
741
742 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
743 uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
744 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
745 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
746
747 int idx = 0;
748 for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
749 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
750 final long expectedTimeUs =
751 (uidTimesMs[i][idx] * 1000 * WAKE_LOCK_WEIGHT) / 100;
752 expectedWakeLockUidTimesUs[cluster][speed] += expectedTimeUs;
753 assertEquals("Unexpected time for uid= " + testUids[i]
754 + " at cluster=" + cluster + ", speed=" + speed,
755 expectedTimeUs,
756 u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
757 idx++;
758 }
759 }
760 }
761 for (int i = 0; i < partialTimerUids.length; ++i) {
762 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(partialTimerUids[i]);
763 assertNotNull("No entry for partial timer uid=" + partialTimerUids[i], u);
764
765 assertNull("Unexpected cpu times for partial timer uid=" + partialTimerUids[i],
766 u.getCpuFreqTimes(STATS_SINCE_CHARGED));
767 assertNull("Unexpected screen-off cpu times for partial timer uid="
768 + partialTimerUids[i],
769 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
770
771 for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
772 for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
773 final long expectedTimeUs = expectedWakeLockUidTimesUs[cluster][speed]
774 / (partialTimerUids.length - i);
775 assertEquals("Unexpected time for partial timer uid= " + partialTimerUids[i]
776 + " at cluster=" + cluster + ", speed=" + speed,
777 expectedTimeUs,
778 u.getTimeAtCpuSpeed(cluster, speed, STATS_SINCE_CHARGED));
779 expectedWakeLockUidTimesUs[cluster][speed] -= expectedTimeUs;
780 }
781 }
782 }
783 for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
784 for (int speed = 0 ; speed < clusterFreqs[cluster]; ++speed) {
785 assertEquals("There shouldn't be any left-overs: "
786 + Arrays.deepToString(expectedWakeLockUidTimesUs),
787 0, expectedWakeLockUidTimesUs[cluster][speed]);
788 }
789 }
790 }
791
792 @Test
793 public void testReadKernelUidCpuFreqTimesLocked_freqsChanged() {
794 // PRECONDITIONS
795 updateTimeBasesLocked(true, false, 0, 0);
796
797 final int testUserId = 11;
798 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
799 final int[] testUids = getUids(testUserId, new int[] {
800 FIRST_APPLICATION_UID + 22,
801 FIRST_APPLICATION_UID + 27,
802 FIRST_APPLICATION_UID + 33
803 });
804 final long[][] uidTimesMs = {
805 {4, 10, 5, 9, 4},
806 {5, 1, 12, 2, 10},
807 {8, 25, 3, 0, 42}
808 };
809 doAnswer(invocation -> {
810 final KernelUidCpuFreqTimeReader.Callback callback =
811 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
812 for (int i = 0; i < testUids.length; ++i) {
813 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
814 }
815 return null;
816 }).when(mKernelUidCpuFreqTimeReader).readDelta(
817 any(KernelUidCpuFreqTimeReader.Callback.class));
818
819 // RUN
820 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
821
822 // VERIFY
823 for (int i = 0; i < testUids.length; ++i) {
824 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
825 assertNotNull("No entry for uid=" + testUids[i], u);
826
827 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
828 uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
829 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
830 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
831 }
832
833 // Repeat the test with the freqs from proc file changed.
834
835 // PRECONDITIONS
836 updateTimeBasesLocked(true, true, 0, 0);
837 final long[][] deltasMs = {
838 {3, 12, 55, 100, 32, 34984, 27983},
839 {3248327490475l, 232349349845043l, 123, 2398, 0, 398, 0},
840 {43, 3345, 2143, 123, 4554, 9374983794839l, 979875}
841 };
842 doAnswer(invocation -> {
843 final KernelUidCpuFreqTimeReader.Callback callback =
844 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
845 for (int i = 0; i < testUids.length; ++i) {
846 callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
847 }
848 return null;
849 }).when(mKernelUidCpuFreqTimeReader).readDelta(
850 any(KernelUidCpuFreqTimeReader.Callback.class));
851
852 // RUN
853 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
854
855 // VERIFY
856 for (int i = 0; i < testUids.length; ++i) {
857 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
858 assertNotNull("No entry for uid=" + testUids[i], u);
859
860 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
861 deltasMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
862 assertArrayEquals("Unexpected screen-off cpu times for uid=" + testUids[i],
863 deltasMs[i], u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
864 }
865 }
866
867 @Test
Sudheer Shanka38383232017-07-25 09:55:03 -0700868 public void testReadKernelUidCpuFreqTimesLocked_isolatedUid() {
869 // PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700870 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700871
872 final int testUserId = 11;
873 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
874 final int isolatedAppId = FIRST_ISOLATED_UID + 27;
875 final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
876 final int[] testUids = getUids(testUserId, new int[] {
877 FIRST_APPLICATION_UID + 22,
878 isolatedAppId,
879 FIRST_APPLICATION_UID + 33
880 });
Sudheer Shanka38383232017-07-25 09:55:03 -0700881 final long[][] uidTimesMs = {
882 {4, 10, 5, 9, 4},
883 {5, 1, 12, 2, 10},
884 {8, 25, 3, 0, 42}
885 };
886 doAnswer(invocation -> {
887 final KernelUidCpuFreqTimeReader.Callback callback =
888 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
Sudheer Shanka38383232017-07-25 09:55:03 -0700889 for (int i = 0; i < testUids.length; ++i) {
890 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
891 }
892 return null;
893 }).when(mKernelUidCpuFreqTimeReader).readDelta(
894 any(KernelUidCpuFreqTimeReader.Callback.class));
895
896 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700897 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
Sudheer Shanka38383232017-07-25 09:55:03 -0700898
899 // VERIFY
Sudheer Shanka38383232017-07-25 09:55:03 -0700900 for (int i = 0; i < testUids.length; ++i) {
901 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
902 if (UserHandle.isIsolated(testUids[i])) {
903 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
904 continue;
905 }
906 assertNotNull("No entry for uid=" + testUids[i], u);
907
908 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
909 uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
910 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
911 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
912 }
913 verify(mKernelUidCpuFreqTimeReader).removeUid(isolatedUid);
914
915
916 // Add an isolated uid mapping and repeat the test.
917
918 // PRECONDITIONS
919 final int ownerUid = UserHandle.getUid(testUserId, FIRST_APPLICATION_UID + 42);
920 mBatteryStatsImpl.addIsolatedUidLocked(isolatedUid, ownerUid);
921 final long[][] deltasMs = {
922 {3, 12, 55, 100, 32},
923 {32483274, 232349349, 123, 2398, 0},
924 {43, 3345, 2143, 123, 4554}
925 };
926 doAnswer(invocation -> {
927 final KernelUidCpuFreqTimeReader.Callback callback =
928 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
Sudheer Shanka38383232017-07-25 09:55:03 -0700929 for (int i = 0; i < testUids.length; ++i) {
930 callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
931 }
932 return null;
933 }).when(mKernelUidCpuFreqTimeReader).readDelta(
934 any(KernelUidCpuFreqTimeReader.Callback.class));
935
936 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700937 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
Sudheer Shanka38383232017-07-25 09:55:03 -0700938
939 // VERIFY
Sudheer Shanka38383232017-07-25 09:55:03 -0700940 for (int i = 0; i < testUids.length; ++i) {
941 BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
942 final long[] expectedTimes;
943 if (UserHandle.isIsolated(testUids[i])) {
944 assertNull("There shouldn't be an entry for isolated uid=" + testUids[i], u);
945 // Since we added a mapping, an entry should've been created for owner uid.
946 u = mBatteryStatsImpl.getUidStats().get(ownerUid);
947 expectedTimes = deltasMs[i];
948 assertNotNull("No entry for owner uid=" + ownerUid, u);
949 } else {
950 assertNotNull("No entry for uid=" + testUids[i], u);
951 expectedTimes = sum(uidTimesMs[i], deltasMs[i]);
952 }
953
954 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
955 expectedTimes, u.getCpuFreqTimes(STATS_SINCE_CHARGED));
956 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
957 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
958 }
959 }
960
961 @Test
962 public void testReadKernelUiidCpuFreqTimesLocked_invalidUid() {
963 // PRECONDITIONS
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700964 updateTimeBasesLocked(true, false, 0, 0);
Sudheer Shanka38383232017-07-25 09:55:03 -0700965
966 final int testUserId = 11;
967 final int invalidUserId = 15;
968 final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
969 when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
970 when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
971 final int[] testUids = getUids(testUserId, new int[] {
972 FIRST_APPLICATION_UID + 22,
973 FIRST_APPLICATION_UID + 27,
974 FIRST_APPLICATION_UID + 33
975 });
Sudheer Shanka38383232017-07-25 09:55:03 -0700976 final long[][] uidTimesMs = {
977 {4, 10, 5, 9, 4},
978 {5, 1, 12, 2, 10},
979 {8, 25, 3, 0, 42}
980 };
981 doAnswer(invocation -> {
982 final KernelUidCpuFreqTimeReader.Callback callback =
983 (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
Sudheer Shanka38383232017-07-25 09:55:03 -0700984 for (int i = 0; i < testUids.length; ++i) {
985 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
986 }
987 // And one for the invalid uid
988 callback.onUidCpuFreqTime(invalidUid, new long[] {12, 839, 32, 34, 21});
989 return null;
990 }).when(mKernelUidCpuFreqTimeReader).readDelta(
991 any(KernelUidCpuFreqTimeReader.Callback.class));
992
993 // RUN
Sudheer Shankab8ad5942017-08-08 12:16:09 -0700994 mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null);
Sudheer Shanka38383232017-07-25 09:55:03 -0700995
996 // VERIFY
Sudheer Shanka38383232017-07-25 09:55:03 -0700997 for (int i = 0; i < testUids.length; ++i) {
998 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
999 assertNotNull("No entry for uid=" + testUids[i], u);
1000
1001 assertArrayEquals("Unexpected cpu times for uid=" + testUids[i],
1002 uidTimesMs[i], u.getCpuFreqTimes(STATS_SINCE_CHARGED));
1003 assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
1004 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
1005 }
1006 assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
1007 mBatteryStatsImpl.getUidStats().get(invalidUid));
1008 verify(mKernelUidCpuFreqTimeReader).removeUid(invalidUid);
1009 }
1010
Sudheer Shankab8ad5942017-08-08 12:16:09 -07001011 private void updateTimeBasesLocked(boolean unplugged, boolean screenOff,
1012 long upTime, long realTime) {
1013 // Set PowerProfile=null before calling updateTimeBasesLocked to avoid execution of
1014 // BatteryStatsImpl.updateCpuTimeLocked
1015 mBatteryStatsImpl.setPowerProfile(null);
1016 mBatteryStatsImpl.updateTimeBasesLocked(unplugged, screenOff, upTime, realTime);
1017 mBatteryStatsImpl.setPowerProfile(mPowerProfile);
1018 }
1019
Sudheer Shanka38383232017-07-25 09:55:03 -07001020 private void initKernelCpuSpeedReaders(int count) {
1021 mKernelCpuSpeedReaders = new KernelCpuSpeedReader[count];
1022 for (int i = 0; i < count; ++i) {
1023 mKernelCpuSpeedReaders[i] = Mockito.mock(KernelCpuSpeedReader.class);
1024 }
1025 mBatteryStatsImpl.setKernelCpuSpeedReaders(mKernelCpuSpeedReaders);
1026 }
1027
1028 private ArrayList<BatteryStatsImpl.StopwatchTimer> getPartialTimers(int... uids) {
1029 final ArrayList<BatteryStatsImpl.StopwatchTimer> partialTimers = new ArrayList<>();
1030 final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
1031 for (int uid : uids) {
1032 final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(uid);
1033 final BatteryStatsImpl.StopwatchTimer timer = new BatteryStatsImpl.StopwatchTimer(
1034 mClocks, u, WAKE_TYPE_PARTIAL, null, timeBase);
1035 partialTimers.add(timer);
1036 }
1037 return partialTimers;
1038 }
1039
1040 private long[] sum(long[] a, long[] b) {
1041 assertEquals("Arrays a: " + Arrays.toString(a) + ", b: " + Arrays.toString(b),
1042 a.length, b.length);
1043 final long[] result = new long[a.length];
1044 for (int i = 0; i < a.length; ++i) {
1045 result[i] = a[i] + b[i];
1046 }
1047 return result;
1048 }
1049
1050 private int[] getUids(int userId, int[] appIds) {
1051 final int[] uids = new int[appIds.length];
1052 for (int i = appIds.length - 1; i >= 0; --i) {
1053 uids[i] = UserHandle.getUid(userId, appIds[i]);
1054 }
1055 return uids;
1056 }
1057}