1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.os; 18 19 20 import android.annotation.StringDef; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.Context; 23 import android.content.res.Resources; 24 import android.content.res.XmlResourceParser; 25 import android.util.Slog; 26 import android.util.proto.ProtoOutputStream; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.internal.util.XmlUtils; 30 31 import org.xmlpull.v1.XmlPullParser; 32 import org.xmlpull.v1.XmlPullParserException; 33 34 import java.io.IOException; 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.util.ArrayList; 38 import java.util.HashMap; 39 40 /** 41 * Reports power consumption values for various device activities. Reads values from an XML file. 42 * Customize the XML file for different devices. 43 * [hidden] 44 */ 45 public class PowerProfile { 46 47 public static final String TAG = "PowerProfile"; 48 49 /* 50 * POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode. 51 * POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should 52 * be zero on devices that can go into full CPU power collapse even when a wake 53 * lock is held. Otherwise, this is the power consumption in addition to 54 * POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity. 55 * POWER_CPU_ACTIVE: Power consumption when CPU is running, excluding power consumed by clusters 56 * and cores. 57 * 58 * CPU Power Equation (assume two clusters): 59 * Total power = POWER_CPU_SUSPEND (always added) 60 * + POWER_CPU_IDLE (skip this and below if in power collapse mode) 61 * + POWER_CPU_ACTIVE (skip this and below if CPU is not running, but a wakelock 62 * is held) 63 * + cluster_power.cluster0 + cluster_power.cluster1 (skip cluster not running) 64 * + core_power.cluster0 * num running cores in cluster 0 65 * + core_power.cluster1 * num running cores in cluster 1 66 */ 67 public static final String POWER_CPU_SUSPEND = "cpu.suspend"; 68 @UnsupportedAppUsage 69 public static final String POWER_CPU_IDLE = "cpu.idle"; 70 @UnsupportedAppUsage 71 public static final String POWER_CPU_ACTIVE = "cpu.active"; 72 73 /** 74 * Power consumption when WiFi driver is scanning for networks. 75 */ 76 @UnsupportedAppUsage 77 public static final String POWER_WIFI_SCAN = "wifi.scan"; 78 79 /** 80 * Power consumption when WiFi driver is on. 81 */ 82 @UnsupportedAppUsage 83 public static final String POWER_WIFI_ON = "wifi.on"; 84 85 /** 86 * Power consumption when WiFi driver is transmitting/receiving. 87 */ 88 @UnsupportedAppUsage 89 public static final String POWER_WIFI_ACTIVE = "wifi.active"; 90 91 // 92 // Updated power constants. These are not estimated, they are real world 93 // currents and voltages for the underlying bluetooth and wifi controllers. 94 // 95 public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle"; 96 public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx"; 97 public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx"; 98 public static final String POWER_WIFI_CONTROLLER_TX_LEVELS = "wifi.controller.tx_levels"; 99 public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage"; 100 101 public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle"; 102 public static final String POWER_BLUETOOTH_CONTROLLER_RX = "bluetooth.controller.rx"; 103 public static final String POWER_BLUETOOTH_CONTROLLER_TX = "bluetooth.controller.tx"; 104 public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE = 105 "bluetooth.controller.voltage"; 106 107 public static final String POWER_MODEM_CONTROLLER_SLEEP = "modem.controller.sleep"; 108 public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle"; 109 public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx"; 110 public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx"; 111 public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE = 112 "modem.controller.voltage"; 113 114 /** 115 * Power consumption when GPS is on. 116 */ 117 @UnsupportedAppUsage 118 public static final String POWER_GPS_ON = "gps.on"; 119 120 /** 121 * GPS power parameters based on signal quality 122 */ 123 public static final String POWER_GPS_SIGNAL_QUALITY_BASED = "gps.signalqualitybased"; 124 public static final String POWER_GPS_OPERATING_VOLTAGE = "gps.voltage"; 125 126 /** 127 * Power consumption when Bluetooth driver is on. 128 * 129 * @deprecated 130 */ 131 @Deprecated 132 @UnsupportedAppUsage 133 public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; 134 135 /** 136 * Power consumption when Bluetooth driver is transmitting/receiving. 137 * 138 * @deprecated 139 */ 140 @Deprecated 141 public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; 142 143 /** 144 * Power consumption when Bluetooth driver gets an AT command. 145 * 146 * @deprecated 147 */ 148 @Deprecated 149 @UnsupportedAppUsage 150 public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; 151 152 /** 153 * Power consumption when screen is in doze/ambient/always-on mode, including backlight power. 154 * 155 * @deprecated Use {@link #POWER_GROUP_DISPLAY_AMBIENT} instead. 156 */ 157 @Deprecated 158 public static final String POWER_AMBIENT_DISPLAY = "ambient.on"; 159 160 /** 161 * Power consumption when screen is on, not including the backlight power. 162 * 163 * @deprecated Use {@link #POWER_GROUP_DISPLAY_SCREEN_ON} instead. 164 */ 165 @Deprecated 166 @UnsupportedAppUsage 167 public static final String POWER_SCREEN_ON = "screen.on"; 168 169 /** 170 * Power consumption when cell radio is on but not on a call. 171 */ 172 @UnsupportedAppUsage 173 public static final String POWER_RADIO_ON = "radio.on"; 174 175 /** 176 * Power consumption when cell radio is hunting for a signal. 177 */ 178 @UnsupportedAppUsage 179 public static final String POWER_RADIO_SCANNING = "radio.scanning"; 180 181 /** 182 * Power consumption when talking on the phone. 183 */ 184 @UnsupportedAppUsage 185 public static final String POWER_RADIO_ACTIVE = "radio.active"; 186 187 /** 188 * Power consumption at full backlight brightness. If the backlight is at 189 * 50% brightness, then this should be multiplied by 0.5 190 * 191 * @deprecated Use {@link #POWER_GROUP_DISPLAY_SCREEN_FULL} instead. 192 */ 193 @Deprecated 194 @UnsupportedAppUsage 195 public static final String POWER_SCREEN_FULL = "screen.full"; 196 197 /** 198 * Power consumed by the audio hardware when playing back audio content. This is in addition 199 * to the CPU power, probably due to a DSP and / or amplifier. 200 */ 201 public static final String POWER_AUDIO = "audio"; 202 203 /** 204 * Power consumed by any media hardware when playing back video content. This is in addition 205 * to the CPU power, probably due to a DSP. 206 */ 207 public static final String POWER_VIDEO = "video"; 208 209 /** 210 * Average power consumption when camera flashlight is on. 211 */ 212 public static final String POWER_FLASHLIGHT = "camera.flashlight"; 213 214 /** 215 * Power consumption when DDR is being used. 216 */ 217 public static final String POWER_MEMORY = "memory.bandwidths"; 218 219 /** 220 * Average power consumption when the camera is on over all standard use cases. 221 * 222 * TODO: Add more fine-grained camera power metrics. 223 */ 224 public static final String POWER_CAMERA = "camera.avg"; 225 226 /** 227 * Power consumed by wif batched scaning. Broken down into bins by 228 * Channels Scanned per Hour. May do 1-720 scans per hour of 1-100 channels 229 * for a range of 1-72,000. Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)! 230 */ 231 public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan"; 232 233 /** 234 * Battery capacity in milliAmpHour (mAh). 235 */ 236 public static final String POWER_BATTERY_CAPACITY = "battery.capacity"; 237 238 /** 239 * Power consumption when a screen is in doze/ambient/always-on mode, including backlight power. 240 */ 241 public static final String POWER_GROUP_DISPLAY_AMBIENT = "ambient.on.display"; 242 243 /** 244 * Power consumption when a screen is on, not including the backlight power. 245 */ 246 public static final String POWER_GROUP_DISPLAY_SCREEN_ON = "screen.on.display"; 247 248 /** 249 * Power consumption of a screen at full backlight brightness. 250 */ 251 public static final String POWER_GROUP_DISPLAY_SCREEN_FULL = "screen.full.display"; 252 253 @StringDef(prefix = { "POWER_GROUP_" }, value = { 254 POWER_GROUP_DISPLAY_AMBIENT, 255 POWER_GROUP_DISPLAY_SCREEN_ON, 256 POWER_GROUP_DISPLAY_SCREEN_FULL, 257 }) 258 @Retention(RetentionPolicy.SOURCE) 259 public @interface PowerGroup {} 260 261 /** 262 * A map from Power Use Item to its power consumption. 263 */ 264 static final HashMap<String, Double> sPowerItemMap = new HashMap<>(); 265 /** 266 * A map from Power Use Item to an array of its power consumption 267 * (for items with variable power e.g. CPU). 268 */ 269 static final HashMap<String, Double[]> sPowerArrayMap = new HashMap<>(); 270 271 private static final String TAG_DEVICE = "device"; 272 private static final String TAG_ITEM = "item"; 273 private static final String TAG_ARRAY = "array"; 274 private static final String TAG_ARRAYITEM = "value"; 275 private static final String ATTR_NAME = "name"; 276 277 private static final Object sLock = new Object(); 278 279 @VisibleForTesting 280 @UnsupportedAppUsage PowerProfile(Context context)281 public PowerProfile(Context context) { 282 this(context, false); 283 } 284 285 /** 286 * For PowerProfileTest 287 */ 288 @VisibleForTesting PowerProfile(Context context, boolean forTest)289 public PowerProfile(Context context, boolean forTest) { 290 // Read the XML file for the given profile (normally only one per device) 291 synchronized (sLock) { 292 if (sPowerItemMap.size() == 0 && sPowerArrayMap.size() == 0) { 293 readPowerValuesFromXml(context, forTest); 294 } 295 initCpuClusters(); 296 initDisplays(); 297 } 298 } 299 readPowerValuesFromXml(Context context, boolean forTest)300 private void readPowerValuesFromXml(Context context, boolean forTest) { 301 final int id = forTest ? com.android.internal.R.xml.power_profile_test : 302 com.android.internal.R.xml.power_profile; 303 final Resources resources = context.getResources(); 304 XmlResourceParser parser = resources.getXml(id); 305 boolean parsingArray = false; 306 ArrayList<Double> array = new ArrayList<>(); 307 String arrayName = null; 308 309 try { 310 XmlUtils.beginDocument(parser, TAG_DEVICE); 311 312 while (true) { 313 XmlUtils.nextElement(parser); 314 315 String element = parser.getName(); 316 if (element == null) break; 317 318 if (parsingArray && !element.equals(TAG_ARRAYITEM)) { 319 // Finish array 320 sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()])); 321 parsingArray = false; 322 } 323 if (element.equals(TAG_ARRAY)) { 324 parsingArray = true; 325 array.clear(); 326 arrayName = parser.getAttributeValue(null, ATTR_NAME); 327 } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) { 328 String name = null; 329 if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME); 330 if (parser.next() == XmlPullParser.TEXT) { 331 String power = parser.getText(); 332 double value = 0; 333 try { 334 value = Double.valueOf(power); 335 } catch (NumberFormatException nfe) { 336 } 337 if (element.equals(TAG_ITEM)) { 338 sPowerItemMap.put(name, value); 339 } else if (parsingArray) { 340 array.add(value); 341 } 342 } 343 } 344 } 345 if (parsingArray) { 346 sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()])); 347 } 348 } catch (XmlPullParserException e) { 349 throw new RuntimeException(e); 350 } catch (IOException e) { 351 throw new RuntimeException(e); 352 } finally { 353 parser.close(); 354 } 355 356 // Now collect other config variables. 357 int[] configResIds = new int[]{ 358 com.android.internal.R.integer.config_bluetooth_idle_cur_ma, 359 com.android.internal.R.integer.config_bluetooth_rx_cur_ma, 360 com.android.internal.R.integer.config_bluetooth_tx_cur_ma, 361 com.android.internal.R.integer.config_bluetooth_operating_voltage_mv, 362 }; 363 364 String[] configResIdKeys = new String[]{ 365 POWER_BLUETOOTH_CONTROLLER_IDLE, 366 POWER_BLUETOOTH_CONTROLLER_RX, 367 POWER_BLUETOOTH_CONTROLLER_TX, 368 POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, 369 }; 370 371 for (int i = 0; i < configResIds.length; i++) { 372 String key = configResIdKeys[i]; 373 // if we already have some of these parameters in power_profile.xml, ignore the 374 // value in config.xml 375 if ((sPowerItemMap.containsKey(key) && sPowerItemMap.get(key) > 0)) { 376 continue; 377 } 378 int value = resources.getInteger(configResIds[i]); 379 if (value > 0) { 380 sPowerItemMap.put(key, (double) value); 381 } 382 } 383 } 384 385 private CpuClusterKey[] mCpuClusters; 386 387 private static final String CPU_PER_CLUSTER_CORE_COUNT = "cpu.clusters.cores"; 388 private static final String CPU_CLUSTER_POWER_COUNT = "cpu.cluster_power.cluster"; 389 private static final String CPU_CORE_SPEED_PREFIX = "cpu.core_speeds.cluster"; 390 private static final String CPU_CORE_POWER_PREFIX = "cpu.core_power.cluster"; 391 initCpuClusters()392 private void initCpuClusters() { 393 if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) { 394 final Double[] data = sPowerArrayMap.get(CPU_PER_CLUSTER_CORE_COUNT); 395 mCpuClusters = new CpuClusterKey[data.length]; 396 for (int cluster = 0; cluster < data.length; cluster++) { 397 int numCpusInCluster = (int) Math.round(data[cluster]); 398 mCpuClusters[cluster] = new CpuClusterKey( 399 CPU_CORE_SPEED_PREFIX + cluster, CPU_CLUSTER_POWER_COUNT + cluster, 400 CPU_CORE_POWER_PREFIX + cluster, numCpusInCluster); 401 } 402 } else { 403 // Default to single. 404 mCpuClusters = new CpuClusterKey[1]; 405 int numCpus = 1; 406 if (sPowerItemMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) { 407 numCpus = (int) Math.round(sPowerItemMap.get(CPU_PER_CLUSTER_CORE_COUNT)); 408 } 409 mCpuClusters[0] = new CpuClusterKey(CPU_CORE_SPEED_PREFIX + 0, 410 CPU_CLUSTER_POWER_COUNT + 0, CPU_CORE_POWER_PREFIX + 0, numCpus); 411 } 412 } 413 414 public static class CpuClusterKey { 415 private final String freqKey; 416 private final String clusterPowerKey; 417 private final String corePowerKey; 418 private final int numCpus; 419 CpuClusterKey(String freqKey, String clusterPowerKey, String corePowerKey, int numCpus)420 private CpuClusterKey(String freqKey, String clusterPowerKey, 421 String corePowerKey, int numCpus) { 422 this.freqKey = freqKey; 423 this.clusterPowerKey = clusterPowerKey; 424 this.corePowerKey = corePowerKey; 425 this.numCpus = numCpus; 426 } 427 } 428 429 @UnsupportedAppUsage getNumCpuClusters()430 public int getNumCpuClusters() { 431 return mCpuClusters.length; 432 } 433 getNumCoresInCpuCluster(int cluster)434 public int getNumCoresInCpuCluster(int cluster) { 435 if (cluster < 0 || cluster >= mCpuClusters.length) { 436 return 0; // index out of bound 437 } 438 return mCpuClusters[cluster].numCpus; 439 } 440 441 @UnsupportedAppUsage getNumSpeedStepsInCpuCluster(int cluster)442 public int getNumSpeedStepsInCpuCluster(int cluster) { 443 if (cluster < 0 || cluster >= mCpuClusters.length) { 444 return 0; // index out of bound 445 } 446 if (sPowerArrayMap.containsKey(mCpuClusters[cluster].freqKey)) { 447 return sPowerArrayMap.get(mCpuClusters[cluster].freqKey).length; 448 } 449 return 1; // Only one speed 450 } 451 getAveragePowerForCpuCluster(int cluster)452 public double getAveragePowerForCpuCluster(int cluster) { 453 if (cluster >= 0 && cluster < mCpuClusters.length) { 454 return getAveragePower(mCpuClusters[cluster].clusterPowerKey); 455 } 456 return 0; 457 } 458 getAveragePowerForCpuCore(int cluster, int step)459 public double getAveragePowerForCpuCore(int cluster, int step) { 460 if (cluster >= 0 && cluster < mCpuClusters.length) { 461 return getAveragePower(mCpuClusters[cluster].corePowerKey, step); 462 } 463 return 0; 464 } 465 466 private int mNumDisplays; 467 initDisplays()468 private void initDisplays() { 469 // Figure out how many displays are listed in the power profile. 470 mNumDisplays = 0; 471 while (!Double.isNaN( 472 getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, mNumDisplays, Double.NaN)) 473 || !Double.isNaN( 474 getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, mNumDisplays, Double.NaN)) 475 || !Double.isNaN( 476 getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, mNumDisplays, 477 Double.NaN))) { 478 mNumDisplays++; 479 } 480 481 // Handle legacy display power constants. 482 final Double deprecatedAmbientDisplay = sPowerItemMap.get(POWER_AMBIENT_DISPLAY); 483 boolean legacy = false; 484 if (deprecatedAmbientDisplay != null && mNumDisplays == 0) { 485 final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_AMBIENT, 0); 486 Slog.w(TAG, POWER_AMBIENT_DISPLAY + " is deprecated! Use " + key + " instead."); 487 sPowerItemMap.put(key, deprecatedAmbientDisplay); 488 legacy = true; 489 } 490 491 final Double deprecatedScreenOn = sPowerItemMap.get(POWER_SCREEN_ON); 492 if (deprecatedScreenOn != null && mNumDisplays == 0) { 493 final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_SCREEN_ON, 0); 494 Slog.w(TAG, POWER_SCREEN_ON + " is deprecated! Use " + key + " instead."); 495 sPowerItemMap.put(key, deprecatedScreenOn); 496 legacy = true; 497 } 498 499 final Double deprecatedScreenFull = sPowerItemMap.get(POWER_SCREEN_FULL); 500 if (deprecatedScreenFull != null && mNumDisplays == 0) { 501 final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_SCREEN_FULL, 0); 502 Slog.w(TAG, POWER_SCREEN_FULL + " is deprecated! Use " + key + " instead."); 503 sPowerItemMap.put(key, deprecatedScreenFull); 504 legacy = true; 505 } 506 if (legacy) { 507 mNumDisplays = 1; 508 } 509 } 510 511 /** 512 * Returns the number built in displays on the device as defined in the power_profile.xml. 513 */ getNumDisplays()514 public int getNumDisplays() { 515 return mNumDisplays; 516 } 517 518 /** 519 * Returns the number of memory bandwidth buckets defined in power_profile.xml, or a 520 * default value if the subsystem has no recorded value. 521 * 522 * @return the number of memory bandwidth buckets. 523 */ getNumElements(String key)524 public int getNumElements(String key) { 525 if (sPowerItemMap.containsKey(key)) { 526 return 1; 527 } else if (sPowerArrayMap.containsKey(key)) { 528 return sPowerArrayMap.get(key).length; 529 } 530 return 0; 531 } 532 533 /** 534 * Returns the average current in mA consumed by the subsystem, or the given 535 * default value if the subsystem has no recorded value. 536 * 537 * @param type the subsystem type 538 * @param defaultValue the value to return if the subsystem has no recorded value. 539 * @return the average current in milliAmps. 540 */ getAveragePowerOrDefault(String type, double defaultValue)541 public double getAveragePowerOrDefault(String type, double defaultValue) { 542 if (sPowerItemMap.containsKey(type)) { 543 return sPowerItemMap.get(type); 544 } else if (sPowerArrayMap.containsKey(type)) { 545 return sPowerArrayMap.get(type)[0]; 546 } else { 547 return defaultValue; 548 } 549 } 550 551 /** 552 * Returns the average current in mA consumed by the subsystem 553 * 554 * @param type the subsystem type 555 * @return the average current in milliAmps. 556 */ 557 @UnsupportedAppUsage getAveragePower(String type)558 public double getAveragePower(String type) { 559 return getAveragePowerOrDefault(type, 0); 560 } 561 562 /** 563 * Returns the average current in mA consumed by the subsystem for the given level. 564 * 565 * @param type the subsystem type 566 * @param level the level of power at which the subsystem is running. For instance, the 567 * signal strength of the cell network between 0 and 4 (if there are 4 bars max.) 568 * If there is no data for multiple levels, the level is ignored. 569 * @return the average current in milliAmps. 570 */ 571 @UnsupportedAppUsage getAveragePower(String type, int level)572 public double getAveragePower(String type, int level) { 573 if (sPowerItemMap.containsKey(type)) { 574 return sPowerItemMap.get(type); 575 } else if (sPowerArrayMap.containsKey(type)) { 576 final Double[] values = sPowerArrayMap.get(type); 577 if (values.length > level && level >= 0) { 578 return values[level]; 579 } else if (level < 0 || values.length == 0) { 580 return 0; 581 } else { 582 return values[values.length - 1]; 583 } 584 } else { 585 return 0; 586 } 587 } 588 589 /** 590 * Returns the average current in mA consumed by an ordinaled subsystem, or the given 591 * default value if the subsystem has no recorded value. 592 * 593 * @param group the subsystem {@link PowerGroup}. 594 * @param ordinal which entity in the {@link PowerGroup}. 595 * @param defaultValue the value to return if the subsystem has no recorded value. 596 * @return the average current in milliAmps. 597 */ getAveragePowerForOrdinal(@owerGroup String group, int ordinal, double defaultValue)598 public double getAveragePowerForOrdinal(@PowerGroup String group, int ordinal, 599 double defaultValue) { 600 final String type = getOrdinalPowerType(group, ordinal); 601 return getAveragePowerOrDefault(type, defaultValue); 602 } 603 604 /** 605 * Returns the average current in mA consumed by an ordinaled subsystem. 606 * 607 * @param group the subsystem {@link PowerGroup}. 608 * @param ordinal which entity in the {@link PowerGroup}. 609 * @return the average current in milliAmps. 610 */ getAveragePowerForOrdinal(@owerGroup String group, int ordinal)611 public double getAveragePowerForOrdinal(@PowerGroup String group, int ordinal) { 612 return getAveragePowerForOrdinal(group, ordinal, 0); 613 } 614 615 /** 616 * Returns the battery capacity, if available, in milli Amp Hours. If not available, 617 * it returns zero. 618 * 619 * @return the battery capacity in mAh 620 */ 621 @UnsupportedAppUsage getBatteryCapacity()622 public double getBatteryCapacity() { 623 return getAveragePower(POWER_BATTERY_CAPACITY); 624 } 625 626 /** 627 * Dump power constants into PowerProfileProto 628 */ dumpDebug(ProtoOutputStream proto)629 public void dumpDebug(ProtoOutputStream proto) { 630 // cpu.suspend 631 writePowerConstantToProto(proto, POWER_CPU_SUSPEND, PowerProfileProto.CPU_SUSPEND); 632 633 // cpu.idle 634 writePowerConstantToProto(proto, POWER_CPU_IDLE, PowerProfileProto.CPU_IDLE); 635 636 // cpu.active 637 writePowerConstantToProto(proto, POWER_CPU_ACTIVE, PowerProfileProto.CPU_ACTIVE); 638 639 // cpu.clusters.cores 640 // cpu.cluster_power.cluster 641 // cpu.core_speeds.cluster 642 // cpu.core_power.cluster 643 for (int cluster = 0; cluster < mCpuClusters.length; cluster++) { 644 final long token = proto.start(PowerProfileProto.CPU_CLUSTER); 645 proto.write(PowerProfileProto.CpuCluster.ID, cluster); 646 proto.write(PowerProfileProto.CpuCluster.CLUSTER_POWER, 647 sPowerItemMap.get(mCpuClusters[cluster].clusterPowerKey)); 648 proto.write(PowerProfileProto.CpuCluster.CORES, mCpuClusters[cluster].numCpus); 649 for (Double speed : sPowerArrayMap.get(mCpuClusters[cluster].freqKey)) { 650 proto.write(PowerProfileProto.CpuCluster.SPEED, speed); 651 } 652 for (Double corePower : sPowerArrayMap.get(mCpuClusters[cluster].corePowerKey)) { 653 proto.write(PowerProfileProto.CpuCluster.CORE_POWER, corePower); 654 } 655 proto.end(token); 656 } 657 658 // wifi.scan 659 writePowerConstantToProto(proto, POWER_WIFI_SCAN, PowerProfileProto.WIFI_SCAN); 660 661 // wifi.on 662 writePowerConstantToProto(proto, POWER_WIFI_ON, PowerProfileProto.WIFI_ON); 663 664 // wifi.active 665 writePowerConstantToProto(proto, POWER_WIFI_ACTIVE, PowerProfileProto.WIFI_ACTIVE); 666 667 // wifi.controller.idle 668 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_IDLE, 669 PowerProfileProto.WIFI_CONTROLLER_IDLE); 670 671 // wifi.controller.rx 672 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_RX, 673 PowerProfileProto.WIFI_CONTROLLER_RX); 674 675 // wifi.controller.tx 676 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_TX, 677 PowerProfileProto.WIFI_CONTROLLER_TX); 678 679 // wifi.controller.tx_levels 680 writePowerConstantArrayToProto(proto, POWER_WIFI_CONTROLLER_TX_LEVELS, 681 PowerProfileProto.WIFI_CONTROLLER_TX_LEVELS); 682 683 // wifi.controller.voltage 684 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE, 685 PowerProfileProto.WIFI_CONTROLLER_OPERATING_VOLTAGE); 686 687 // bluetooth.controller.idle 688 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_IDLE, 689 PowerProfileProto.BLUETOOTH_CONTROLLER_IDLE); 690 691 // bluetooth.controller.rx 692 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_RX, 693 PowerProfileProto.BLUETOOTH_CONTROLLER_RX); 694 695 // bluetooth.controller.tx 696 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_TX, 697 PowerProfileProto.BLUETOOTH_CONTROLLER_TX); 698 699 // bluetooth.controller.voltage 700 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, 701 PowerProfileProto.BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE); 702 703 // modem.controller.sleep 704 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_SLEEP, 705 PowerProfileProto.MODEM_CONTROLLER_SLEEP); 706 707 // modem.controller.idle 708 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_IDLE, 709 PowerProfileProto.MODEM_CONTROLLER_IDLE); 710 711 // modem.controller.rx 712 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_RX, 713 PowerProfileProto.MODEM_CONTROLLER_RX); 714 715 // modem.controller.tx 716 writePowerConstantArrayToProto(proto, POWER_MODEM_CONTROLLER_TX, 717 PowerProfileProto.MODEM_CONTROLLER_TX); 718 719 // modem.controller.voltage 720 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE, 721 PowerProfileProto.MODEM_CONTROLLER_OPERATING_VOLTAGE); 722 723 // gps.on 724 writePowerConstantToProto(proto, POWER_GPS_ON, PowerProfileProto.GPS_ON); 725 726 // gps.signalqualitybased 727 writePowerConstantArrayToProto(proto, POWER_GPS_SIGNAL_QUALITY_BASED, 728 PowerProfileProto.GPS_SIGNAL_QUALITY_BASED); 729 730 // gps.voltage 731 writePowerConstantToProto(proto, POWER_GPS_OPERATING_VOLTAGE, 732 PowerProfileProto.GPS_OPERATING_VOLTAGE); 733 734 // bluetooth.on 735 writePowerConstantToProto(proto, POWER_BLUETOOTH_ON, PowerProfileProto.BLUETOOTH_ON); 736 737 // bluetooth.active 738 writePowerConstantToProto(proto, POWER_BLUETOOTH_ACTIVE, 739 PowerProfileProto.BLUETOOTH_ACTIVE); 740 741 // bluetooth.at 742 writePowerConstantToProto(proto, POWER_BLUETOOTH_AT_CMD, 743 PowerProfileProto.BLUETOOTH_AT_CMD); 744 745 // ambient.on 746 writePowerConstantToProto(proto, POWER_AMBIENT_DISPLAY, PowerProfileProto.AMBIENT_DISPLAY); 747 748 // screen.on 749 writePowerConstantToProto(proto, POWER_SCREEN_ON, PowerProfileProto.SCREEN_ON); 750 751 // radio.on 752 writePowerConstantToProto(proto, POWER_RADIO_ON, PowerProfileProto.RADIO_ON); 753 754 // radio.scanning 755 writePowerConstantToProto(proto, POWER_RADIO_SCANNING, PowerProfileProto.RADIO_SCANNING); 756 757 // radio.active 758 writePowerConstantToProto(proto, POWER_RADIO_ACTIVE, PowerProfileProto.RADIO_ACTIVE); 759 760 // screen.full 761 writePowerConstantToProto(proto, POWER_SCREEN_FULL, PowerProfileProto.SCREEN_FULL); 762 763 // audio 764 writePowerConstantToProto(proto, POWER_AUDIO, PowerProfileProto.AUDIO); 765 766 // video 767 writePowerConstantToProto(proto, POWER_VIDEO, PowerProfileProto.VIDEO); 768 769 // camera.flashlight 770 writePowerConstantToProto(proto, POWER_FLASHLIGHT, PowerProfileProto.FLASHLIGHT); 771 772 // memory.bandwidths 773 writePowerConstantToProto(proto, POWER_MEMORY, PowerProfileProto.MEMORY); 774 775 // camera.avg 776 writePowerConstantToProto(proto, POWER_CAMERA, PowerProfileProto.CAMERA); 777 778 // wifi.batchedscan 779 writePowerConstantToProto(proto, POWER_WIFI_BATCHED_SCAN, 780 PowerProfileProto.WIFI_BATCHED_SCAN); 781 782 // battery.capacity 783 writePowerConstantToProto(proto, POWER_BATTERY_CAPACITY, 784 PowerProfileProto.BATTERY_CAPACITY); 785 } 786 787 // Writes items in sPowerItemMap to proto if exists. writePowerConstantToProto(ProtoOutputStream proto, String key, long fieldId)788 private void writePowerConstantToProto(ProtoOutputStream proto, String key, long fieldId) { 789 if (sPowerItemMap.containsKey(key)) { 790 proto.write(fieldId, sPowerItemMap.get(key)); 791 } 792 } 793 794 // Writes items in sPowerArrayMap to proto if exists. writePowerConstantArrayToProto(ProtoOutputStream proto, String key, long fieldId)795 private void writePowerConstantArrayToProto(ProtoOutputStream proto, String key, long fieldId) { 796 if (sPowerArrayMap.containsKey(key)) { 797 for (Double d : sPowerArrayMap.get(key)) { 798 proto.write(fieldId, d); 799 } 800 } 801 } 802 803 // Creates the key for an ordinaled power constant from the group and ordinal. getOrdinalPowerType(@owerGroup String group, int ordinal)804 private static String getOrdinalPowerType(@PowerGroup String group, int ordinal) { 805 return group + ordinal; 806 } 807 } 808