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