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.Uid.NUM_PROCESS_STATE; 21 import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND; 22 import static android.os.BatteryStats.Uid.PROCESS_STATE_CACHED; 23 import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE; 24 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP; 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.mockito.ArgumentMatchers.argThat; 31 import static org.mockito.ArgumentMatchers.eq; 32 import static org.mockito.Mockito.when; 33 34 import android.os.BatteryStats; 35 import android.util.SparseArray; 36 import android.util.SparseIntArray; 37 import android.view.Display; 38 39 import androidx.test.filters.LargeTest; 40 import androidx.test.runner.AndroidJUnit4; 41 42 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader; 43 import com.android.internal.util.ArrayUtils; 44 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 import org.mockito.ArgumentMatcher; 49 import org.mockito.Mock; 50 import org.mockito.MockitoAnnotations; 51 52 import java.util.Arrays; 53 54 @LargeTest 55 @RunWith(AndroidJUnit4.class) 56 public class BatteryStatsImplTest { 57 @Mock 58 private KernelCpuUidFreqTimeReader mKernelUidCpuFreqTimeReader; 59 @Mock 60 private KernelSingleUidTimeReader mKernelSingleUidTimeReader; 61 62 private MockBatteryStatsImpl mBatteryStatsImpl; 63 64 @Before setUp()65 public void setUp() { 66 MockitoAnnotations.initMocks(this); 67 68 when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true); 69 when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true); 70 mBatteryStatsImpl = new MockBatteryStatsImpl() 71 .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader) 72 .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader); 73 } 74 75 @Test testUpdateProcStateCpuTimes()76 public void testUpdateProcStateCpuTimes() { 77 mBatteryStatsImpl.setOnBatteryInternal(true); 78 mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0); 79 80 final int[] testUids = {10032, 10048, 10145, 10139}; 81 final int[] testProcStates = { 82 PROCESS_STATE_BACKGROUND, 83 PROCESS_STATE_FOREGROUND_SERVICE, 84 PROCESS_STATE_TOP, 85 PROCESS_STATE_CACHED 86 }; 87 addPendingUids(testUids, testProcStates); 88 final long[][] cpuTimes = { 89 {349734983, 394982394832l, 909834, 348934, 9838}, 90 {7498, 1239890, 988, 13298, 98980}, 91 {989834, 384098, 98483, 23809, 4984}, 92 {4859048, 348903, 4578967, 5973894, 298549} 93 }; 94 for (int i = 0; i < testUids.length; ++i) { 95 when(mKernelSingleUidTimeReader.readDeltaMs(testUids[i])).thenReturn(cpuTimes[i]); 96 97 // Verify there are no cpu times initially. 98 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUids[i]); 99 for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) { 100 assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 101 assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 102 } 103 } 104 105 mBatteryStatsImpl.updateProcStateCpuTimes(true, false); 106 107 verifyNoPendingUids(); 108 for (int i = 0; i < testUids.length; ++i) { 109 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]); 110 for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) { 111 if (procState == testProcStates[i]) { 112 assertArrayEquals("Uid=" + testUids[i], cpuTimes[i], 113 u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 114 } else { 115 assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 116 } 117 assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 118 } 119 } 120 121 final long[][] delta1 = { 122 {9589, 148934, 309894, 3098493, 98754}, 123 {21983, 94983, 4983, 9878493, 84854}, 124 {945894, 9089432, 19478, 3834, 7845}, 125 {843895, 43948, 949582, 99, 384} 126 }; 127 for (int i = 0; i < testUids.length; ++i) { 128 when(mKernelSingleUidTimeReader.readDeltaMs(testUids[i])).thenReturn(delta1[i]); 129 } 130 addPendingUids(testUids, testProcStates); 131 132 mBatteryStatsImpl.updateProcStateCpuTimes(true, false); 133 134 verifyNoPendingUids(); 135 for (int i = 0; i < testUids.length; ++i) { 136 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]); 137 for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) { 138 if (procState == testProcStates[i]) { 139 long[] expectedCpuTimes = cpuTimes[i].clone(); 140 for (int j = 0; j < expectedCpuTimes.length; ++j) { 141 expectedCpuTimes[j] += delta1[i][j]; 142 } 143 assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, 144 u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 145 } else { 146 assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 147 } 148 assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 149 } 150 } 151 152 mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); 153 final long[][] delta2 = { 154 {95932, 2943, 49834, 89034, 139}, 155 {349, 89605, 5896, 845, 98444}, 156 {678, 7498, 9843, 889, 4894}, 157 {488, 998, 8498, 394, 574} 158 }; 159 for (int i = 0; i < testUids.length; ++i) { 160 when(mKernelSingleUidTimeReader.readDeltaMs(testUids[i])).thenReturn(delta2[i]); 161 } 162 addPendingUids(testUids, testProcStates); 163 164 mBatteryStatsImpl.updateProcStateCpuTimes(true, true); 165 166 verifyNoPendingUids(); 167 for (int i = 0; i < testUids.length; ++i) { 168 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]); 169 for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) { 170 if (procState == testProcStates[i]) { 171 long[] expectedCpuTimes = cpuTimes[i].clone(); 172 for (int j = 0; j < expectedCpuTimes.length; ++j) { 173 expectedCpuTimes[j] += delta1[i][j] + delta2[i][j]; 174 } 175 assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, 176 u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 177 assertArrayEquals("Uid=" + testUids[i], delta2[i], 178 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 179 } else { 180 assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 181 assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 182 } 183 } 184 } 185 186 final long[][] delta3 = { 187 {98545, 95768795, 76586, 548945, 57846}, 188 {788876, 586, 578459, 8776984, 9578923}, 189 {3049509483598l, 4597834, 377654, 94589035, 7854}, 190 {9493, 784, 99895, 8974893, 9879843} 191 }; 192 for (int i = 0; i < testUids.length; ++i) { 193 when(mKernelSingleUidTimeReader.readDeltaMs(testUids[i])).thenReturn( 194 delta3[i].clone()); 195 } 196 addPendingUids(testUids, testProcStates); 197 final int parentUid = testUids[1]; 198 final int childUid = 99099; 199 addIsolatedUid(parentUid, childUid); 200 final long[] isolatedUidCpuTimes = {495784, 398473, 4895, 4905, 30984093}; 201 when(mKernelSingleUidTimeReader.readDeltaMs(childUid)).thenReturn(isolatedUidCpuTimes); 202 203 mBatteryStatsImpl.updateProcStateCpuTimes(true, true); 204 205 verifyNoPendingUids(); 206 for (int i = 0; i < testUids.length; ++i) { 207 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]); 208 for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) { 209 if (procState == testProcStates[i]) { 210 long[] expectedCpuTimes = cpuTimes[i].clone(); 211 for (int j = 0; j < expectedCpuTimes.length; ++j) { 212 expectedCpuTimes[j] += delta1[i][j] + delta2[i][j] + delta3[i][j] 213 + (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0); 214 } 215 assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, 216 u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 217 long[] expectedScreenOffTimes = delta2[i].clone(); 218 for (int j = 0; j < expectedScreenOffTimes.length; ++j) { 219 expectedScreenOffTimes[j] += delta3[i][j] 220 + (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0); 221 } 222 assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes, 223 u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 224 } else { 225 assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 226 assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 227 } 228 } 229 } 230 } 231 232 @Test testCopyFromAllUidsCpuTimes()233 public void testCopyFromAllUidsCpuTimes() { 234 mBatteryStatsImpl.setOnBatteryInternal(false); 235 mBatteryStatsImpl.updateTimeBasesLocked(false, Display.STATE_ON, 0, 0); 236 237 final int[] testUids = {10032, 10048, 10145, 10139}; 238 final int[] testProcStates = { 239 PROCESS_STATE_BACKGROUND, 240 PROCESS_STATE_FOREGROUND_SERVICE, 241 PROCESS_STATE_TOP, 242 PROCESS_STATE_CACHED 243 }; 244 final int[] pendingUidIdx = {1, 2}; 245 updateProcessStates(testUids, testProcStates, pendingUidIdx); 246 247 final SparseArray<long[]> allUidCpuTimes = new SparseArray<>(); 248 long[][] allCpuTimes = { 249 {938483, 4985984, 439893}, 250 {499, 94904, 27694}, 251 {302949085, 39789473, 34792839}, 252 {9809485, 9083475, 347889834}, 253 }; 254 for (int i = 0; i < testUids.length; ++i) { 255 allUidCpuTimes.put(testUids[i], allCpuTimes[i]); 256 } 257 when(mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs()).thenReturn(allUidCpuTimes); 258 long[][] expectedCpuTimes = { 259 {843598745, 397843, 32749, 99854}, 260 {9834, 5885, 487589, 394}, 261 {203984, 439, 9859, 30948}, 262 {9389, 858, 239, 349} 263 }; 264 for (int i = 0; i < testUids.length; ++i) { 265 final int idx = i; 266 final ArgumentMatcher<long[]> matcher = times -> Arrays.equals(times, allCpuTimes[idx]); 267 when(mKernelSingleUidTimeReader.computeDelta(eq(testUids[i]), argThat(matcher))) 268 .thenReturn(expectedCpuTimes[i]); 269 } 270 271 mBatteryStatsImpl.copyFromAllUidsCpuTimes(true, false); 272 273 verifyNoPendingUids(); 274 for (int i = 0; i < testUids.length; ++i) { 275 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]); 276 for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) { 277 if (procState == testProcStates[i]) { 278 assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i], 279 u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 280 } else { 281 assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 282 } 283 assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState)); 284 } 285 } 286 } 287 288 @Test testAddCpuTimes()289 public void testAddCpuTimes() { 290 long[] timesA = null; 291 long[] timesB = null; 292 assertNull(mBatteryStatsImpl.addCpuTimes(timesA, timesB)); 293 294 timesA = new long[] {34, 23, 45, 24}; 295 assertArrayEquals(timesA, mBatteryStatsImpl.addCpuTimes(timesA, timesB)); 296 297 timesB = timesA; 298 timesA = null; 299 assertArrayEquals(timesB, mBatteryStatsImpl.addCpuTimes(timesA, timesB)); 300 301 final long[] expected = {434, 6784, 34987, 9984}; 302 timesA = new long[timesB.length]; 303 for (int i = 0; i < timesA.length; ++i) { 304 timesA[i] = expected[i] - timesB[i]; 305 } 306 assertArrayEquals(expected, mBatteryStatsImpl.addCpuTimes(timesA, timesB)); 307 } 308 309 @Test testMulticastWakelockAcqRel()310 public void testMulticastWakelockAcqRel() { 311 final int testUid = 10032; 312 final int acquireTimeMs = 1000; 313 final int releaseTimeMs = 1005; 314 final int currentTimeMs = 1011; 315 316 mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); 317 318 // Create a Uid Object 319 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid); 320 assertNotNull(u); 321 322 // Acquire and release the lock 323 u.noteWifiMulticastEnabledLocked(acquireTimeMs); 324 u.noteWifiMulticastDisabledLocked(releaseTimeMs); 325 326 // Get the total acquisition time 327 long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, 328 BatteryStats.STATS_SINCE_CHARGED); 329 assertEquals("Miscalculations of Multicast wakelock acquisition time", 330 (releaseTimeMs - acquireTimeMs) * 1000, totalTime); 331 } 332 333 @Test testMulticastWakelockAcqNoRel()334 public void testMulticastWakelockAcqNoRel() { 335 final int testUid = 10032; 336 final int acquireTimeMs = 1000; 337 final int currentTimeMs = 1011; 338 339 mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); 340 341 // Create a Uid Object 342 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid); 343 assertNotNull(u); 344 345 // Acquire the lock 346 u.noteWifiMulticastEnabledLocked(acquireTimeMs); 347 348 // Get the total acquisition time 349 long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, 350 BatteryStats.STATS_SINCE_CHARGED); 351 assertEquals("Miscalculations of Multicast wakelock acquisition time", 352 (currentTimeMs - acquireTimeMs) * 1000, totalTime); 353 } 354 355 @Test testMulticastWakelockAcqAcqRelRel()356 public void testMulticastWakelockAcqAcqRelRel() { 357 final int testUid = 10032; 358 final int acquireTimeMs_1 = 1000; 359 final int acquireTimeMs_2 = 1002; 360 361 final int releaseTimeMs_1 = 1005; 362 final int releaseTimeMs_2 = 1009; 363 final int currentTimeMs = 1011; 364 365 mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); 366 367 // Create a Uid Object 368 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid); 369 assertNotNull(u); 370 371 // Acquire and release the lock (twice in nested way) 372 u.noteWifiMulticastEnabledLocked(acquireTimeMs_1); 373 u.noteWifiMulticastEnabledLocked(acquireTimeMs_2); 374 375 u.noteWifiMulticastDisabledLocked(releaseTimeMs_1); 376 u.noteWifiMulticastDisabledLocked(releaseTimeMs_2); 377 378 // Get the total acquisition time 379 long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, 380 BatteryStats.STATS_SINCE_CHARGED); 381 assertEquals("Miscalculations of Multicast wakelock acquisition time", 382 (releaseTimeMs_2 - acquireTimeMs_1) * 1000, totalTime); 383 } 384 385 @Test testMulticastWakelockAcqRelAcqRel()386 public void testMulticastWakelockAcqRelAcqRel() { 387 final int testUid = 10032; 388 final int acquireTimeMs_1 = 1000; 389 final int acquireTimeMs_2 = 1005; 390 391 final int releaseTimeMs_1 = 1002; 392 final int releaseTimeMs_2 = 1009; 393 final int currentTimeMs = 1011; 394 395 mBatteryStatsImpl.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); 396 397 // Create a Uid Object 398 final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUid); 399 assertNotNull(u); 400 401 // Acquire and release the lock (twice) 402 u.noteWifiMulticastEnabledLocked(acquireTimeMs_1); 403 u.noteWifiMulticastDisabledLocked(releaseTimeMs_1); 404 405 u.noteWifiMulticastEnabledLocked(acquireTimeMs_2); 406 u.noteWifiMulticastDisabledLocked(releaseTimeMs_2); 407 408 // Get the total acquisition time 409 long totalTime = u.getWifiMulticastTime(currentTimeMs*1000, 410 BatteryStats.STATS_SINCE_CHARGED); 411 assertEquals("Miscalculations of Multicast wakelock acquisition time", 412 ((releaseTimeMs_1 - acquireTimeMs_1) + (releaseTimeMs_2 - acquireTimeMs_2)) 413 * 1000, totalTime); 414 } 415 addIsolatedUid(int parentUid, int childUid)416 private void addIsolatedUid(int parentUid, int childUid) { 417 final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(parentUid); 418 u.addIsolatedUid(childUid); 419 } 420 addPendingUids(int[] uids, int[] procStates)421 private void addPendingUids(int[] uids, int[] procStates) { 422 final SparseIntArray pendingUids = mBatteryStatsImpl.getPendingUids(); 423 for (int i = 0; i < uids.length; ++i) { 424 pendingUids.put(uids[i], procStates[i]); 425 } 426 } 427 updateProcessStates(int[] uids, int[] procStates, int[] pendingUidsIdx)428 private void updateProcessStates(int[] uids, int[] procStates, 429 int[] pendingUidsIdx) { 430 final SparseIntArray pendingUids = mBatteryStatsImpl.getPendingUids(); 431 for (int i = 0; i < uids.length; ++i) { 432 final BatteryStatsImpl.Uid u = mBatteryStatsImpl.getUidStatsLocked(uids[i]); 433 if (ArrayUtils.contains(pendingUidsIdx, i)) { 434 u.setProcessStateForTest(PROCESS_STATE_TOP); 435 pendingUids.put(uids[i], procStates[i]); 436 } else { 437 u.setProcessStateForTest(procStates[i]); 438 } 439 } 440 } 441 verifyNoPendingUids()442 private void verifyNoPendingUids() { 443 final SparseIntArray pendingUids = mBatteryStatsImpl.getPendingUids(); 444 assertEquals("There shouldn't be any pending uids left: " + pendingUids, 445 0, pendingUids.size()); 446 } 447 } 448