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