• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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