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