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