1 /* 2 * Copyright (C) 2020 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.BatteryConsumer.POWER_COMPONENT_ANY; 20 import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND; 21 import static android.os.BatteryConsumer.PROCESS_STATE_CACHED; 22 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND; 23 import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static org.junit.Assert.assertThrows; 28 import static org.junit.Assert.fail; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.when; 31 32 import static java.util.regex.Pattern.quote; 33 34 import android.os.AggregateBatteryConsumer; 35 import android.os.BatteryConsumer; 36 import android.os.BatteryUsageStats; 37 import android.os.Parcel; 38 import android.os.UidBatteryConsumer; 39 import android.os.UserBatteryConsumer; 40 import android.util.Xml; 41 42 import androidx.test.filters.SmallTest; 43 import androidx.test.runner.AndroidJUnit4; 44 45 import com.android.modules.utils.TypedXmlPullParser; 46 import com.android.modules.utils.TypedXmlSerializer; 47 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 51 import java.io.ByteArrayInputStream; 52 import java.io.ByteArrayOutputStream; 53 import java.io.PrintWriter; 54 import java.io.StringWriter; 55 import java.nio.charset.StandardCharsets; 56 import java.util.HashSet; 57 import java.util.List; 58 import java.util.Map; 59 import java.util.Set; 60 import java.util.stream.Collectors; 61 62 @SmallTest 63 @RunWith(AndroidJUnit4.class) 64 public class BatteryUsageStatsTest { 65 private static final int USER_ID = 42; 66 private static final int APP_UID1 = 271; 67 private static final int APP_UID2 = 314; 68 69 @Test testBuilder()70 public void testBuilder() throws Exception { 71 BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(true).build(); 72 assertBatteryUsageStats1(batteryUsageStats, true); 73 batteryUsageStats.close(); 74 } 75 76 @Test testBuilder_noProcessStateData()77 public void testBuilder_noProcessStateData() throws Exception { 78 BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(false).build(); 79 assertBatteryUsageStats1(batteryUsageStats, false); 80 batteryUsageStats.close(); 81 } 82 83 @Test testParcelability_smallNumberOfUids()84 public void testParcelability_smallNumberOfUids() throws Exception { 85 final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats1(true).build(); 86 final Parcel parcel = Parcel.obtain(); 87 parcel.writeParcelable(outBatteryUsageStats, 0); 88 outBatteryUsageStats.close(); 89 90 assertThat(parcel.dataSize()).isLessThan(100000); 91 92 parcel.setDataPosition(0); 93 94 final BatteryUsageStats inBatteryUsageStats = 95 parcel.readParcelable(getClass().getClassLoader()); 96 assertThat(inBatteryUsageStats).isNotNull(); 97 assertBatteryUsageStats1(inBatteryUsageStats, true); 98 inBatteryUsageStats.close(); 99 } 100 101 @Test testParcelability_largeNumberOfUids()102 public void testParcelability_largeNumberOfUids() throws Exception { 103 final BatteryUsageStats.Builder builder = 104 new BatteryUsageStats.Builder(new String[0]); 105 106 // Without the use of a CursorWindow, this BatteryUsageStats object would generate a Parcel 107 // larger than 64 Kb 108 final int uidCount = 200; 109 for (int i = 0; i < uidCount; i++) { 110 BatteryStatsImpl.Uid mockUid = mock(BatteryStatsImpl.Uid.class); 111 when(mockUid.getUid()).thenReturn(i); 112 builder.getOrCreateUidBatteryConsumerBuilder(mockUid) 113 .addConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, i * 100); 114 } 115 116 BatteryUsageStats outBatteryUsageStats = builder.build(); 117 118 final Parcel parcel = Parcel.obtain(); 119 parcel.writeParcelable(outBatteryUsageStats, 0); 120 121 // Under ravenwood this parcel is larger. On a device, 2K would suffice 122 assertThat(parcel.dataSize()).isLessThan(128_000); 123 124 parcel.setDataPosition(0); 125 126 final BatteryUsageStats inBatteryUsageStats = 127 parcel.readParcelable(getClass().getClassLoader(), BatteryUsageStats.class); 128 parcel.recycle(); 129 130 assertThat(inBatteryUsageStats.getUidBatteryConsumers()).hasSize(uidCount); 131 final Map<Integer, UidBatteryConsumer> consumersByUid = 132 inBatteryUsageStats.getUidBatteryConsumers().stream().collect( 133 Collectors.toMap(UidBatteryConsumer::getUid, c -> c)); 134 for (int i = 0; i < uidCount; i++) { 135 final UidBatteryConsumer uidBatteryConsumer = consumersByUid.get(i); 136 assertThat(uidBatteryConsumer).isNotNull(); 137 assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(i * 100); 138 } 139 inBatteryUsageStats.close(); 140 outBatteryUsageStats.close(); 141 } 142 143 @Test testDefaultSessionDuration()144 public void testDefaultSessionDuration() throws Exception { 145 final BatteryUsageStats stats = 146 buildBatteryUsageStats1(true).setStatsDuration(10000).build(); 147 assertThat(stats.getStatsDuration()).isEqualTo(10000); 148 stats.close(); 149 } 150 151 @Test testDump()152 public void testDump() throws Exception { 153 final BatteryUsageStats stats = buildBatteryUsageStats1(true).build(); 154 final StringWriter out = new StringWriter(); 155 try (PrintWriter pw = new PrintWriter(out)) { 156 stats.dump(pw, " "); 157 } 158 stats.close(); 159 160 final String dump = out.toString(); 161 162 assertThat(dump).contains("Capacity: 4000"); 163 assertThat(dump).contains("Computed drain: 30000"); 164 assertThat(dump).contains("actual drain: 1000-2000"); 165 assertThat(dump).contains("cpu: 20100 apps: 10100 duration: 20s 300ms"); 166 assertThat(dump).contains("FOO: 20200 apps: 10200 duration: 20s 400ms"); 167 assertThat(dump).containsMatch(quote("(on battery, screen on)") + "\\s*" 168 + "cpu: 2333 apps: 1333 duration: 3s 332ms"); 169 assertThat(dump).containsMatch(quote("(not on battery, screen on)") + "\\s*" 170 + "cpu: 2555 apps: 1555 duration: 5s 552ms"); 171 assertThat(dump).containsMatch(quote("(on battery, screen off/doze)") + "\\s*" 172 + "cpu: 2444 apps: 1444 duration: 4s 442ms"); 173 assertThat(dump).containsMatch(quote("(not on battery, screen off/doze)") + "\\s*" 174 + "cpu: 123 apps: 123 duration: 456ms"); 175 assertThat(dump).containsMatch( 176 quote("UID 271: 1200 " 177 + "fg: 1777 (1s 0ms) bg: 2388 (1s 500ms) fgs: 1999 (500ms) cached: 123") 178 + "\\s*" 179 + quote("screen=300 cpu=400 (600ms) cpu:fg=1777 (7s 771ms) " 180 + "cpu:bg=1888 (8s 881ms) cpu:fgs=1999 (9s 991ms) " 181 + "cpu:cached=123 (456ms) FOO=500 (800ms) FOO:bg=500 (800ms)") + "\\s*" 182 + quote("(on battery, screen on)") + "\\s*" 183 + quote("cpu=1777 (7s 771ms) cpu:fg=1777 (7s 771ms) " 184 + "FOO=500 (800ms) FOO:bg=500 (800ms)")); 185 assertThat(dump).containsMatch("User 42: 30.0\\s*" 186 + quote("cpu=10.0 (30ms) FOO=20.0 (40ms)")); 187 } 188 189 @Test testDumpNoScreenOrPowerState()190 public void testDumpNoScreenOrPowerState() throws Exception { 191 final BatteryUsageStats stats = buildBatteryUsageStats1(true, false, false).build(); 192 final StringWriter out = new StringWriter(); 193 try (PrintWriter pw = new PrintWriter(out)) { 194 stats.dump(pw, " "); 195 } 196 stats.close(); 197 198 final String dump = out.toString(); 199 200 assertThat(dump).contains("Capacity: 4000"); 201 assertThat(dump).contains("Computed drain: 30000"); 202 assertThat(dump).contains("actual drain: 1000-2000"); 203 assertThat(dump).contains("cpu: 20100 apps: 10100 duration: 20s 300ms"); 204 assertThat(dump).contains("FOO: 20200 apps: 10200 duration: 20s 400ms"); 205 assertThat(dump).containsMatch( 206 quote("UID 271: 1200 " 207 + "fg: 1777 (1s 0ms) bg: 2388 (1s 500ms) fgs: 1999 (500ms) cached: 123") 208 + "\\s*" 209 + quote("screen=300 cpu=400 (600ms) cpu:fg=1777 (7s 771ms) " 210 + "cpu:bg=1888 (8s 881ms) cpu:fgs=1999 (9s 991ms) " 211 + "cpu:cached=123 (456ms) FOO=500 (800ms) FOO:bg=500 (800ms)")); 212 assertThat(dump).containsMatch("User 42: 30.0\\s*" 213 + quote("cpu=10.0 (30ms) FOO=20.0")); 214 } 215 216 @Test testPowerComponentNames_existAndUnique()217 public void testPowerComponentNames_existAndUnique() { 218 Set<String> allNames = new HashSet<>(); 219 for (int i = 0; i < BatteryConsumer.POWER_COMPONENT_COUNT; i++) { 220 assertThat(BatteryConsumer.powerComponentIdToString(i)).isNotNull(); 221 allNames.add(BatteryConsumer.powerComponentIdToString(i)); 222 } 223 assertThat(allNames).hasSize(BatteryConsumer.POWER_COMPONENT_COUNT); 224 } 225 226 @Test testAdd()227 public void testAdd() throws Exception { 228 final BatteryUsageStats stats1 = buildBatteryUsageStats1(false).build(); 229 final BatteryUsageStats stats2 = buildBatteryUsageStats2(new String[]{"FOO"}, true).build(); 230 final BatteryUsageStats sum = 231 new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, 0) 232 .add(stats1) 233 .add(stats2) 234 .build(); 235 assertBatteryUsageStats(sum, 42345, 50, 2234, 4345, 1234, 1000, 5000, 5000); 236 237 final List<UidBatteryConsumer> uidBatteryConsumers = 238 sum.getUidBatteryConsumers(); 239 for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) { 240 if (uidBatteryConsumer.getUid() == APP_UID1) { 241 assertUidBatteryConsumer(uidBatteryConsumer, 1200 + 924, null, 242 5321, 6900, 532, 423, 400 + 345, 243 500 + 456, 1167, 1478, 244 true, 3554, 4732, 3998, 444, 3554, 15542, 3776, 17762, 3998, 19982, 245 444, 1110); 246 } else if (uidBatteryConsumer.getUid() == APP_UID2) { 247 assertUidBatteryConsumer(uidBatteryConsumer, 1332, "bar", 248 1111, 2220, 2, 333, 444, 249 555, 666, 777, 250 true, 1777, 2443, 1999, 321, 1777, 7771, 1888, 8881, 1999, 9991, 251 321, 654); 252 } else { 253 fail("Unexpected UID " + uidBatteryConsumer.getUid()); 254 } 255 } 256 257 assertAggregateBatteryConsumer(sum, 258 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 259 20223, 20434, 20645, 20856); 260 261 assertAggregateBatteryConsumer(sum, 262 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 263 40211, 40422, 40633, 40844); 264 stats1.close(); 265 stats2.close(); 266 sum.close(); 267 } 268 269 @Test testAdd_customComponentMismatch()270 public void testAdd_customComponentMismatch() throws Exception { 271 final BatteryUsageStats.Builder builder = 272 new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, 0); 273 final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"BAR"}, false).build(); 274 275 assertThrows(IllegalArgumentException.class, () -> builder.add(stats)); 276 stats.close(); 277 builder.discard(); 278 } 279 280 @Test testAdd_processStateDataMismatch()281 public void testAdd_processStateDataMismatch() throws Exception { 282 final BatteryUsageStats.Builder builder = 283 new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, 0); 284 final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"FOO"}, false).build(); 285 286 assertThrows(IllegalArgumentException.class, () -> builder.add(stats)); 287 stats.close(); 288 builder.discard(); 289 } 290 291 @Test testXml()292 public void testXml() throws Exception { 293 ByteArrayOutputStream out = new ByteArrayOutputStream(); 294 TypedXmlSerializer serializer = Xml.newBinarySerializer(); 295 serializer.setOutput(out, StandardCharsets.UTF_8.name()); 296 serializer.startDocument(null, true); 297 final BatteryUsageStats stats = buildBatteryUsageStats1(true).build(); 298 stats.writeXml(serializer); 299 serializer.endDocument(); 300 stats.close(); 301 302 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 303 TypedXmlPullParser parser = Xml.newBinaryPullParser(); 304 parser.setInput(in, StandardCharsets.UTF_8.name()); 305 final BatteryUsageStats fromXml = BatteryUsageStats.createFromXml(parser); 306 assertBatteryUsageStats1(fromXml, true); 307 fromXml.close(); 308 } 309 buildBatteryUsageStats1(boolean includeUserBatteryConsumer)310 private BatteryUsageStats.Builder buildBatteryUsageStats1(boolean includeUserBatteryConsumer) { 311 return buildBatteryUsageStats1(includeUserBatteryConsumer, true, true); 312 } 313 buildBatteryUsageStats1(boolean includeUserBatteryConsumer, boolean includeScreenState, boolean includePowerState)314 private BatteryUsageStats.Builder buildBatteryUsageStats1(boolean includeUserBatteryConsumer, 315 boolean includeScreenState, boolean includePowerState) { 316 final MockClock clocks = new MockClock(); 317 final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks); 318 319 final BatteryUsageStats.Builder builder = 320 new BatteryUsageStats.Builder(new String[]{"FOO"}, true, 321 includeScreenState, includePowerState, 0) 322 .setBatteryCapacity(4000) 323 .addDischargePercentage(20) 324 .addDischargedPowerRange(1000, 2000) 325 .addDischargeDurationMs(1234) 326 .setStatsStartTimestamp(1000) 327 .setStatsEndTimestamp(3000); 328 329 addUidBatteryConsumer(builder, batteryStats, APP_UID1, "foo", 330 1000, 1500, 500, 331 300, 400, 332 500, 600, 800, 333 1777, 7771, 1888, 8881, 1999, 9991, 123, 456); 334 335 addAggregateBatteryConsumer(builder, 336 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0, 337 10100, 10200, 10300, 10400, 338 1333, 3331, 1444, 4441, 1555, 5551, 123, 456); 339 340 addAggregateBatteryConsumer(builder, 341 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 30000, 342 20100, 20200, 20300, 20400, 343 2333, 3332, 2444, 4442, 2555, 5552, 123, 456); 344 345 if (includeUserBatteryConsumer) { 346 builder.getOrCreateUserBatteryConsumerBuilder(USER_ID) 347 .addConsumedPower( 348 BatteryConsumer.POWER_COMPONENT_CPU, 10) 349 .addConsumedPower( 350 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 20) 351 .addUsageDurationMillis( 352 BatteryConsumer.POWER_COMPONENT_CPU, 30) 353 .addUsageDurationMillis( 354 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 40); 355 } 356 return builder; 357 } 358 buildBatteryUsageStats2(String[] customPowerComponentNames, boolean includeProcessStateData)359 private BatteryUsageStats.Builder buildBatteryUsageStats2(String[] customPowerComponentNames, 360 boolean includeProcessStateData) { 361 final MockClock clocks = new MockClock(); 362 final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks); 363 364 final BatteryUsageStats.Builder builder = 365 new BatteryUsageStats.Builder(customPowerComponentNames, 366 includeProcessStateData, true, true, 0); 367 builder.addDischargePercentage(30) 368 .addDischargedPowerRange(1234, 2345) 369 .setStatsStartTimestamp(2000) 370 .setStatsEndTimestamp(5000); 371 372 addUidBatteryConsumer(builder, batteryStats, APP_UID1, null, 373 4321, 5400, 32, 374 123, 345, 375 456, 567, 678, 376 1777, 7771, 1888, 8881, 1999, 9991, 321, 654); 377 378 addUidBatteryConsumer(builder, batteryStats, APP_UID2, "bar", 379 1111, 2220, 2, 380 333, 444, 381 555, 666, 777, 382 1777, 7771, 1888, 8881, 1999, 9991, 321, 654); 383 384 addAggregateBatteryConsumer(builder, 385 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 0, 386 10123, 10234, 10345, 10456, 387 4333, 3334, 5444, 4445, 6555, 5556, 321, 654); 388 389 addAggregateBatteryConsumer(builder, 390 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 12345, 391 20111, 20222, 20333, 20444, 392 7333, 3337, 8444, 4448, 9555, 5559, 123, 456); 393 394 return builder; 395 } 396 addUidBatteryConsumer(BatteryUsageStats.Builder builder, MockBatteryStatsImpl batteryStats, int uid, String packageWithHighestDrain, int timeInProcessStateForeground, int timeInProcessStateBackground, int timeInProcessStateForegroundService, double screenPower, double cpuPower, double customComponentPower, int cpuDuration, int customComponentDuration, double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs, double cpuPowerCached, long cpuDurationCached)397 private void addUidBatteryConsumer(BatteryUsageStats.Builder builder, 398 MockBatteryStatsImpl batteryStats, int uid, String packageWithHighestDrain, 399 int timeInProcessStateForeground, int timeInProcessStateBackground, 400 int timeInProcessStateForegroundService, double screenPower, 401 double cpuPower, double customComponentPower, 402 int cpuDuration, int customComponentDuration, double cpuPowerForeground, 403 int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground, 404 double cpuPowerFgs, int cpuDurationFgs, double cpuPowerCached, long cpuDurationCached) { 405 final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(uid); 406 final UidBatteryConsumer.Builder uidBuilder = 407 builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid); 408 uidBuilder 409 .setPackageWithHighestDrain(packageWithHighestDrain) 410 .setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND, timeInProcessStateForeground) 411 .setTimeInProcessStateMs(PROCESS_STATE_BACKGROUND, timeInProcessStateBackground) 412 .setTimeInProcessStateMs(PROCESS_STATE_FOREGROUND_SERVICE, 413 timeInProcessStateForegroundService) 414 .addConsumedPower( 415 BatteryConsumer.POWER_COMPONENT_SCREEN, screenPower) 416 .addConsumedPower( 417 BatteryConsumer.POWER_COMPONENT_CPU, cpuPower) 418 .addConsumedPower( 419 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, customComponentPower) 420 .addUsageDurationMillis( 421 BatteryConsumer.POWER_COMPONENT_CPU, cpuDuration) 422 .addUsageDurationMillis( 423 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, customComponentDuration); 424 if (builder.isProcessStateDataNeeded()) { 425 final BatteryConsumer.Key cpuFgKey = builder.isScreenStateDataNeeded() 426 ? uidBuilder.getKey( 427 BatteryConsumer.POWER_COMPONENT_CPU, 428 BatteryConsumer.PROCESS_STATE_FOREGROUND, 429 BatteryConsumer.SCREEN_STATE_ON, 430 BatteryConsumer.POWER_STATE_BATTERY) 431 : uidBuilder.getKey( 432 BatteryConsumer.POWER_COMPONENT_CPU, 433 BatteryConsumer.PROCESS_STATE_FOREGROUND); 434 final BatteryConsumer.Key cpuBgKey = uidBuilder.getKey( 435 BatteryConsumer.POWER_COMPONENT_CPU, 436 BatteryConsumer.PROCESS_STATE_BACKGROUND); 437 final BatteryConsumer.Key cpuFgsKey = uidBuilder.getKey( 438 BatteryConsumer.POWER_COMPONENT_CPU, 439 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); 440 final BatteryConsumer.Key cachedKey = uidBuilder.getKey( 441 BatteryConsumer.POWER_COMPONENT_CPU, 442 BatteryConsumer.PROCESS_STATE_CACHED); 443 final BatteryConsumer.Key customBgKey = builder.isScreenStateDataNeeded() 444 ? uidBuilder.getKey( 445 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 446 BatteryConsumer.PROCESS_STATE_BACKGROUND, 447 BatteryConsumer.SCREEN_STATE_ON, 448 BatteryConsumer.POWER_STATE_BATTERY) 449 : uidBuilder.getKey( 450 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 451 BatteryConsumer.PROCESS_STATE_BACKGROUND); 452 uidBuilder.addConsumedPower(cpuFgKey, cpuPowerForeground) 453 .addUsageDurationMillis(cpuFgKey, cpuDurationForeground) 454 .addConsumedPower(cpuBgKey, cpuPowerBackground) 455 .addUsageDurationMillis(cpuBgKey, cpuDurationBackground) 456 .addConsumedPower(cpuFgsKey, cpuPowerFgs) 457 .addUsageDurationMillis(cpuFgsKey, cpuDurationFgs) 458 .addConsumedPower(cachedKey, cpuPowerCached) 459 .addUsageDurationMillis(cachedKey, cpuDurationCached) 460 .addConsumedPower(customBgKey, customComponentPower) 461 .addUsageDurationMillis(customBgKey, customComponentDuration); 462 } 463 } 464 addAggregateBatteryConsumer(BatteryUsageStats.Builder builder, int scope, double consumedPower, int cpuPower, int customComponentPower, int cpuDuration, int customComponentDuration, double cpuPowerBatScrOn, long cpuDurationBatScrOn, double cpuPowerBatScrOff, long cpuDurationBatScrOff, double cpuPowerChgScrOn, long cpuDurationChgScrOn, double cpuPowerChgScrOff, long cpuDurationChgScrOff)465 private void addAggregateBatteryConsumer(BatteryUsageStats.Builder builder, int scope, 466 double consumedPower, int cpuPower, int customComponentPower, int cpuDuration, 467 int customComponentDuration, double cpuPowerBatScrOn, long cpuDurationBatScrOn, 468 double cpuPowerBatScrOff, long cpuDurationBatScrOff, double cpuPowerChgScrOn, 469 long cpuDurationChgScrOn, double cpuPowerChgScrOff, long cpuDurationChgScrOff) { 470 final AggregateBatteryConsumer.Builder aggBuilder = 471 builder.getAggregateBatteryConsumerBuilder(scope) 472 .addConsumedPower(consumedPower) 473 .addConsumedPower( 474 BatteryConsumer.POWER_COMPONENT_CPU, cpuPower) 475 .addConsumedPower( 476 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 477 customComponentPower) 478 .addUsageDurationMillis( 479 BatteryConsumer.POWER_COMPONENT_CPU, cpuDuration) 480 .addUsageDurationMillis( 481 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 482 customComponentDuration); 483 if (builder.isPowerStateDataNeeded() || builder.isScreenStateDataNeeded()) { 484 final BatteryConsumer.Key cpuBatScrOn = aggBuilder.getKey( 485 BatteryConsumer.POWER_COMPONENT_CPU, 486 BatteryConsumer.PROCESS_STATE_UNSPECIFIED, 487 BatteryConsumer.SCREEN_STATE_ON, 488 BatteryConsumer.POWER_STATE_BATTERY); 489 final BatteryConsumer.Key cpuBatScrOff = aggBuilder.getKey( 490 BatteryConsumer.POWER_COMPONENT_CPU, 491 BatteryConsumer.PROCESS_STATE_UNSPECIFIED, 492 BatteryConsumer.SCREEN_STATE_OTHER, 493 BatteryConsumer.POWER_STATE_BATTERY); 494 final BatteryConsumer.Key cpuChgScrOn = aggBuilder.getKey( 495 BatteryConsumer.POWER_COMPONENT_CPU, 496 BatteryConsumer.PROCESS_STATE_UNSPECIFIED, 497 BatteryConsumer.SCREEN_STATE_ON, 498 BatteryConsumer.POWER_STATE_OTHER); 499 final BatteryConsumer.Key cpuChgScrOff = aggBuilder.getKey( 500 BatteryConsumer.POWER_COMPONENT_CPU, 501 BatteryConsumer.PROCESS_STATE_UNSPECIFIED, 502 BatteryConsumer.SCREEN_STATE_OTHER, 503 BatteryConsumer.POWER_STATE_OTHER); 504 aggBuilder.addConsumedPower(cpuBatScrOn, cpuPowerBatScrOn) 505 .addUsageDurationMillis(cpuBatScrOn, cpuDurationBatScrOn) 506 .addConsumedPower(cpuBatScrOff, cpuPowerBatScrOff) 507 .addUsageDurationMillis(cpuBatScrOff, cpuDurationBatScrOff) 508 .addConsumedPower(cpuChgScrOn, cpuPowerChgScrOn) 509 .addUsageDurationMillis(cpuChgScrOn, cpuDurationChgScrOn) 510 .addConsumedPower(cpuChgScrOff, cpuPowerChgScrOff) 511 .addUsageDurationMillis(cpuChgScrOff, cpuDurationChgScrOff); 512 } 513 } 514 assertBatteryUsageStats1(BatteryUsageStats batteryUsageStats, boolean includesUserBatteryConsumers)515 public void assertBatteryUsageStats1(BatteryUsageStats batteryUsageStats, 516 boolean includesUserBatteryConsumers) { 517 assertBatteryUsageStats(batteryUsageStats, 30000, 20, 1000, 2000, 1234, 1000, 3000, 2000); 518 519 final List<UidBatteryConsumer> uidBatteryConsumers = 520 batteryUsageStats.getUidBatteryConsumers(); 521 assertThat(uidBatteryConsumers).hasSize(1); 522 for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) { 523 if (uidBatteryConsumer.getUid() == APP_UID1) { 524 assertUidBatteryConsumer(uidBatteryConsumer, 1200, "foo", 525 1000, 1500, 500, 300, 400, 526 500, 600, 800, 527 true, 1777, 2388, 1999, 123, 1777, 7771, 1888, 8881, 1999, 9991, 123, 456); 528 } else { 529 fail("Unexpected UID " + uidBatteryConsumer.getUid()); 530 } 531 } 532 533 final List<UserBatteryConsumer> userBatteryConsumers = 534 batteryUsageStats.getUserBatteryConsumers(); 535 if (includesUserBatteryConsumers) { 536 assertThat(userBatteryConsumers).hasSize(1); 537 for (UserBatteryConsumer userBatteryConsumer : userBatteryConsumers) { 538 if (userBatteryConsumer.getUserId() == USER_ID) { 539 assertUserBatteryConsumer(userBatteryConsumer, 42, 10, 20, 30, 40); 540 } else { 541 fail("Unexpected User ID " + userBatteryConsumer.getUserId()); 542 } 543 } 544 } else { 545 assertThat(userBatteryConsumers).isEmpty(); 546 } 547 548 assertAggregateBatteryConsumer(batteryUsageStats, 549 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS, 550 10100, 10200, 10300, 10400); 551 552 assertAggregateBatteryConsumer(batteryUsageStats, 553 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE, 554 20100, 20200, 20300, 20400); 555 } 556 assertBatteryUsageStats(BatteryUsageStats batteryUsageStats, int consumedPower, int dischargePercentage, int dischagePowerLower, int dischargePowerUpper, int dischargeDuration, int statsStartTimestamp, int statsEndTimestamp, int statsDuration)557 private void assertBatteryUsageStats(BatteryUsageStats batteryUsageStats, int consumedPower, 558 int dischargePercentage, int dischagePowerLower, int dischargePowerUpper, 559 int dischargeDuration, int statsStartTimestamp, int statsEndTimestamp, 560 int statsDuration) { 561 assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(consumedPower); 562 assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(dischargePercentage); 563 assertThat(batteryUsageStats.getDischargedPowerRange().getLower()).isEqualTo( 564 dischagePowerLower); 565 assertThat(batteryUsageStats.getDischargedPowerRange().getUpper()).isEqualTo( 566 dischargePowerUpper); 567 assertThat(batteryUsageStats.getDischargeDurationMs()).isEqualTo(dischargeDuration); 568 assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(statsStartTimestamp); 569 assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(statsEndTimestamp); 570 assertThat(batteryUsageStats.getStatsDuration()).isEqualTo(statsDuration); 571 } 572 assertUidBatteryConsumer(UidBatteryConsumer uidBatteryConsumer, double consumedPower, String packageWithHighestDrain, int timeInProcessStateForeground, int timeInProcessStateBackground, int timeInProcessStateForegroundService, int screenPower, double cpuPower, double customComponentPower, int cpuDuration, int customComponentDuration, boolean processStateDataIncluded, double totalPowerForeground, double totalPowerBackground, double totalPowerFgs, double totalPowerCached, double cpuPowerForeground, int cpuDurationForeground, double cpuPowerBackground, int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs, int cpuPowerCached, int cpuDurationCached)573 private void assertUidBatteryConsumer(UidBatteryConsumer uidBatteryConsumer, 574 double consumedPower, String packageWithHighestDrain, int timeInProcessStateForeground, 575 int timeInProcessStateBackground, int timeInProcessStateForegroundService, 576 int screenPower, double cpuPower, 577 double customComponentPower, int cpuDuration, 578 int customComponentDuration, boolean processStateDataIncluded, 579 double totalPowerForeground, double totalPowerBackground, double totalPowerFgs, 580 double totalPowerCached, double cpuPowerForeground, int cpuDurationForeground, 581 double cpuPowerBackground, 582 int cpuDurationBackground, double cpuPowerFgs, int cpuDurationFgs, 583 int cpuPowerCached, int cpuDurationCached) { 584 assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(consumedPower); 585 assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo( 586 packageWithHighestDrain); 587 assertThat(uidBatteryConsumer.getTimeInStateMs( 588 UidBatteryConsumer.STATE_FOREGROUND)).isEqualTo(timeInProcessStateForeground); 589 assertThat(uidBatteryConsumer.getTimeInStateMs( 590 UidBatteryConsumer.STATE_BACKGROUND)).isEqualTo( 591 timeInProcessStateBackground + timeInProcessStateForegroundService); 592 assertThat(uidBatteryConsumer.getTimeInProcessStateMs( 593 PROCESS_STATE_FOREGROUND)).isEqualTo(timeInProcessStateForeground); 594 assertThat(uidBatteryConsumer.getTimeInProcessStateMs( 595 PROCESS_STATE_BACKGROUND)).isEqualTo(timeInProcessStateBackground); 596 assertThat(uidBatteryConsumer.getTimeInProcessStateMs( 597 PROCESS_STATE_FOREGROUND_SERVICE)).isEqualTo(timeInProcessStateForegroundService); 598 assertThat(uidBatteryConsumer.getConsumedPower( 599 BatteryConsumer.POWER_COMPONENT_SCREEN)).isEqualTo(screenPower); 600 assertThat(uidBatteryConsumer.getConsumedPower( 601 BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPower); 602 assertThat(uidBatteryConsumer.getConsumedPower( 603 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(customComponentPower); 604 assertThat(uidBatteryConsumer.getUsageDurationMillis( 605 BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuDuration); 606 assertThat(uidBatteryConsumer.getUsageDurationMillis( 607 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo( 608 customComponentDuration); 609 assertThat(uidBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1); 610 assertThat(uidBatteryConsumer.getCustomPowerComponentName( 611 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO"); 612 613 if (processStateDataIncluded) { 614 assertThat(uidBatteryConsumer.getConsumedPower( 615 new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY, 616 PROCESS_STATE_FOREGROUND))) 617 .isEqualTo(totalPowerForeground); 618 assertThat(uidBatteryConsumer.getConsumedPower( 619 new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY, 620 PROCESS_STATE_BACKGROUND))) 621 .isEqualTo(totalPowerBackground); 622 assertThat(uidBatteryConsumer.getConsumedPower( 623 new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY, 624 PROCESS_STATE_FOREGROUND_SERVICE))) 625 .isEqualTo(totalPowerFgs); 626 assertThat(uidBatteryConsumer.getConsumedPower( 627 new BatteryConsumer.Dimensions(POWER_COMPONENT_ANY, 628 PROCESS_STATE_CACHED))) 629 .isEqualTo(totalPowerCached); 630 } 631 632 final BatteryConsumer.Dimensions cpuFg = new BatteryConsumer.Dimensions( 633 BatteryConsumer.POWER_COMPONENT_CPU, BatteryConsumer.PROCESS_STATE_FOREGROUND); 634 if (processStateDataIncluded) { 635 assertThat(uidBatteryConsumer.getConsumedPower(cpuFg)) 636 .isEqualTo(cpuPowerForeground); 637 assertThat(uidBatteryConsumer.getUsageDurationMillis(cpuFg)) 638 .isEqualTo(cpuDurationForeground); 639 } else { 640 assertThat(uidBatteryConsumer.getConsumedPower(cpuFg)).isEqualTo(0); 641 } 642 643 final BatteryConsumer.Dimensions cpuBg = new BatteryConsumer.Dimensions( 644 BatteryConsumer.POWER_COMPONENT_CPU, BatteryConsumer.PROCESS_STATE_BACKGROUND); 645 if (processStateDataIncluded) { 646 assertThat(uidBatteryConsumer.getConsumedPower(cpuBg)) 647 .isEqualTo(cpuPowerBackground); 648 assertThat(uidBatteryConsumer.getUsageDurationMillis(cpuBg)) 649 .isEqualTo(cpuDurationBackground); 650 } else { 651 assertThat(uidBatteryConsumer.getConsumedPower(cpuBg)) 652 .isEqualTo(0); 653 } 654 655 final BatteryConsumer.Dimensions cpuFgs = new BatteryConsumer.Dimensions( 656 BatteryConsumer.POWER_COMPONENT_CPU, 657 BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE); 658 if (processStateDataIncluded) { 659 assertThat(uidBatteryConsumer.getConsumedPower(cpuFgs)) 660 .isEqualTo(cpuPowerFgs); 661 assertThat(uidBatteryConsumer.getUsageDurationMillis(cpuFgs)) 662 .isEqualTo(cpuDurationFgs); 663 } else { 664 assertThat(uidBatteryConsumer.getConsumedPower(cpuFgs)) 665 .isEqualTo(0); 666 } 667 668 final BatteryConsumer.Dimensions cached = new BatteryConsumer.Dimensions( 669 BatteryConsumer.POWER_COMPONENT_CPU, 670 BatteryConsumer.PROCESS_STATE_CACHED); 671 if (processStateDataIncluded) { 672 assertThat(uidBatteryConsumer.getConsumedPower(cached)) 673 .isEqualTo(cpuPowerCached); 674 assertThat(uidBatteryConsumer.getUsageDurationMillis(cached)) 675 .isEqualTo(cpuDurationCached); 676 } else { 677 assertThat(uidBatteryConsumer.getConsumedPower(cached)) 678 .isEqualTo(0); 679 } 680 } 681 assertUserBatteryConsumer(UserBatteryConsumer userBatteryConsumer, int userId, int cpuPower, int customComponentPower, int cpuDuration, int customComponentDuration)682 private void assertUserBatteryConsumer(UserBatteryConsumer userBatteryConsumer, 683 int userId, int cpuPower, int customComponentPower, 684 int cpuDuration, int customComponentDuration) { 685 assertThat(userBatteryConsumer.getConsumedPower( 686 BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPower); 687 assertThat(userBatteryConsumer.getConsumedPower( 688 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(customComponentPower); 689 assertThat(userBatteryConsumer.getUsageDurationMillis( 690 BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuDuration); 691 assertThat(userBatteryConsumer.getUsageDurationMillis( 692 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo( 693 customComponentDuration); 694 assertThat(userBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1); 695 assertThat(userBatteryConsumer.getCustomPowerComponentName( 696 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO"); 697 } 698 assertAggregateBatteryConsumer(BatteryUsageStats batteryUsageStats, int aggregateBatteryConsumerScopeAllApps, int cpuPower, int customComponentPower, int cpuDuration, int customComponentDuration)699 private void assertAggregateBatteryConsumer(BatteryUsageStats batteryUsageStats, 700 int aggregateBatteryConsumerScopeAllApps, int cpuPower, int customComponentPower, 701 int cpuDuration, int customComponentDuration) { 702 final BatteryConsumer appsBatteryConsumer = batteryUsageStats.getAggregateBatteryConsumer( 703 aggregateBatteryConsumerScopeAllApps); 704 assertThat(appsBatteryConsumer.getConsumedPower( 705 BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuPower); 706 assertThat(appsBatteryConsumer.getConsumedPower( 707 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(customComponentPower); 708 assertThat(appsBatteryConsumer.getUsageDurationMillis( 709 BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(cpuDuration); 710 assertThat(appsBatteryConsumer.getUsageDurationMillis( 711 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo( 712 customComponentDuration); 713 assertThat(appsBatteryConsumer.getCustomPowerComponentCount()).isEqualTo(1); 714 assertThat(appsBatteryConsumer.getCustomPowerComponentName( 715 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo("FOO"); 716 } 717 } 718