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