• 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.util.proto.ProtoOutputStream;
23 
24 import java.io.PrintWriter;
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 
28 /**
29  * Interface for objects containing battery attribution data.
30  *
31  * @hide
32  */
33 public abstract class BatteryConsumer {
34 
35     /**
36      * Power usage component, describing the particular part of the system
37      * responsible for power drain.
38      *
39      * @hide
40      */
41     @IntDef(prefix = {"POWER_COMPONENT_"}, value = {
42             POWER_COMPONENT_SCREEN,
43             POWER_COMPONENT_CPU,
44             POWER_COMPONENT_BLUETOOTH,
45             POWER_COMPONENT_CAMERA,
46             POWER_COMPONENT_AUDIO,
47             POWER_COMPONENT_VIDEO,
48             POWER_COMPONENT_FLASHLIGHT,
49             POWER_COMPONENT_MOBILE_RADIO,
50             POWER_COMPONENT_SYSTEM_SERVICES,
51             POWER_COMPONENT_SENSORS,
52             POWER_COMPONENT_GNSS,
53             POWER_COMPONENT_WIFI,
54             POWER_COMPONENT_WAKELOCK,
55             POWER_COMPONENT_MEMORY,
56             POWER_COMPONENT_PHONE,
57             POWER_COMPONENT_IDLE,
58             POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
59     })
60     @Retention(RetentionPolicy.SOURCE)
61     public static @interface PowerComponent {
62     }
63 
64     public static final int POWER_COMPONENT_SCREEN = OsProtoEnums.POWER_COMPONENT_SCREEN; // 0
65     public static final int POWER_COMPONENT_CPU = OsProtoEnums.POWER_COMPONENT_CPU; // 1
66     public static final int POWER_COMPONENT_BLUETOOTH = OsProtoEnums.POWER_COMPONENT_BLUETOOTH; // 2
67     public static final int POWER_COMPONENT_CAMERA = OsProtoEnums.POWER_COMPONENT_CAMERA; // 3
68     public static final int POWER_COMPONENT_AUDIO = OsProtoEnums.POWER_COMPONENT_AUDIO; // 4
69     public static final int POWER_COMPONENT_VIDEO = OsProtoEnums.POWER_COMPONENT_VIDEO; // 5
70     public static final int POWER_COMPONENT_FLASHLIGHT =
71             OsProtoEnums.POWER_COMPONENT_FLASHLIGHT; // 6
72     public static final int POWER_COMPONENT_SYSTEM_SERVICES =
73             OsProtoEnums.POWER_COMPONENT_SYSTEM_SERVICES; // 7
74     public static final int POWER_COMPONENT_MOBILE_RADIO =
75             OsProtoEnums.POWER_COMPONENT_MOBILE_RADIO; // 8
76     public static final int POWER_COMPONENT_SENSORS = OsProtoEnums.POWER_COMPONENT_SENSORS; // 9
77     public static final int POWER_COMPONENT_GNSS = OsProtoEnums.POWER_COMPONENT_GNSS; // 10
78     public static final int POWER_COMPONENT_WIFI = OsProtoEnums.POWER_COMPONENT_WIFI; // 11
79     public static final int POWER_COMPONENT_WAKELOCK = OsProtoEnums.POWER_COMPONENT_WAKELOCK; // 12
80     public static final int POWER_COMPONENT_MEMORY = OsProtoEnums.POWER_COMPONENT_MEMORY; // 13
81     public static final int POWER_COMPONENT_PHONE = OsProtoEnums.POWER_COMPONENT_PHONE; // 14
82     public static final int POWER_COMPONENT_AMBIENT_DISPLAY =
83             OsProtoEnums.POWER_COMPONENT_AMBIENT_DISPLAY; // 15
84     public static final int POWER_COMPONENT_IDLE = OsProtoEnums.POWER_COMPONENT_IDLE; // 16
85     // Power that is re-attributed to other battery consumers. For example, for System Server
86     // this represents the power attributed to apps requesting system services.
87     // The value should be negative or zero.
88     public static final int POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS =
89             OsProtoEnums.POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS; // 17
90 
91     public static final int POWER_COMPONENT_COUNT = 18;
92 
93     public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
94     public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
95 
96     private static final String[] sPowerComponentNames = new String[POWER_COMPONENT_COUNT];
97 
98     static {
99         // Assign individually to avoid future mismatch
100         sPowerComponentNames[POWER_COMPONENT_SCREEN] = "screen";
101         sPowerComponentNames[POWER_COMPONENT_CPU] = "cpu";
102         sPowerComponentNames[POWER_COMPONENT_BLUETOOTH] = "bluetooth";
103         sPowerComponentNames[POWER_COMPONENT_CAMERA] = "camera";
104         sPowerComponentNames[POWER_COMPONENT_AUDIO] = "audio";
105         sPowerComponentNames[POWER_COMPONENT_VIDEO] = "video";
106         sPowerComponentNames[POWER_COMPONENT_FLASHLIGHT] = "flashlight";
107         sPowerComponentNames[POWER_COMPONENT_SYSTEM_SERVICES] = "system_services";
108         sPowerComponentNames[POWER_COMPONENT_MOBILE_RADIO] = "mobile_radio";
109         sPowerComponentNames[POWER_COMPONENT_SENSORS] = "sensors";
110         sPowerComponentNames[POWER_COMPONENT_GNSS] = "gnss";
111         sPowerComponentNames[POWER_COMPONENT_WIFI] = "wifi";
112         sPowerComponentNames[POWER_COMPONENT_WAKELOCK] = "wakelock";
113         sPowerComponentNames[POWER_COMPONENT_MEMORY] = "memory";
114         sPowerComponentNames[POWER_COMPONENT_PHONE] = "phone";
115         sPowerComponentNames[POWER_COMPONENT_AMBIENT_DISPLAY] = "ambient_display";
116         sPowerComponentNames[POWER_COMPONENT_IDLE] = "idle";
117         sPowerComponentNames[POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS] = "reattributed";
118     }
119 
120     /**
121      * Identifiers of models used for power estimation.
122      *
123      * @hide
124      */
125     @IntDef(prefix = {"POWER_MODEL_"}, value = {
126             POWER_MODEL_UNDEFINED,
127             POWER_MODEL_POWER_PROFILE,
128             POWER_MODEL_MEASURED_ENERGY,
129     })
130     @Retention(RetentionPolicy.SOURCE)
131     public @interface PowerModel {
132     }
133 
134     /**
135      * Unspecified power model.
136      */
137     public static final int POWER_MODEL_UNDEFINED = 0;
138 
139     /**
140      * Power model that is based on average consumption rates that hardware components
141      * consume in various states.
142      */
143     public static final int POWER_MODEL_POWER_PROFILE = 1;
144 
145     /**
146      * Power model that is based on energy consumption measured by on-device power monitors.
147      */
148     public static final int POWER_MODEL_MEASURED_ENERGY = 2;
149 
150     protected final PowerComponents mPowerComponents;
151 
BatteryConsumer(@onNull PowerComponents powerComponents)152     protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
153         mPowerComponents = powerComponents;
154     }
155 
156     /**
157      * Total power consumed by this consumer, in mAh.
158      */
getConsumedPower()159     public double getConsumedPower() {
160         return mPowerComponents.getConsumedPower();
161     }
162 
163     /**
164      * Returns the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
165      *
166      * @param componentId The ID of the power component, e.g.
167      *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
168      * @return Amount of consumed power in mAh.
169      */
getConsumedPower(@owerComponent int componentId)170     public double getConsumedPower(@PowerComponent int componentId) {
171         return mPowerComponents.getConsumedPower(componentId);
172     }
173 
174     /**
175      * Returns the ID of the model that was used for power estimation.
176      *
177      * @param componentId The ID of the power component, e.g.
178      *                    {@link BatteryConsumer#POWER_COMPONENT_CPU}.
179      */
getPowerModel(@atteryConsumer.PowerComponent int componentId)180     public @PowerModel int getPowerModel(@BatteryConsumer.PowerComponent int componentId) {
181         return mPowerComponents.getPowerModel(componentId);
182     }
183 
184     /**
185      * Returns the amount of drain attributed to the specified custom drain type.
186      *
187      * @param componentId The ID of the custom power component.
188      * @return Amount of consumed power in mAh.
189      */
getConsumedPowerForCustomComponent(int componentId)190     public double getConsumedPowerForCustomComponent(int componentId) {
191         return mPowerComponents.getConsumedPowerForCustomComponent(componentId);
192     }
193 
getCustomPowerComponentCount()194     public int getCustomPowerComponentCount() {
195         return mPowerComponents.getCustomPowerComponentCount();
196     }
197 
setCustomPowerComponentNames(String[] customPowerComponentNames)198     void setCustomPowerComponentNames(String[] customPowerComponentNames) {
199         mPowerComponents.setCustomPowerComponentNames(customPowerComponentNames);
200     }
201 
202     /**
203      * Returns the name of the specified power component.
204      *
205      * @param componentId The ID of the custom power component.
206      */
getCustomPowerComponentName(int componentId)207     public String getCustomPowerComponentName(int componentId) {
208         return mPowerComponents.getCustomPowerComponentName(componentId);
209     }
210 
211     /**
212      * Returns the amount of time since BatteryStats reset used by the specified component, e.g.
213      * CPU, WiFi etc.
214      *
215      * @param componentId The ID of the power component, e.g.
216      *                    {@link UidBatteryConsumer#POWER_COMPONENT_CPU}.
217      * @return Amount of time in milliseconds.
218      */
getUsageDurationMillis(@owerComponent int componentId)219     public long getUsageDurationMillis(@PowerComponent int componentId) {
220         return mPowerComponents.getUsageDurationMillis(componentId);
221     }
222 
223     /**
224      * Returns the amount of usage time attributed to the specified custom component
225      * since BatteryStats reset.
226      *
227      * @param componentId The ID of the custom power component.
228      * @return Amount of time in milliseconds.
229      */
getUsageDurationForCustomComponentMillis(int componentId)230     public long getUsageDurationForCustomComponentMillis(int componentId) {
231         return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId);
232     }
233 
writeToParcel(Parcel dest, int flags)234     protected void writeToParcel(Parcel dest, int flags) {
235         mPowerComponents.writeToParcel(dest, flags);
236     }
237 
238     /**
239      * Returns the name of the specified component.  Intended for logging and debugging.
240      */
powerComponentIdToString(@atteryConsumer.PowerComponent int componentId)241     public static String powerComponentIdToString(@BatteryConsumer.PowerComponent int componentId) {
242         return sPowerComponentNames[componentId];
243     }
244 
245     /**
246      * Returns the name of the specified power model.  Intended for logging and debugging.
247      */
powerModelToString(@atteryConsumer.PowerModel int powerModel)248     public static String powerModelToString(@BatteryConsumer.PowerModel int powerModel) {
249         switch (powerModel) {
250             case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
251                 return "measured energy";
252             case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
253                 return "power profile";
254             default:
255                 return "";
256         }
257     }
258 
259     /**
260      * Prints the stats in a human-readable format.
261      */
dump(PrintWriter pw)262     public void dump(PrintWriter pw) {
263         dump(pw, true);
264     }
265 
266     /**
267      * Prints the stats in a human-readable format.
268      *
269      * @param skipEmptyComponents if true, omit any power components with a zero amount.
270      */
dump(PrintWriter pw, boolean skipEmptyComponents)271     public abstract void dump(PrintWriter pw, boolean skipEmptyComponents);
272 
273     /** Returns whether there are any atoms.proto BATTERY_CONSUMER_DATA data to write to a proto. */
hasStatsProtoData()274     boolean hasStatsProtoData() {
275         return writeStatsProtoImpl(null, /* Irrelevant fieldId: */ 0);
276     }
277 
278     /** Writes the atoms.proto BATTERY_CONSUMER_DATA for this BatteryConsumer to the given proto. */
writeStatsProto(@onNull ProtoOutputStream proto, long fieldId)279     void writeStatsProto(@NonNull ProtoOutputStream proto, long fieldId) {
280         writeStatsProtoImpl(proto, fieldId);
281     }
282 
283     /**
284      * Returns whether there are any atoms.proto BATTERY_CONSUMER_DATA data to write to a proto,
285      * and writes it to the given proto if it is non-null.
286      */
writeStatsProtoImpl(@ullable ProtoOutputStream proto, long fieldId)287     private boolean writeStatsProtoImpl(@Nullable ProtoOutputStream proto, long fieldId) {
288         final long totalConsumedPowerDeciCoulombs = convertMahToDeciCoulombs(getConsumedPower());
289 
290         if (totalConsumedPowerDeciCoulombs == 0) {
291             // NOTE: Strictly speaking we should also check !mPowerComponents.hasStatsProtoData().
292             // However, that call is a bit expensive (a for loop). And the only way that
293             // totalConsumedPower can be 0 while mPowerComponents.hasStatsProtoData() is true is
294             // if POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS (which is the only negative
295             // allowed) happens to exactly equal the sum of all other components, which
296             // can't really happen in practice.
297             // So we'll just adopt the rule "if total==0, don't write any details".
298             // If negative values are used for other things in the future, this can be revisited.
299             return false;
300         }
301         if (proto == null) {
302             // We're just asked whether there is data, not to actually write it. And there is.
303             return true;
304         }
305 
306         final long token = proto.start(fieldId);
307         proto.write(
308                 BatteryUsageStatsAtomsProto.BatteryConsumerData.TOTAL_CONSUMED_POWER_DECI_COULOMBS,
309                 totalConsumedPowerDeciCoulombs);
310         mPowerComponents.writeStatsProto(proto);
311         proto.end(token);
312 
313         return true;
314     }
315 
316     /** Converts charge from milliamp hours (mAh) to decicoulombs (dC). */
convertMahToDeciCoulombs(double powerMah)317     static long convertMahToDeciCoulombs(double powerMah) {
318         return (long) (powerMah * (10 * 3600 / 1000) + 0.5);
319     }
320 
321     protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
322         final PowerComponents.Builder mPowerComponentsBuilder;
323 
BaseBuilder(@onNull String[] customPowerComponentNames, boolean includePowerModels)324         public BaseBuilder(@NonNull String[] customPowerComponentNames,
325                 boolean includePowerModels) {
326             mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentNames,
327                     includePowerModels);
328         }
329 
330         /**
331          * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
332          *
333          * @param componentId    The ID of the power component, e.g.
334          *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
335          * @param componentPower Amount of consumed power in mAh.
336          */
337         @NonNull
setConsumedPower(@owerComponent int componentId, double componentPower)338         public T setConsumedPower(@PowerComponent int componentId, double componentPower) {
339             return setConsumedPower(componentId, componentPower, POWER_MODEL_POWER_PROFILE);
340         }
341 
342         /**
343          * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
344          *
345          * @param componentId    The ID of the power component, e.g.
346          *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
347          * @param componentPower Amount of consumed power in mAh.
348          */
349         @SuppressWarnings("unchecked")
350         @NonNull
setConsumedPower(@owerComponent int componentId, double componentPower, @PowerModel int powerModel)351         public T setConsumedPower(@PowerComponent int componentId, double componentPower,
352                 @PowerModel int powerModel) {
353             mPowerComponentsBuilder.setConsumedPower(componentId, componentPower, powerModel);
354             return (T) this;
355         }
356 
357         /**
358          * Sets the amount of drain attributed to the specified custom drain type.
359          *
360          * @param componentId    The ID of the custom power component.
361          * @param componentPower Amount of consumed power in mAh.
362          */
363         @SuppressWarnings("unchecked")
364         @NonNull
setConsumedPowerForCustomComponent(int componentId, double componentPower)365         public T setConsumedPowerForCustomComponent(int componentId, double componentPower) {
366             mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower);
367             return (T) this;
368         }
369 
370         /**
371          * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
372          *
373          * @param componentId              The ID of the power component, e.g.
374          *                                 {@link UidBatteryConsumer#POWER_COMPONENT_CPU}.
375          * @param componentUsageTimeMillis Amount of time in microseconds.
376          */
377         @SuppressWarnings("unchecked")
378         @NonNull
setUsageDurationMillis(@idBatteryConsumer.PowerComponent int componentId, long componentUsageTimeMillis)379         public T setUsageDurationMillis(@UidBatteryConsumer.PowerComponent int componentId,
380                 long componentUsageTimeMillis) {
381             mPowerComponentsBuilder.setUsageDurationMillis(componentId, componentUsageTimeMillis);
382             return (T) this;
383         }
384 
385         /**
386          * Sets the amount of time used by the specified custom component.
387          *
388          * @param componentId              The ID of the custom power component.
389          * @param componentUsageTimeMillis Amount of time in microseconds.
390          */
391         @SuppressWarnings("unchecked")
392         @NonNull
setUsageDurationForCustomComponentMillis(int componentId, long componentUsageTimeMillis)393         public T setUsageDurationForCustomComponentMillis(int componentId,
394                 long componentUsageTimeMillis) {
395             mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId,
396                     componentUsageTimeMillis);
397             return (T) this;
398         }
399 
400         /**
401          * Returns the total power accumulated by this builder so far. It may change
402          * by the time the {@code build()} method is called.
403          */
getTotalPower()404         public double getTotalPower() {
405             return mPowerComponentsBuilder.getTotalPower();
406         }
407     }
408 }
409