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