• 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 android.os;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.database.Cursor;
23 import android.database.CursorWindow;
24 import android.util.IntArray;
25 import android.util.Slog;
26 import android.util.SparseArray;
27 import android.util.proto.ProtoOutputStream;
28 
29 import java.io.PrintWriter;
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.List;
35 
36 /**
37  * Interface for objects containing battery attribution data.
38  *
39  * @hide
40  */
41 @android.ravenwood.annotation.RavenwoodKeepWholeClass
42 public abstract class BatteryConsumer {
43 
44     private static final String TAG = "BatteryConsumer";
45 
46     /**
47      * Power usage component, describing the particular part of the system
48      * responsible for power drain.
49      *
50      * @hide
51      */
52     @IntDef(prefix = {"POWER_COMPONENT_"}, value = {
53             POWER_COMPONENT_ANY,
54             POWER_COMPONENT_SCREEN,
55             POWER_COMPONENT_CPU,
56             POWER_COMPONENT_BLUETOOTH,
57             POWER_COMPONENT_CAMERA,
58             POWER_COMPONENT_AUDIO,
59             POWER_COMPONENT_VIDEO,
60             POWER_COMPONENT_FLASHLIGHT,
61             POWER_COMPONENT_MOBILE_RADIO,
62             POWER_COMPONENT_SYSTEM_SERVICES,
63             POWER_COMPONENT_SENSORS,
64             POWER_COMPONENT_GNSS,
65             POWER_COMPONENT_WIFI,
66             POWER_COMPONENT_WAKELOCK,
67             POWER_COMPONENT_MEMORY,
68             POWER_COMPONENT_PHONE,
69             POWER_COMPONENT_AMBIENT_DISPLAY,
70             POWER_COMPONENT_IDLE,
71             POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
72             POWER_COMPONENT_BASE,
73     })
74     @Retention(RetentionPolicy.SOURCE)
75     public @interface PowerComponent {
76     }
77 
78     public static final int POWER_COMPONENT_ANY = -1;
79     public static final int POWER_COMPONENT_SCREEN = OsProtoEnums.POWER_COMPONENT_SCREEN; // 0
80     public static final int POWER_COMPONENT_CPU = OsProtoEnums.POWER_COMPONENT_CPU; // 1
81     public static final int POWER_COMPONENT_BLUETOOTH = OsProtoEnums.POWER_COMPONENT_BLUETOOTH; // 2
82     public static final int POWER_COMPONENT_CAMERA = OsProtoEnums.POWER_COMPONENT_CAMERA; // 3
83     public static final int POWER_COMPONENT_AUDIO = OsProtoEnums.POWER_COMPONENT_AUDIO; // 4
84     public static final int POWER_COMPONENT_VIDEO = OsProtoEnums.POWER_COMPONENT_VIDEO; // 5
85     public static final int POWER_COMPONENT_FLASHLIGHT =
86             OsProtoEnums.POWER_COMPONENT_FLASHLIGHT; // 6
87     public static final int POWER_COMPONENT_SYSTEM_SERVICES =
88             OsProtoEnums.POWER_COMPONENT_SYSTEM_SERVICES; // 7
89     public static final int POWER_COMPONENT_MOBILE_RADIO =
90             OsProtoEnums.POWER_COMPONENT_MOBILE_RADIO; // 8
91     public static final int POWER_COMPONENT_SENSORS = OsProtoEnums.POWER_COMPONENT_SENSORS; // 9
92     public static final int POWER_COMPONENT_GNSS = OsProtoEnums.POWER_COMPONENT_GNSS; // 10
93     public static final int POWER_COMPONENT_WIFI = OsProtoEnums.POWER_COMPONENT_WIFI; // 11
94     public static final int POWER_COMPONENT_WAKELOCK = OsProtoEnums.POWER_COMPONENT_WAKELOCK; // 12
95     public static final int POWER_COMPONENT_MEMORY = OsProtoEnums.POWER_COMPONENT_MEMORY; // 13
96     public static final int POWER_COMPONENT_PHONE = OsProtoEnums.POWER_COMPONENT_PHONE; // 14
97     public static final int POWER_COMPONENT_AMBIENT_DISPLAY =
98             OsProtoEnums.POWER_COMPONENT_AMBIENT_DISPLAY; // 15
99     public static final int POWER_COMPONENT_IDLE = OsProtoEnums.POWER_COMPONENT_IDLE; // 16
100     // Power that is re-attributed to other battery consumers. For example, for System Server
101     // this represents the power attributed to apps requesting system services.
102     // The value should be negative or zero.
103     public static final int POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS =
104             OsProtoEnums.POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS; // 17
105     // Power component ID that is used for technical purposes of attribution of time-in-state
106     // for UIDs and other general computations not associated with specific hardware.
107     public static final int POWER_COMPONENT_BASE = 18;
108     public static final int POWER_COMPONENT_COUNT = 19;
109 
110     public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
111     public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
112 
113     private static final String[] sPowerComponentNames = new String[POWER_COMPONENT_COUNT];
114 
115     static {
116         // Assign individually to avoid future mismatch
117         sPowerComponentNames[POWER_COMPONENT_SCREEN] = "screen";
118         sPowerComponentNames[POWER_COMPONENT_CPU] = "cpu";
119         sPowerComponentNames[POWER_COMPONENT_BLUETOOTH] = "bluetooth";
120         sPowerComponentNames[POWER_COMPONENT_CAMERA] = "camera";
121         sPowerComponentNames[POWER_COMPONENT_AUDIO] = "audio";
122         sPowerComponentNames[POWER_COMPONENT_VIDEO] = "video";
123         sPowerComponentNames[POWER_COMPONENT_FLASHLIGHT] = "flashlight";
124         sPowerComponentNames[POWER_COMPONENT_SYSTEM_SERVICES] = "system_services";
125         sPowerComponentNames[POWER_COMPONENT_MOBILE_RADIO] = "mobile_radio";
126         sPowerComponentNames[POWER_COMPONENT_SENSORS] = "sensors";
127         sPowerComponentNames[POWER_COMPONENT_GNSS] = "gnss";
128         sPowerComponentNames[POWER_COMPONENT_WIFI] = "wifi";
129         sPowerComponentNames[POWER_COMPONENT_WAKELOCK] = "wakelock";
130         sPowerComponentNames[POWER_COMPONENT_MEMORY] = "memory";
131         sPowerComponentNames[POWER_COMPONENT_PHONE] = "phone";
132         sPowerComponentNames[POWER_COMPONENT_AMBIENT_DISPLAY] = "ambient_display";
133         sPowerComponentNames[POWER_COMPONENT_IDLE] = "idle";
134         sPowerComponentNames[POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS] = "reattributed";
135         sPowerComponentNames[POWER_COMPONENT_BASE] = "";        // Top-level, no need for a name
136     }
137 
138     /**
139      * An integer that is either one of @PowerComponent constants or a custom component ID
140      * between FIRST_CUSTOM_POWER_COMPONENT_ID and LAST_CUSTOM_POWER_COMPONENT_ID.
141      *
142      * @hide
143      */
144     @Retention(RetentionPolicy.SOURCE)
145     public @interface PowerComponentId {
146     }
147 
148     /**
149      * Identifiers of models used for power estimation.
150      *
151      * @hide
152      */
153     @IntDef(prefix = {"POWER_MODEL_"}, value = {
154             POWER_MODEL_UNDEFINED,
155             POWER_MODEL_POWER_PROFILE,
156             POWER_MODEL_ENERGY_CONSUMPTION,
157     })
158     @Retention(RetentionPolicy.SOURCE)
159     public @interface PowerModel {
160     }
161 
162     /**
163      * Unspecified power model.
164      *
165      * @deprecated PowerModel is no longer supported
166      */
167     @Deprecated
168     public static final int POWER_MODEL_UNDEFINED = 0;
169 
170     /**
171      * Power model that is based on average consumption rates that hardware components
172      * consume in various states.
173      *
174      * @deprecated PowerModel is no longer supported
175      */
176     @Deprecated
177     public static final int POWER_MODEL_POWER_PROFILE = 1;
178 
179     /**
180      * Power model that is based on energy consumption stats provided by PowerStats HAL.
181      *
182      * @deprecated PowerModel is no longer supported
183      */
184     @Deprecated
185     public static final int POWER_MODEL_ENERGY_CONSUMPTION = 2;
186 
187     /**
188      * Identifiers of consumed power aggregations.
189      *
190      * @hide
191      */
192     @IntDef(prefix = {"PROCESS_STATE_"}, value = {
193             PROCESS_STATE_ANY,
194             PROCESS_STATE_UNSPECIFIED,
195             PROCESS_STATE_FOREGROUND,
196             PROCESS_STATE_BACKGROUND,
197             PROCESS_STATE_FOREGROUND_SERVICE,
198             PROCESS_STATE_CACHED,
199     })
200     @Retention(RetentionPolicy.SOURCE)
201     public @interface ProcessState {
202     }
203 
204     public static final int PROCESS_STATE_ANY = -1;
205     public static final int PROCESS_STATE_UNSPECIFIED = 0;
206     public static final int PROCESS_STATE_FOREGROUND = 1;
207     public static final int PROCESS_STATE_BACKGROUND = 2;
208     public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
209     public static final int PROCESS_STATE_CACHED = 4;
210 
211     public static final int PROCESS_STATE_COUNT = 5;
212 
213     private static final String[] sProcessStateNames = new String[PROCESS_STATE_COUNT];
214 
215     static {
216         // Assign individually to avoid future mismatch
217         sProcessStateNames[PROCESS_STATE_UNSPECIFIED] = "unspecified";
218         sProcessStateNames[PROCESS_STATE_FOREGROUND] = "fg";
219         sProcessStateNames[PROCESS_STATE_BACKGROUND] = "bg";
220         sProcessStateNames[PROCESS_STATE_FOREGROUND_SERVICE] = "fgs";
221         sProcessStateNames[PROCESS_STATE_CACHED] = "cached";
222     }
223 
224     private static final IntArray SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE;
225     static {
226         int[] supportedPowerComponents = {
227                 POWER_COMPONENT_BASE,
228                 POWER_COMPONENT_CPU,
229                 POWER_COMPONENT_MOBILE_RADIO,
230                 POWER_COMPONENT_WIFI,
231                 POWER_COMPONENT_BLUETOOTH,
232                 POWER_COMPONENT_AUDIO,
233                 POWER_COMPONENT_VIDEO,
234                 POWER_COMPONENT_FLASHLIGHT,
235                 POWER_COMPONENT_CAMERA,
236                 POWER_COMPONENT_GNSS,
237                 POWER_COMPONENT_SENSORS,
238                 POWER_COMPONENT_WAKELOCK,
239         };
240         Arrays.sort(supportedPowerComponents);
241         SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE = IntArray.wrap(supportedPowerComponents);
242     };
243 
244     static final int COLUMN_INDEX_BATTERY_CONSUMER_TYPE = 0;
245     /**
246      * Identifiers of consumed power aggregations per SCREEN state.
247      *
248      * @hide
249      */
250     @IntDef(prefix = {"SCREEN_STATE_"}, value = {
251             SCREEN_STATE_ANY,
252             SCREEN_STATE_UNSPECIFIED,
253             SCREEN_STATE_ON,
254             SCREEN_STATE_OTHER,
255     })
256     @Retention(RetentionPolicy.SOURCE)
257     public @interface ScreenState {
258     }
259 
260     static final int COLUMN_COUNT = 1;
261 
262     public static final int SCREEN_STATE_ANY = 0;
263     public static final int SCREEN_STATE_UNSPECIFIED = 0;
264     public static final int SCREEN_STATE_ON = 1;
265     public static final int SCREEN_STATE_OTHER = 2;  // Off, doze etc
266 
267     public static final int SCREEN_STATE_COUNT = 3;
268 
269     private static final String[] sScreenStateNames = new String[SCREEN_STATE_COUNT];
270 
271     static {
272         // Assign individually to avoid future mismatch
273         sScreenStateNames[SCREEN_STATE_UNSPECIFIED] = "unspecified";
274         sScreenStateNames[SCREEN_STATE_ON] = "on";
275         sScreenStateNames[SCREEN_STATE_OTHER] = "off/doze";
276     }
277 
278     /**
279      * Identifiers of consumed power aggregations per POWER state.
280      *
281      * @hide
282      */
283     @IntDef(prefix = {"POWER_STATE_"}, value = {
284             POWER_STATE_ANY,
285             POWER_STATE_UNSPECIFIED,
286             POWER_STATE_BATTERY,
287             POWER_STATE_OTHER,
288     })
289     @Retention(RetentionPolicy.SOURCE)
290     public @interface PowerState {
291     }
292 
293     public static final int POWER_STATE_ANY = 0;
294     public static final int POWER_STATE_UNSPECIFIED = 0;
295     public static final int POWER_STATE_BATTERY = 1;
296     public static final int POWER_STATE_OTHER = 2;   // Plugged in, or on wireless charger, etc.
297 
298     public static final int POWER_STATE_COUNT = 3;
299 
300     private static final String[] sPowerStateNames = new String[POWER_STATE_COUNT];
301 
302     static {
303         // Assign individually to avoid future mismatch
304         sPowerStateNames[POWER_STATE_UNSPECIFIED] = "unspecified";
305         sPowerStateNames[POWER_STATE_BATTERY] = "on battery";
306         sPowerStateNames[POWER_STATE_OTHER] = "not on battery";
307     }
308 
309     /**
310      * Identifies power attribution dimensions that a caller is interested in.
311      */
312     public static final class Dimensions {
313         public final @PowerComponentId int powerComponentId;
314         public final @ProcessState int processState;
315         public final @ScreenState int screenState;
316         public final @PowerState int powerState;
317 
Dimensions(@owerComponentId int powerComponentId, @ProcessState int processState)318         public Dimensions(@PowerComponentId int powerComponentId, @ProcessState int processState) {
319             this(powerComponentId, processState, SCREEN_STATE_ANY, POWER_STATE_ANY);
320         }
321 
Dimensions(@owerComponentId int powerComponentId, int processState, @ScreenState int screenState, @PowerState int powerState)322         public Dimensions(@PowerComponentId int powerComponentId, int processState,
323                 @ScreenState int screenState, @PowerState int powerState) {
324             this.powerComponentId = powerComponentId;
325             this.processState = processState;
326             this.screenState = screenState;
327             this.powerState = powerState;
328         }
329 
330         @Override
toString()331         public String toString() {
332             boolean dimensionSpecified = false;
333             StringBuilder sb = new StringBuilder();
334             if (powerComponentId != POWER_COMPONENT_ANY) {
335                 sb.append("powerComponent=");
336                 if (powerComponentId < POWER_COMPONENT_COUNT) {
337                     sb.append(sPowerComponentNames[powerComponentId]);
338                 } else {
339                     sb.append("CUSTOM/").append(powerComponentId);
340                 }
341                 dimensionSpecified = true;
342             }
343             if (processState != PROCESS_STATE_ANY) {
344                 if (dimensionSpecified) {
345                     sb.append(", ");
346                 }
347                 sb.append("processState=").append(sProcessStateNames[processState]);
348                 dimensionSpecified = true;
349             }
350             if (screenState != SCREEN_STATE_ANY) {
351                 if (dimensionSpecified) {
352                     sb.append(", ");
353                 }
354                 sb.append("screenState=").append(screenStateToString(screenState));
355                 dimensionSpecified = true;
356             }
357             if (powerState != POWER_STATE_ANY) {
358                 if (dimensionSpecified) {
359                     sb.append(", ");
360                 }
361                 sb.append("powerState=").append(powerStateToString(powerState));
362                 dimensionSpecified = true;
363             }
364             if (!dimensionSpecified) {
365                 sb.append("any components and process states");
366             }
367             return sb.toString();
368         }
369     }
370 
371     public static final Dimensions UNSPECIFIED_DIMENSIONS =
372             new Dimensions(POWER_COMPONENT_ANY, PROCESS_STATE_ANY, SCREEN_STATE_ANY,
373                     POWER_STATE_ANY);
374 
375     /**
376      * Identifies power attribution dimensions that are captured by a data element of
377      * a BatteryConsumer. These Keys are used to access those values and to set them using
378      * Builders.  See for example {@link #getConsumedPower(Key)}.
379      *
380      * Keys cannot be allocated by the client - they can only be obtained by calling
381      * {@link #getKeys} or {@link #getKey}.  All BatteryConsumers that are part of the
382      * same BatteryUsageStats share the same set of keys, therefore it is safe to obtain
383      * the keys from one BatteryConsumer and apply them to other BatteryConsumers
384      * in the same BatteryUsageStats.
385      */
386     public static final class Key {
387         public final @PowerComponentId int powerComponentId;
388         public final @ProcessState int processState;
389         public final @ScreenState int screenState;
390         public final @PowerState int powerState;
391 
392         final int mPowerColumnIndex;
393         final int mDurationColumnIndex;
394 
Key(@owerComponentId int powerComponentId, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState, int powerColumnIndex, int durationColumnIndex)395         private Key(@PowerComponentId int powerComponentId, @ProcessState int processState,
396                 @ScreenState int screenState, @PowerState int powerState,
397                 int powerColumnIndex, int durationColumnIndex) {
398             this.powerComponentId = powerComponentId;
399             this.processState = processState;
400             this.screenState = screenState;
401             this.powerState = powerState;
402 
403             mPowerColumnIndex = powerColumnIndex;
404             mDurationColumnIndex = durationColumnIndex;
405         }
406 
407         /**
408          * Returns true if this key should be included in an enumeration parameterized with
409          * the supplied dimensions.
410          */
matches(@owerComponentId int powerComponent, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState)411         boolean matches(@PowerComponentId int powerComponent, @ProcessState int processState,
412                 @ScreenState int screenState, @PowerState int powerState) {
413             if (powerComponent != POWER_COMPONENT_ANY && this.powerComponentId != powerComponent) {
414                 return false;
415             }
416             if (this.processState == PROCESS_STATE_UNSPECIFIED) {
417                 // PROCESS_STATE_UNSPECIFIED is used for storing a precomputed total
418                 return false;
419             }
420             if (processState != PROCESS_STATE_ANY && this.processState != processState) {
421                 return false;
422             }
423             if (screenState != SCREEN_STATE_ANY && this.screenState != screenState) {
424                 return false;
425             }
426             if (powerState != POWER_STATE_ANY && this.powerState != powerState) {
427                 return false;
428             }
429             return true;
430         }
431 
432         @SuppressWarnings("EqualsUnsafeCast")
433         @Override
equals(Object o)434         public boolean equals(Object o) {
435             // Skipping null and class check for performance
436             final Key key = (Key) o;
437             return powerComponentId == key.powerComponentId
438                     && processState == key.processState
439                     && screenState == key.screenState
440                     && powerState == key.powerState;
441         }
442 
443         @Override
hashCode()444         public int hashCode() {
445             int result = powerComponentId;
446             result = 31 * result + processState;
447             result = 31 * result + screenState;
448             result = 31 * result + powerState;
449             return result;
450         }
451 
452         /**
453          * Returns a string suitable for use in dumpsys.
454          */
toString(@owerComponentId int powerComponent, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState)455         public static String toString(@PowerComponentId int powerComponent,
456                 @ProcessState int processState, @ScreenState int screenState,
457                 @PowerState int powerState) {
458             StringBuilder sb = new StringBuilder();
459             if (powerComponent < POWER_COMPONENT_COUNT) {
460                 sb.append(powerComponentIdToString(powerComponent));
461             } else {
462                 sb.append("CUSTOM/").append(powerComponent);
463             }
464             if (processState != PROCESS_STATE_UNSPECIFIED) {
465                 sb.append(':');
466                 sb.append(processStateToString(processState));
467             }
468             if (screenState != SCREEN_STATE_UNSPECIFIED) {
469                 sb.append(":scr-");
470                 sb.append(sScreenStateNames[screenState]);
471             }
472             if (powerState != POWER_STATE_UNSPECIFIED) {
473                 sb.append(":pwr-");
474                 sb.append(sPowerStateNames[powerState]);
475             }
476             return sb.toString();
477         }
478 
479         @Override
toString()480         public String toString() {
481             return toString(powerComponentId, processState, screenState, powerState);
482         }
483     }
484 
485     protected final BatteryConsumerData mData;
486     protected final PowerComponents mPowerComponents;
487 
BatteryConsumer(BatteryConsumerData data, @NonNull PowerComponents powerComponents)488     protected BatteryConsumer(BatteryConsumerData data, @NonNull PowerComponents powerComponents) {
489         mData = data;
490         mPowerComponents = powerComponents;
491     }
492 
BatteryConsumer(BatteryConsumerData data)493     public BatteryConsumer(BatteryConsumerData data) {
494         mData = data;
495         mPowerComponents = new PowerComponents(data);
496     }
497 
498     /**
499      * Returns the name of the specified power component, e.g. "CPU", "GPU" etc.
500      */
getPowerComponentName(@owerComponentId int powerComponent)501     public String getPowerComponentName(@PowerComponentId int powerComponent) {
502         return mData.layout.getPowerComponentName(powerComponent);
503     }
504 
505     /**
506      * Total power consumed by this consumer, in mAh.
507      */
getConsumedPower()508     public double getConsumedPower() {
509         return mPowerComponents.getConsumedPower(UNSPECIFIED_DIMENSIONS);
510     }
511 
512     /**
513      * Returns power consumed aggregated over the specified dimensions, in mAh.
514      */
getConsumedPower(Dimensions dimensions)515     public double getConsumedPower(Dimensions dimensions) {
516         return mPowerComponents.getConsumedPower(dimensions);
517     }
518 
519     /**
520      * Returns the amount of usage time  aggregated over the specified dimensions, in millis.
521      */
getUsageDurationMillis(@onNull Dimensions dimensions)522     public long getUsageDurationMillis(@NonNull Dimensions dimensions) {
523         return mPowerComponents.getUsageDurationMillis(dimensions);
524     }
525 
526     /**
527      * Returns indexes of all included power components.
528      */
529     @PowerComponentId
getPowerComponentIds()530     public int[] getPowerComponentIds() {
531         return mData.layout.powerComponentIds;
532     }
533 
534     /**
535      * Returns keys for various power values attributed to the specified component
536      * held by this BatteryUsageStats object.
537      */
getKeys(@owerComponentId int componentId)538     public Key[] getKeys(@PowerComponentId int componentId) {
539         return mData.layout.getKeys(componentId);
540     }
541 
542     /**
543      * Returns the key for the power attributed to the specified component,
544      * for all values of other dimensions such as process state.
545      */
getKey(@owerComponentId int componentId)546     public Key getKey(@PowerComponentId int componentId) {
547         return mData.layout.getKey(componentId, PROCESS_STATE_UNSPECIFIED, SCREEN_STATE_UNSPECIFIED,
548                 POWER_STATE_UNSPECIFIED);
549     }
550 
551     /**
552      * Returns the key for the power attributed to the specified component and process state.
553      */
getKey(@owerComponentId int componentId, @ProcessState int processState)554     public Key getKey(@PowerComponentId int componentId, @ProcessState int processState) {
555         return mData.layout.getKey(componentId, processState, SCREEN_STATE_UNSPECIFIED,
556                 POWER_STATE_UNSPECIFIED);
557     }
558 
559     /**
560      * Returns the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
561      *
562      * @param componentId The ID of the power component, e.g.
563      *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
564      * @return Amount of consumed power in mAh.
565      */
getConsumedPower(@owerComponentId int componentId)566     public double getConsumedPower(@PowerComponentId int componentId) {
567         return mPowerComponents.getConsumedPower(componentId, PROCESS_STATE_ANY,
568                         SCREEN_STATE_ANY, POWER_STATE_ANY);
569     }
570 
571     /**
572      * Returns the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
573      *
574      * @param key The key of the power component, obtained by calling {@link #getKey} or
575      *            {@link #getKeys} method.
576      * @return Amount of consumed power in mAh.
577      */
getConsumedPower(@onNull Key key)578     public double getConsumedPower(@NonNull Key key) {
579         return mPowerComponents.getConsumedPower(key);
580     }
581 
582     /**
583      * Returns the ID of the model that was used for power estimation.
584      *
585      * @param componentId The ID of the power component, e.g.
586      *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
587      * @deprecated PowerModel is no longer supported
588      */
589     @Deprecated
getPowerModel(@owerComponentId int componentId)590     public @PowerModel int getPowerModel(@PowerComponentId int componentId) {
591         return POWER_MODEL_UNDEFINED;
592     }
593 
594     /**
595      * Returns the ID of the model that was used for power estimation.
596      *
597      * @param key The key of the power component, obtained by calling {@link #getKey} or
598      *            {@link #getKeys} method.
599      * @deprecated PowerModel is no longer supported
600      */
601     @Deprecated
getPowerModel(@onNull BatteryConsumer.Key key)602     public @PowerModel int getPowerModel(@NonNull BatteryConsumer.Key key) {
603         return POWER_MODEL_UNDEFINED;
604     }
605 
606     /**
607      * Returns the amount of drain attributed to the specified custom drain type.
608      *
609      * @param componentId The ID of the custom power component.
610      * @return Amount of consumed power in mAh.
611      *
612      * @deprecated Use getConsumedPower instead
613      */
614     @Deprecated
getConsumedPowerForCustomComponent(int componentId)615     public double getConsumedPowerForCustomComponent(int componentId) {
616         return getConsumedPower(componentId);
617     }
618 
getCustomPowerComponentCount()619     public int getCustomPowerComponentCount() {
620         return mData.layout.customPowerComponentCount;
621     }
622 
623     /**
624      * Returns the name of the specified power component.
625      *
626      * @param componentId The ID of the custom power component.
627      */
getCustomPowerComponentName(int componentId)628     public String getCustomPowerComponentName(int componentId) {
629         return mPowerComponents.getCustomPowerComponentName(componentId);
630     }
631 
632     /**
633      * Returns the amount of time since BatteryStats reset used by the specified component, e.g.
634      * CPU, WiFi etc.
635      *
636      * @param componentId The ID of the power component, e.g.
637      *                    {@link UidBatteryConsumer#POWER_COMPONENT_CPU}.
638      * @return Amount of time in milliseconds.
639      */
getUsageDurationMillis(@owerComponentId int componentId)640     public long getUsageDurationMillis(@PowerComponentId int componentId) {
641         return mPowerComponents.getUsageDurationMillis(componentId, PROCESS_STATE_ANY,
642                 SCREEN_STATE_ANY, POWER_STATE_ANY);
643     }
644 
645     /**
646      * Returns the amount of time since BatteryStats reset used by the specified component, e.g.
647      * CPU, WiFi etc.
648      *
649      *
650      * @param key The key of the power component, obtained by calling {@link #getKey} or
651      *            {@link #getKeys} method.
652      * @return Amount of time in milliseconds.
653      */
getUsageDurationMillis(@onNull Key key)654     public long getUsageDurationMillis(@NonNull Key key) {
655         return mPowerComponents.getUsageDurationMillis(key);
656     }
657 
658     /**
659      * Returns the name of the specified component.  Intended for logging and debugging.
660      */
powerComponentIdToString(@atteryConsumer.PowerComponent int componentId)661     public static String powerComponentIdToString(@BatteryConsumer.PowerComponent int componentId) {
662         if (componentId == POWER_COMPONENT_ANY) {
663             return "all";
664         }
665         return sPowerComponentNames[componentId];
666     }
667 
668     /**
669      * Returns the equivalent PowerModel enum for the specified power model.
670      * {@see BatteryUsageStatsAtomsProto.BatteryConsumerData.PowerComponentUsage.PowerModel}
671      */
powerModelToProtoEnum(@atteryConsumer.PowerModel int powerModel)672     public static int powerModelToProtoEnum(@BatteryConsumer.PowerModel int powerModel) {
673         switch (powerModel) {
674             case BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION:
675                 return BatteryUsageStatsAtomsProto.PowerComponentModel.MEASURED_ENERGY;
676             case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
677                 return BatteryUsageStatsAtomsProto.PowerComponentModel.POWER_PROFILE;
678             default:
679                 return BatteryUsageStatsAtomsProto.PowerComponentModel.UNDEFINED;
680         }
681     }
682 
683     /**
684      * Returns the name of the specified process state.  Intended for logging and debugging.
685      */
processStateToString(@atteryConsumer.ProcessState int processState)686     public static String processStateToString(@BatteryConsumer.ProcessState int processState) {
687         return sProcessStateNames[processState];
688     }
689 
690     /**
691      * Returns the human-readable name of the specified power state (on battery or not)
692      */
powerStateToString(@owerState int powerState)693     public static String powerStateToString(@PowerState int powerState) {
694         return sPowerStateNames[powerState];
695     }
696 
697     /**
698      * Returns the human-readable name of the specified screen state (on or off/doze)
699      */
screenStateToString(@creenState int screenState)700     public static String screenStateToString(@ScreenState int screenState) {
701         return sScreenStateNames[screenState];
702     }
703 
704     /**
705      * Prints the stats in a human-readable format.
706      */
dump(PrintWriter pw)707     public void dump(PrintWriter pw) {
708         dump(pw, true);
709     }
710 
711     /**
712      * Prints the stats in a human-readable format.
713      *
714      * @param skipEmptyComponents if true, omit any power components with a zero amount.
715      */
dump(PrintWriter pw, boolean skipEmptyComponents)716     public abstract void dump(PrintWriter pw, boolean skipEmptyComponents);
717 
718     /** Returns whether there are any atoms.proto BATTERY_CONSUMER_DATA data to write to a proto. */
hasStatsProtoData()719     boolean hasStatsProtoData() {
720         return writeStatsProtoImpl(null, /* Irrelevant fieldId: */ 0);
721     }
722 
723     /** Writes the atoms.proto BATTERY_CONSUMER_DATA for this BatteryConsumer to the given proto. */
writeStatsProto(@onNull ProtoOutputStream proto, long fieldId)724     void writeStatsProto(@NonNull ProtoOutputStream proto, long fieldId) {
725         writeStatsProtoImpl(proto, fieldId);
726     }
727 
728     /**
729      * Returns whether there are any atoms.proto BATTERY_CONSUMER_DATA data to write to a proto,
730      * and writes it to the given proto if it is non-null.
731      */
writeStatsProtoImpl(@ullable ProtoOutputStream proto, long fieldId)732     private boolean writeStatsProtoImpl(@Nullable ProtoOutputStream proto, long fieldId) {
733         final long totalConsumedPowerDeciCoulombs = convertMahToDeciCoulombs(getConsumedPower());
734 
735         if (totalConsumedPowerDeciCoulombs == 0) {
736             // NOTE: Strictly speaking we should also check !mPowerComponents.hasStatsProtoData().
737             // However, that call is a bit expensive (a for loop). And the only way that
738             // totalConsumedPower can be 0 while mPowerComponents.hasStatsProtoData() is true is
739             // if POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS (which is the only negative
740             // allowed) happens to exactly equal the sum of all other components, which
741             // can't really happen in practice.
742             // So we'll just adopt the rule "if total==0, don't write any details".
743             // If negative values are used for other things in the future, this can be revisited.
744             return false;
745         }
746         if (proto == null) {
747             // We're just asked whether there is data, not to actually write it. And there is.
748             return true;
749         }
750 
751         final long token = proto.start(fieldId);
752         proto.write(
753                 BatteryUsageStatsAtomsProto.BatteryConsumerData.TOTAL_CONSUMED_POWER_DECI_COULOMBS,
754                 totalConsumedPowerDeciCoulombs);
755         mPowerComponents.writeStatsProto(proto);
756         proto.end(token);
757 
758         return true;
759     }
760 
761     /** Converts charge from milliamp hours (mAh) to decicoulombs (dC). */
convertMahToDeciCoulombs(double powerMah)762     static long convertMahToDeciCoulombs(double powerMah) {
763         return (long) (powerMah * (10 * 3600 / 1000) + 0.5);
764     }
765 
766     static class BatteryConsumerData {
767         private final CursorWindow mCursorWindow;
768         private final int mCursorRow;
769         public final BatteryConsumerDataLayout layout;
770 
BatteryConsumerData(CursorWindow cursorWindow, int cursorRow, BatteryConsumerDataLayout layout)771         BatteryConsumerData(CursorWindow cursorWindow, int cursorRow,
772                 BatteryConsumerDataLayout layout) {
773             mCursorWindow = cursorWindow;
774             mCursorRow = cursorRow;
775             this.layout = layout;
776         }
777 
778         @Nullable
create(CursorWindow cursorWindow, BatteryConsumerDataLayout layout)779         static BatteryConsumerData create(CursorWindow cursorWindow,
780                 BatteryConsumerDataLayout layout) {
781             int cursorRow = cursorWindow.getNumRows();
782             if (!cursorWindow.allocRow()) {
783                 Slog.e(TAG, "Cannot allocate BatteryConsumerData: too many UIDs: " + cursorRow);
784                 cursorRow = -1;
785             }
786             return new BatteryConsumerData(cursorWindow, cursorRow, layout);
787         }
788 
hasValue(int columnIndex)789         boolean hasValue(int columnIndex) {
790             if (mCursorRow == -1) {
791                 return false;
792             }
793             return mCursorWindow.getType(mCursorRow, columnIndex) != Cursor.FIELD_TYPE_NULL;
794         }
795 
putInt(int columnIndex, int value)796         void putInt(int columnIndex, int value) {
797             if (mCursorRow == -1) {
798                 return;
799             }
800             mCursorWindow.putLong(value, mCursorRow, columnIndex);
801         }
802 
getInt(int columnIndex)803         int getInt(int columnIndex) {
804             if (mCursorRow == -1) {
805                 return 0;
806             }
807             return mCursorWindow.getInt(mCursorRow, columnIndex);
808         }
809 
putDouble(int columnIndex, double value)810         void putDouble(int columnIndex, double value) {
811             if (mCursorRow == -1) {
812                 return;
813             }
814             mCursorWindow.putDouble(value, mCursorRow, columnIndex);
815         }
816 
getDouble(int columnIndex)817         double getDouble(int columnIndex) {
818             if (mCursorRow == -1) {
819                 return 0;
820             }
821             return mCursorWindow.getDouble(mCursorRow, columnIndex);
822         }
823 
putLong(int columnIndex, long value)824         void putLong(int columnIndex, long value) {
825             if (mCursorRow == -1) {
826                 return;
827             }
828             mCursorWindow.putLong(value, mCursorRow, columnIndex);
829         }
830 
getLong(int columnIndex)831         long getLong(int columnIndex) {
832             if (mCursorRow == -1) {
833                 return 0;
834             }
835             return mCursorWindow.getLong(mCursorRow, columnIndex);
836         }
837 
putString(int columnIndex, String value)838         void putString(int columnIndex, String value) {
839             if (mCursorRow == -1) {
840                 return;
841             }
842             mCursorWindow.putString(value, mCursorRow, columnIndex);
843         }
844 
getString(int columnIndex)845         String getString(int columnIndex) {
846             if (mCursorRow == -1) {
847                 return null;
848             }
849             return mCursorWindow.getString(mCursorRow, columnIndex);
850         }
851     }
852 
853     static class BatteryConsumerDataLayout {
854         private static final Key[] KEY_ARRAY = new Key[0];
855         public final String[] customPowerComponentNames;
856         public final int customPowerComponentCount;
857         public final boolean processStateDataIncluded;
858         public final boolean screenStateDataIncluded;
859         public final boolean powerStateDataIncluded;
860         public final @PowerComponentId int[] powerComponentIds;
861         public final Key[] keys;
862         public final SparseArray<Key> indexedKeys;
863         public final int totalConsumedPowerColumnIndex;
864         public final int columnCount;
865         private SparseArray<Key[]> mPerComponentKeys;
866 
BatteryConsumerDataLayout(int firstColumn, String[] customPowerComponentNames, boolean includeProcessStateData, boolean includeScreenState, boolean includePowerState)867         private BatteryConsumerDataLayout(int firstColumn, String[] customPowerComponentNames,
868                 boolean includeProcessStateData, boolean includeScreenState,
869                 boolean includePowerState) {
870             this.customPowerComponentNames = customPowerComponentNames;
871             this.customPowerComponentCount = customPowerComponentNames.length;
872             this.processStateDataIncluded = includeProcessStateData;
873             this.screenStateDataIncluded = includeScreenState;
874             this.powerStateDataIncluded = includePowerState;
875 
876             powerComponentIds = new int[POWER_COMPONENT_COUNT + customPowerComponentCount];
877             int id = 0;
878             for (int componentId = 0; componentId < POWER_COMPONENT_COUNT; componentId++) {
879                 powerComponentIds[id++] = componentId;
880             }
881             for (int i = 0; i < customPowerComponentCount; i++) {
882                 powerComponentIds[id++] = FIRST_CUSTOM_POWER_COMPONENT_ID + i;
883             }
884 
885             int columnIndex = firstColumn;
886 
887             totalConsumedPowerColumnIndex = columnIndex++;
888 
889             ArrayList<Key> keyList = new ArrayList<>();
890             for (int screenState = 0; screenState < SCREEN_STATE_COUNT; screenState++) {
891                 if (!includeScreenState && screenState != SCREEN_STATE_UNSPECIFIED) {
892                     continue;
893                 }
894                 for (int powerState = 0; powerState < POWER_STATE_COUNT; powerState++) {
895                     if (!includePowerState && powerState != POWER_STATE_UNSPECIFIED) {
896                         continue;
897                     }
898                     for (int i = 0; i < powerComponentIds.length; i++) {
899                         columnIndex = addKeys(keyList, includeProcessStateData,
900                                 powerComponentIds[i], screenState, powerState, columnIndex);
901                     }
902                 }
903             }
904 
905             columnCount = columnIndex;
906 
907             keys = keyList.toArray(KEY_ARRAY);
908             indexedKeys = new SparseArray<>(keys.length);
909             for (int i = 0; i < keys.length; i++) {
910                 Key key = keys[i];
911                 indexedKeys.put(keyIndex(key.powerComponentId, key.processState, key.screenState,
912                         key.powerState), key);
913             }
914         }
915 
getPowerComponentName(@owerComponentId int powerComponentId)916         public String getPowerComponentName(@PowerComponentId int powerComponentId) {
917             if (powerComponentId < POWER_COMPONENT_COUNT) {
918                 return BatteryConsumer.powerComponentIdToString(powerComponentId);
919             } else if (powerComponentId >= FIRST_CUSTOM_POWER_COMPONENT_ID && powerComponentId
920                     < FIRST_CUSTOM_POWER_COMPONENT_ID + customPowerComponentCount) {
921                 return customPowerComponentNames[powerComponentId
922                         - FIRST_CUSTOM_POWER_COMPONENT_ID];
923             } else {
924                 throw new IllegalArgumentException(
925                         "Unsupported power component " + powerComponentId);
926             }
927         }
928 
addKeys(List<Key> keys, boolean includeProcessStateData, @PowerComponentId int componentId, int screenState, int powerState, int columnIndex)929         private int addKeys(List<Key> keys, boolean includeProcessStateData,
930                 @PowerComponentId int componentId, int screenState, int powerState,
931                 int columnIndex) {
932             keys.add(new Key(componentId, PROCESS_STATE_UNSPECIFIED, screenState, powerState,
933                     columnIndex++,      // power
934                     columnIndex++       // usage duration
935             ));
936 
937             // Declare Keys for all process states, if needed
938             if (includeProcessStateData || componentId == POWER_COMPONENT_BASE) {
939                 boolean isSupported = SUPPORTED_POWER_COMPONENTS_PER_PROCESS_STATE
940                         .binarySearch(componentId) >= 0
941                         || componentId >= FIRST_CUSTOM_POWER_COMPONENT_ID;
942                 if (isSupported) {
943                     for (int processState = 0; processState < PROCESS_STATE_COUNT; processState++) {
944                         if (processState == PROCESS_STATE_UNSPECIFIED) { // Already added above
945                             continue;
946                         }
947                         keys.add(new Key(componentId, processState, screenState, powerState,
948                                 columnIndex++,      // power
949                                 columnIndex++       // usage duration
950                         ));
951                     }
952                 }
953             }
954             return columnIndex;
955         }
956 
getKey(@owerComponentId int componentId, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState)957         Key getKey(@PowerComponentId int componentId, @ProcessState int processState,
958                 @ScreenState int screenState, @PowerState int powerState) {
959             return indexedKeys.get(keyIndex(componentId, processState, screenState, powerState));
960         }
961 
getKeyOrThrow(@owerComponentId int componentId, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState)962         Key getKeyOrThrow(@PowerComponentId int componentId, @ProcessState int processState,
963                 @ScreenState int screenState, @PowerState int powerState) {
964             Key key = getKey(componentId, processState, screenState, powerState);
965             if (key == null) {
966                 throw new IllegalArgumentException(
967                         "Unsupported power component ID: " + Key.toString(componentId, processState,
968                                 screenState, powerState));
969             }
970             return key;
971         }
972 
getKeys(@owerComponentId int componentId)973         public Key[] getKeys(@PowerComponentId int componentId) {
974             synchronized (this) {
975                 if (mPerComponentKeys == null) {
976                     mPerComponentKeys = new SparseArray<>(powerComponentIds.length);
977                 }
978                 Key[] componentKeys = mPerComponentKeys.get(componentId);
979                 if (componentKeys == null) {
980                     ArrayList<Key> out = new ArrayList<>();
981                     for (Key key : keys) {
982                         if (key.powerComponentId == componentId) {
983                             out.add(key);
984                         }
985                     }
986                     componentKeys = out.toArray(new Key[out.size()]);
987                     mPerComponentKeys.put(componentId, componentKeys);
988                 }
989                 return componentKeys;
990             }
991         }
992 
keyIndex(@owerComponent int componentId, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState)993         private int keyIndex(@PowerComponent int componentId, @ProcessState int processState,
994                 @ScreenState int screenState, @PowerState int powerState) {
995             // [CCCCCCPPPSSBB]
996             // C - component ID
997             // P - process state
998             // S - screen state
999             // B - power state
1000             return componentId << 7 | processState << 4 | screenState << 2 | powerState;
1001         }
1002     }
1003 
createBatteryConsumerDataLayout( String[] customPowerComponentNames, boolean includeProcessStateData, boolean includeScreenStateData, boolean includePowerStateData)1004     static BatteryConsumerDataLayout createBatteryConsumerDataLayout(
1005             String[] customPowerComponentNames,
1006             boolean includeProcessStateData, boolean includeScreenStateData,
1007             boolean includePowerStateData) {
1008         int columnCount = BatteryConsumer.COLUMN_COUNT;
1009         columnCount = Math.max(columnCount, AggregateBatteryConsumer.COLUMN_COUNT);
1010         columnCount = Math.max(columnCount, UidBatteryConsumer.COLUMN_COUNT);
1011         columnCount = Math.max(columnCount, UserBatteryConsumer.COLUMN_COUNT);
1012 
1013         return new BatteryConsumerDataLayout(columnCount, customPowerComponentNames,
1014                 includeProcessStateData, includeScreenStateData, includePowerStateData);
1015     }
1016 
1017     protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
1018         protected final BatteryConsumer.BatteryConsumerData mData;
1019         protected final PowerComponents.Builder mPowerComponentsBuilder;
1020 
BaseBuilder(BatteryConsumer.BatteryConsumerData data, int consumerType, double minConsumedPowerThreshold)1021         public BaseBuilder(BatteryConsumer.BatteryConsumerData data, int consumerType,
1022                 double minConsumedPowerThreshold) {
1023             mData = data;
1024             data.putLong(COLUMN_INDEX_BATTERY_CONSUMER_TYPE, consumerType);
1025 
1026             mPowerComponentsBuilder = new PowerComponents.Builder(data, minConsumedPowerThreshold);
1027         }
1028 
1029         @Nullable
getKeys(@owerComponentId int componentId)1030         public Key[] getKeys(@PowerComponentId int componentId) {
1031             return mData.layout.getKeys(componentId);
1032         }
1033 
1034         @Nullable
getKey(@owerComponentId int componentId, @ProcessState int processState)1035         public Key getKey(@PowerComponentId int componentId, @ProcessState int processState) {
1036             return mData.layout.getKey(componentId, processState, SCREEN_STATE_UNSPECIFIED,
1037                     POWER_STATE_UNSPECIFIED);
1038         }
1039 
1040         @Nullable
getKey(@owerComponentId int componentId, @ProcessState int processState, @ScreenState int screenState, @PowerState int powerState)1041         public Key getKey(@PowerComponentId int componentId, @ProcessState int processState,
1042                 @ScreenState int screenState, @PowerState int powerState) {
1043             return mData.layout.getKey(componentId, processState, screenState, powerState);
1044         }
1045 
1046         /**
1047          * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
1048          *
1049          * @param componentId    The ID of the power component, e.g.
1050          *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
1051          * @param componentPower Amount of consumed power in mAh.
1052          * @deprecated use {@link #addConsumedPower}
1053          */
1054         @Deprecated
1055         @NonNull
setConsumedPower(@owerComponentId int componentId, double componentPower)1056         public T setConsumedPower(@PowerComponentId int componentId, double componentPower) {
1057             return setConsumedPower(componentId, componentPower, POWER_MODEL_POWER_PROFILE);
1058         }
1059 
1060         /**
1061          * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
1062          *
1063          * @param componentId    The ID of the power component, e.g.
1064          *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
1065          * @param componentPower Amount of consumed power in mAh.
1066          * @deprecated use {@link #addConsumedPower}
1067          */
1068         @Deprecated
1069         @SuppressWarnings("unchecked")
1070         @NonNull
setConsumedPower(@owerComponentId int componentId, double componentPower, @PowerModel int powerModel)1071         public T setConsumedPower(@PowerComponentId int componentId, double componentPower,
1072                 @PowerModel int powerModel) {
1073             mPowerComponentsBuilder.setConsumedPower(getKey(componentId, PROCESS_STATE_UNSPECIFIED),
1074                     componentPower);
1075             return (T) this;
1076         }
1077 
1078         @SuppressWarnings("unchecked")
1079         @NonNull
addConsumedPower(@owerComponentId int componentId, double componentPower, @PowerModel int powerModel)1080         public T addConsumedPower(@PowerComponentId int componentId, double componentPower,
1081                 @PowerModel int powerModel) {
1082             mPowerComponentsBuilder.addConsumedPower(getKey(componentId, PROCESS_STATE_UNSPECIFIED),
1083                     componentPower);
1084             return (T) this;
1085         }
1086 
1087         @SuppressWarnings("unchecked")
1088         @NonNull
setConsumedPower(Key key, double componentPower, @PowerModel int powerModel)1089         public T setConsumedPower(Key key, double componentPower, @PowerModel int powerModel) {
1090             mPowerComponentsBuilder.setConsumedPower(key, componentPower);
1091             return (T) this;
1092         }
1093 
1094         @SuppressWarnings("unchecked")
1095         @NonNull
addConsumedPower(@owerComponentId int componentId, double componentPower)1096         public T addConsumedPower(@PowerComponentId int componentId, double componentPower) {
1097             mPowerComponentsBuilder.addConsumedPower(getKey(componentId, PROCESS_STATE_UNSPECIFIED),
1098                     componentPower);
1099             return (T) this;
1100         }
1101 
1102         @SuppressWarnings("unchecked")
1103         @NonNull
addConsumedPower(Key key, double componentPower)1104         public T addConsumedPower(Key key, double componentPower) {
1105             mPowerComponentsBuilder.addConsumedPower(key, componentPower);
1106             return (T) this;
1107         }
1108 
1109         /**
1110          * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
1111          *
1112          * @param componentId              The ID of the power component, e.g.
1113          *                                 {@link UidBatteryConsumer#POWER_COMPONENT_CPU}.
1114          * @param componentUsageTimeMillis Amount of time in microseconds.
1115          * @deprecated use {@link #addUsageDurationMillis}
1116          */
1117         @Deprecated
1118         @SuppressWarnings("unchecked")
1119         @NonNull
setUsageDurationMillis(@owerComponentId int componentId, long componentUsageTimeMillis)1120         public T setUsageDurationMillis(@PowerComponentId int componentId,
1121                 long componentUsageTimeMillis) {
1122             mPowerComponentsBuilder
1123                     .setUsageDurationMillis(getKey(componentId, PROCESS_STATE_UNSPECIFIED),
1124                             componentUsageTimeMillis);
1125             return (T) this;
1126         }
1127 
1128         @Deprecated
1129         @SuppressWarnings("unchecked")
1130         @NonNull
setUsageDurationMillis(Key key, long componentUsageTimeMillis)1131         public T setUsageDurationMillis(Key key, long componentUsageTimeMillis) {
1132             mPowerComponentsBuilder.setUsageDurationMillis(key, componentUsageTimeMillis);
1133             return (T) this;
1134         }
1135 
1136         @NonNull
addUsageDurationMillis(@owerComponentId int componentId, long componentUsageTimeMillis)1137         public T addUsageDurationMillis(@PowerComponentId int componentId,
1138                 long componentUsageTimeMillis) {
1139             mPowerComponentsBuilder.addUsageDurationMillis(
1140                     getKey(componentId, PROCESS_STATE_UNSPECIFIED), componentUsageTimeMillis);
1141             return (T) this;
1142         }
1143 
1144         @SuppressWarnings("unchecked")
1145         @NonNull
addUsageDurationMillis(Key key, long componentUsageTimeMillis)1146         public T addUsageDurationMillis(Key key, long componentUsageTimeMillis) {
1147             mPowerComponentsBuilder.addUsageDurationMillis(key, componentUsageTimeMillis);
1148             return (T) this;
1149         }
1150 
1151         /**
1152          * Returns the total power accumulated by this builder so far. It may change
1153          * by the time the {@code build()} method is called.
1154          */
getTotalPower()1155         public double getTotalPower() {
1156             return mPowerComponentsBuilder.getTotalPower();
1157         }
1158     }
1159 }
1160