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.LongDef; 21 import android.annotation.Nullable; 22 import android.annotation.StringDef; 23 import android.annotation.XmlRes; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.content.Context; 26 import android.content.res.Resources; 27 import android.content.res.XmlResourceParser; 28 import android.util.IndentingPrintWriter; 29 import android.util.Slog; 30 import android.util.SparseArray; 31 import android.util.proto.ProtoOutputStream; 32 33 import com.android.internal.annotations.GuardedBy; 34 import com.android.internal.annotations.VisibleForTesting; 35 import com.android.internal.power.ModemPowerProfile; 36 import com.android.internal.util.XmlUtils; 37 38 import org.xmlpull.v1.XmlPullParser; 39 import org.xmlpull.v1.XmlPullParserException; 40 41 import java.io.IOException; 42 import java.io.PrintWriter; 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 import java.util.ArrayList; 46 import java.util.Arrays; 47 import java.util.HashMap; 48 49 /** 50 * Reports power consumption values for various device activities. Reads values from an XML file. 51 * Customize the XML file for different devices. 52 * [hidden] 53 */ 54 @android.ravenwood.annotation.RavenwoodKeepWholeClass 55 public class PowerProfile { 56 57 public static final String TAG = "PowerProfile"; 58 59 /* 60 * POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode. 61 * POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should 62 * be zero on devices that can go into full CPU power collapse even when a wake 63 * lock is held. Otherwise, this is the power consumption in addition to 64 * POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity. 65 * POWER_CPU_ACTIVE: Power consumption when CPU is running, excluding power consumed by clusters 66 * and cores. 67 * 68 * CPU Power Equation (assume two clusters): 69 * Total power = POWER_CPU_SUSPEND (always added) 70 * + POWER_CPU_IDLE (skip this and below if in power collapse mode) 71 * + POWER_CPU_ACTIVE (skip this and below if CPU is not running, but a wakelock 72 * is held) 73 * + cluster_power.cluster0 + cluster_power.cluster1 (skip cluster not running) 74 * + core_power.cluster0 * num running cores in cluster 0 75 * + core_power.cluster1 * num running cores in cluster 1 76 */ 77 public static final String POWER_CPU_SUSPEND = "cpu.suspend"; 78 @UnsupportedAppUsage 79 public static final String POWER_CPU_IDLE = "cpu.idle"; 80 @UnsupportedAppUsage 81 public static final String POWER_CPU_ACTIVE = "cpu.active"; 82 83 /** 84 * Power consumption when WiFi driver is scanning for networks. 85 */ 86 @UnsupportedAppUsage 87 public static final String POWER_WIFI_SCAN = "wifi.scan"; 88 89 /** 90 * Power consumption when WiFi driver is on. 91 */ 92 @UnsupportedAppUsage 93 public static final String POWER_WIFI_ON = "wifi.on"; 94 95 /** 96 * Power consumption when WiFi driver is transmitting/receiving. 97 */ 98 @UnsupportedAppUsage 99 public static final String POWER_WIFI_ACTIVE = "wifi.active"; 100 101 // 102 // Updated power constants. These are not estimated, they are real world 103 // currents and voltages for the underlying bluetooth and wifi controllers. 104 // 105 public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle"; 106 public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx"; 107 public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx"; 108 public static final String POWER_WIFI_CONTROLLER_TX_LEVELS = "wifi.controller.tx_levels"; 109 public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage"; 110 111 public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle"; 112 public static final String POWER_BLUETOOTH_CONTROLLER_RX = "bluetooth.controller.rx"; 113 public static final String POWER_BLUETOOTH_CONTROLLER_TX = "bluetooth.controller.tx"; 114 public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE = 115 "bluetooth.controller.voltage"; 116 117 public static final String POWER_MODEM_CONTROLLER_SLEEP = "modem.controller.sleep"; 118 public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle"; 119 public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx"; 120 public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx"; 121 public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE = 122 "modem.controller.voltage"; 123 124 /** 125 * Power consumption when GPS is on. 126 */ 127 @UnsupportedAppUsage 128 public static final String POWER_GPS_ON = "gps.on"; 129 130 /** 131 * GPS power parameters based on signal quality 132 */ 133 public static final String POWER_GPS_SIGNAL_QUALITY_BASED = "gps.signalqualitybased"; 134 public static final String POWER_GPS_OPERATING_VOLTAGE = "gps.voltage"; 135 136 /** 137 * Power consumption when Bluetooth driver is on. 138 * 139 * @deprecated 140 */ 141 @Deprecated 142 @UnsupportedAppUsage 143 public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; 144 145 /** 146 * Power consumption when Bluetooth driver is transmitting/receiving. 147 * 148 * @deprecated 149 */ 150 @Deprecated 151 public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; 152 153 /** 154 * Power consumption when Bluetooth driver gets an AT command. 155 * 156 * @deprecated 157 */ 158 @Deprecated 159 @UnsupportedAppUsage 160 public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; 161 162 /** 163 * Power consumption when screen is in doze/ambient/always-on mode, including backlight power. 164 * 165 * @deprecated Use {@link #POWER_GROUP_DISPLAY_AMBIENT} instead. 166 */ 167 @Deprecated 168 public static final String POWER_AMBIENT_DISPLAY = "ambient.on"; 169 170 /** 171 * Power consumption when screen is on, not including the backlight power. 172 * 173 * @deprecated Use {@link #POWER_GROUP_DISPLAY_SCREEN_ON} instead. 174 */ 175 @Deprecated 176 @UnsupportedAppUsage 177 public static final String POWER_SCREEN_ON = "screen.on"; 178 179 /** 180 * Power consumption when cell radio is on but not on a call. 181 */ 182 @UnsupportedAppUsage 183 public static final String POWER_RADIO_ON = "radio.on"; 184 185 /** 186 * Power consumption when cell radio is hunting for a signal. 187 */ 188 @UnsupportedAppUsage 189 public static final String POWER_RADIO_SCANNING = "radio.scanning"; 190 191 /** 192 * Power consumption when talking on the phone. 193 */ 194 @UnsupportedAppUsage 195 public static final String POWER_RADIO_ACTIVE = "radio.active"; 196 197 /** 198 * Power consumption at full backlight brightness. If the backlight is at 199 * 50% brightness, then this should be multiplied by 0.5 200 * 201 * @deprecated Use {@link #POWER_GROUP_DISPLAY_SCREEN_FULL} instead. 202 */ 203 @Deprecated 204 @UnsupportedAppUsage 205 public static final String POWER_SCREEN_FULL = "screen.full"; 206 207 /** 208 * Power consumed by the audio hardware when playing back audio content. This is in addition 209 * to the CPU power, probably due to a DSP and / or amplifier. 210 */ 211 public static final String POWER_AUDIO = "audio"; 212 213 /** 214 * Power consumed by any media hardware when playing back video content. This is in addition 215 * to the CPU power, probably due to a DSP. 216 */ 217 public static final String POWER_VIDEO = "video"; 218 219 /** 220 * Average power consumption when camera flashlight is on. 221 */ 222 public static final String POWER_FLASHLIGHT = "camera.flashlight"; 223 224 /** 225 * Power consumption when DDR is being used. 226 */ 227 public static final String POWER_MEMORY = "memory.bandwidths"; 228 229 /** 230 * Average power consumption when the camera is on over all standard use cases. 231 * 232 * TODO: Add more fine-grained camera power metrics. 233 */ 234 public static final String POWER_CAMERA = "camera.avg"; 235 236 /** 237 * Power consumed by wif batched scaning. Broken down into bins by 238 * Channels Scanned per Hour. May do 1-720 scans per hour of 1-100 channels 239 * for a range of 1-72,000. Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)! 240 */ 241 public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan"; 242 243 /** 244 * Battery capacity in milliAmpHour (mAh). 245 */ 246 public static final String POWER_BATTERY_CAPACITY = "battery.capacity"; 247 248 /** 249 * Power consumption when a screen is in doze/ambient/always-on mode, including backlight power. 250 */ 251 public static final String POWER_GROUP_DISPLAY_AMBIENT = "ambient.on.display"; 252 253 /** 254 * Power consumption when a screen is on, not including the backlight power. 255 */ 256 public static final String POWER_GROUP_DISPLAY_SCREEN_ON = "screen.on.display"; 257 258 /** 259 * Power consumption of a screen at full backlight brightness. 260 */ 261 public static final String POWER_GROUP_DISPLAY_SCREEN_FULL = "screen.full.display"; 262 263 @StringDef(prefix = { "POWER_GROUP_" }, value = { 264 POWER_GROUP_DISPLAY_AMBIENT, 265 POWER_GROUP_DISPLAY_SCREEN_ON, 266 POWER_GROUP_DISPLAY_SCREEN_FULL, 267 }) 268 @Retention(RetentionPolicy.SOURCE) 269 public @interface PowerGroup {} 270 271 /** 272 * Constants for generating a 64bit power constant key. 273 * 274 * The bitfields of a key describes what its corresponding power constant represents: 275 * [63:40] - RESERVED 276 * [39:32] - {@link Subsystem} (max count = 16). 277 * [31:0] - per Subsystem fields, see {@link ModemPowerProfile}. 278 * 279 */ 280 private static final long SUBSYSTEM_MASK = 0xF_0000_0000L; 281 /** 282 * Power constant not associated with a subsystem. 283 */ 284 public static final long SUBSYSTEM_NONE = 0x0_0000_0000L; 285 /** 286 * Modem power constant. 287 */ 288 public static final long SUBSYSTEM_MODEM = 0x1_0000_0000L; 289 290 @LongDef(prefix = { "SUBSYSTEM_" }, value = { 291 SUBSYSTEM_NONE, 292 SUBSYSTEM_MODEM, 293 }) 294 @Retention(RetentionPolicy.SOURCE) 295 public @interface Subsystem {} 296 297 private static final long SUBSYSTEM_FIELDS_MASK = 0xFFFF_FFFF; 298 299 public static final int POWER_BRACKETS_UNSPECIFIED = -1; 300 301 /** 302 * A map from Power Use Item to its power consumption. 303 */ 304 static final HashMap<String, Double> sPowerItemMap = new HashMap<>(); 305 /** 306 * A map from Power Use Item to an array of its power consumption 307 * (for items with variable power e.g. CPU). 308 */ 309 static final HashMap<String, Double[]> sPowerArrayMap = new HashMap<>(); 310 311 static final ModemPowerProfile sModemPowerProfile = new ModemPowerProfile(); 312 313 private static final String TAG_DEVICE = "device"; 314 private static final String TAG_ITEM = "item"; 315 private static final String TAG_ARRAY = "array"; 316 private static final String TAG_ARRAYITEM = "value"; 317 private static final String ATTR_NAME = "name"; 318 319 private static final String TAG_MODEM = "modem"; 320 321 private static final Object sLock = new Object(); 322 323 private int mCpuPowerBracketCount; 324 325 @VisibleForTesting PowerProfile()326 public PowerProfile() { 327 synchronized (sLock) { 328 initLocked(); 329 } 330 } 331 332 @VisibleForTesting 333 @UnsupportedAppUsage PowerProfile(Context context)334 public PowerProfile(Context context) { 335 this(context, false); 336 } 337 338 /** 339 * For PowerProfileTest 340 */ 341 @VisibleForTesting PowerProfile(Context context, boolean forTest)342 public PowerProfile(Context context, boolean forTest) { 343 // Read the XML file for the given profile (normally only one per device) 344 synchronized (sLock) { 345 final int xmlId = forTest ? com.android.internal.R.xml.power_profile_test 346 : com.android.internal.R.xml.power_profile; 347 initLocked(context, xmlId); 348 } 349 } 350 351 /** 352 * Reinitialize the PowerProfile with the provided XML. 353 * WARNING: use only for testing! 354 */ 355 @VisibleForTesting initForTesting(XmlPullParser parser)356 public void initForTesting(XmlPullParser parser) { 357 initForTesting(parser, null); 358 } 359 360 /** 361 * Reinitialize the PowerProfile with the provided XML, using optional Resources for fallback 362 * configuration settings. 363 * WARNING: use only for testing! 364 */ 365 @VisibleForTesting initForTesting(XmlPullParser parser, @Nullable Resources resources)366 public void initForTesting(XmlPullParser parser, @Nullable Resources resources) { 367 synchronized (sLock) { 368 sPowerItemMap.clear(); 369 sPowerArrayMap.clear(); 370 sModemPowerProfile.clear(); 371 372 try { 373 readPowerValuesFromXml(parser, resources); 374 } finally { 375 if (parser instanceof XmlResourceParser) { 376 ((XmlResourceParser) parser).close(); 377 } 378 } 379 initLocked(); 380 } 381 } 382 383 @GuardedBy("sLock") initLocked(Context context, @XmlRes int xmlId)384 private void initLocked(Context context, @XmlRes int xmlId) { 385 if (sPowerItemMap.size() == 0 && sPowerArrayMap.size() == 0) { 386 final Resources resources = context.getResources(); 387 XmlResourceParser parser = resources.getXml(xmlId); 388 readPowerValuesFromXml(parser, resources); 389 } 390 initLocked(); 391 } 392 initLocked()393 private void initLocked() { 394 initCpuClusters(); 395 initCpuScalingPolicies(); 396 initCpuPowerBrackets(); 397 initDisplays(); 398 initModem(); 399 } 400 readPowerValuesFromXml(XmlPullParser parser, @Nullable Resources resources)401 private static void readPowerValuesFromXml(XmlPullParser parser, 402 @Nullable Resources resources) { 403 boolean parsingArray = false; 404 ArrayList<Double> array = new ArrayList<>(); 405 String arrayName = null; 406 407 try { 408 XmlUtils.beginDocument(parser, TAG_DEVICE); 409 410 while (true) { 411 XmlUtils.nextElement(parser); 412 413 String element = parser.getName(); 414 if (element == null) break; 415 416 if (parsingArray && !element.equals(TAG_ARRAYITEM)) { 417 // Finish array 418 sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()])); 419 parsingArray = false; 420 } 421 if (element.equals(TAG_ARRAY)) { 422 parsingArray = true; 423 array.clear(); 424 arrayName = parser.getAttributeValue(null, ATTR_NAME); 425 } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) { 426 String name = null; 427 if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME); 428 if (parser.next() == XmlPullParser.TEXT) { 429 String power = parser.getText(); 430 double value = 0; 431 try { 432 value = Double.valueOf(power); 433 } catch (NumberFormatException nfe) { 434 } 435 if (element.equals(TAG_ITEM)) { 436 sPowerItemMap.put(name, value); 437 } else if (parsingArray) { 438 array.add(value); 439 } 440 } 441 } else if (element.equals(TAG_MODEM)) { 442 sModemPowerProfile.parseFromXml(parser); 443 } 444 } 445 if (parsingArray) { 446 sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()])); 447 } 448 } catch (XmlPullParserException e) { 449 throw new RuntimeException(e); 450 } catch (IOException e) { 451 throw new RuntimeException(e); 452 } finally { 453 if (parser instanceof XmlResourceParser) { 454 ((XmlResourceParser) parser).close(); 455 } 456 } 457 458 if (resources != null) { 459 getDefaultValuesFromConfig(resources); 460 } 461 } 462 getDefaultValuesFromConfig(Resources resources)463 private static void getDefaultValuesFromConfig(Resources resources) { 464 // Now collect other config variables. 465 int[] configResIds = new int[]{ 466 com.android.internal.R.integer.config_bluetooth_idle_cur_ma, 467 com.android.internal.R.integer.config_bluetooth_rx_cur_ma, 468 com.android.internal.R.integer.config_bluetooth_tx_cur_ma, 469 com.android.internal.R.integer.config_bluetooth_operating_voltage_mv, 470 }; 471 472 String[] configResIdKeys = new String[]{ 473 POWER_BLUETOOTH_CONTROLLER_IDLE, 474 POWER_BLUETOOTH_CONTROLLER_RX, 475 POWER_BLUETOOTH_CONTROLLER_TX, 476 POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, 477 }; 478 479 for (int i = 0; i < configResIds.length; i++) { 480 String key = configResIdKeys[i]; 481 // if we already have some of these parameters in power_profile.xml, ignore the 482 // value in config.xml 483 if ((sPowerItemMap.containsKey(key) && sPowerItemMap.get(key) > 0)) { 484 continue; 485 } 486 int value = resources.getInteger(configResIds[i]); 487 if (value > 0) { 488 sPowerItemMap.put(key, (double) value); 489 } 490 } 491 } 492 493 private CpuClusterKey[] mCpuClusters; 494 495 private static final String CPU_PER_CLUSTER_CORE_COUNT = "cpu.clusters.cores"; 496 private static final String CPU_CLUSTER_POWER_COUNT = "cpu.cluster_power.cluster"; 497 private static final String CPU_CORE_SPEED_PREFIX = "cpu.core_speeds.cluster"; 498 private static final String CPU_CORE_POWER_PREFIX = "cpu.core_power.cluster"; 499 private static final String CPU_POWER_BRACKETS_PREFIX = "cpu.power_brackets.policy"; 500 initCpuClusters()501 private void initCpuClusters() { 502 if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) { 503 final Double[] data = sPowerArrayMap.get(CPU_PER_CLUSTER_CORE_COUNT); 504 mCpuClusters = new CpuClusterKey[data.length]; 505 for (int cluster = 0; cluster < data.length; cluster++) { 506 int numCpusInCluster = (int) Math.round(data[cluster]); 507 mCpuClusters[cluster] = new CpuClusterKey( 508 CPU_CORE_SPEED_PREFIX + cluster, CPU_CLUSTER_POWER_COUNT + cluster, 509 CPU_CORE_POWER_PREFIX + cluster, numCpusInCluster); 510 } 511 } else { 512 // Default to single. 513 mCpuClusters = new CpuClusterKey[1]; 514 int numCpus = 1; 515 if (sPowerItemMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) { 516 numCpus = (int) Math.round(sPowerItemMap.get(CPU_PER_CLUSTER_CORE_COUNT)); 517 } 518 mCpuClusters[0] = new CpuClusterKey(CPU_CORE_SPEED_PREFIX + 0, 519 CPU_CLUSTER_POWER_COUNT + 0, CPU_CORE_POWER_PREFIX + 0, numCpus); 520 } 521 } 522 523 private SparseArray<CpuScalingPolicyPower> mCpuScalingPolicies; 524 private static final String CPU_SCALING_POLICY_POWER_POLICY = "cpu.scaling_policy_power.policy"; 525 private static final String CPU_SCALING_STEP_POWER_POLICY = "cpu.scaling_step_power.policy"; 526 initCpuScalingPolicies()527 private void initCpuScalingPolicies() { 528 int policyCount = 0; 529 for (String key : sPowerItemMap.keySet()) { 530 if (key.startsWith(CPU_SCALING_POLICY_POWER_POLICY)) { 531 int policy = 532 Integer.parseInt(key.substring(CPU_SCALING_POLICY_POWER_POLICY.length())); 533 policyCount = Math.max(policyCount, policy + 1); 534 } 535 } 536 for (String key : sPowerArrayMap.keySet()) { 537 if (key.startsWith(CPU_SCALING_STEP_POWER_POLICY)) { 538 int policy = 539 Integer.parseInt(key.substring(CPU_SCALING_STEP_POWER_POLICY.length())); 540 policyCount = Math.max(policyCount, policy + 1); 541 } 542 } 543 544 if (policyCount > 0) { 545 mCpuScalingPolicies = new SparseArray<>(policyCount); 546 for (int policy = 0; policy < policyCount; policy++) { 547 Double policyPower = sPowerItemMap.get(CPU_SCALING_POLICY_POWER_POLICY + policy); 548 Double[] stepPower = sPowerArrayMap.get(CPU_SCALING_STEP_POWER_POLICY + policy); 549 if (policyPower != null || stepPower != null) { 550 double[] primitiveStepPower; 551 if (stepPower != null) { 552 primitiveStepPower = new double[stepPower.length]; 553 for (int i = 0; i < stepPower.length; i++) { 554 primitiveStepPower[i] = stepPower[i]; 555 } 556 } else { 557 primitiveStepPower = new double[0]; 558 } 559 mCpuScalingPolicies.put(policy, new CpuScalingPolicyPower( 560 policyPower != null ? policyPower : 0, primitiveStepPower)); 561 } 562 } 563 } else { 564 // Legacy power_profile.xml 565 int cpuId = 0; 566 for (CpuClusterKey cpuCluster : mCpuClusters) { 567 policyCount = cpuId + 1; 568 cpuId += cpuCluster.numCpus; 569 } 570 571 if (policyCount > 0) { 572 mCpuScalingPolicies = new SparseArray<>(policyCount); 573 cpuId = 0; 574 for (CpuClusterKey cpuCluster : mCpuClusters) { 575 double clusterPower = getAveragePower(cpuCluster.clusterPowerKey); 576 double[] stepPower; 577 int numSteps = getNumElements(cpuCluster.corePowerKey); 578 if (numSteps != 0) { 579 stepPower = new double[numSteps]; 580 for (int step = 0; step < numSteps; step++) { 581 stepPower[step] = getAveragePower(cpuCluster.corePowerKey, step); 582 } 583 } else { 584 stepPower = new double[1]; 585 } 586 mCpuScalingPolicies.put(cpuId, 587 new CpuScalingPolicyPower(clusterPower, stepPower)); 588 cpuId += cpuCluster.numCpus; 589 } 590 } else { 591 mCpuScalingPolicies = new SparseArray<>(1); 592 mCpuScalingPolicies.put(0, 593 new CpuScalingPolicyPower(getAveragePower(POWER_CPU_ACTIVE), 594 new double[]{0})); 595 } 596 } 597 } 598 599 /** 600 * Parses or computes CPU power brackets: groups of states with similar power requirements. 601 */ initCpuPowerBrackets()602 private void initCpuPowerBrackets() { 603 boolean anyBracketsSpecified = false; 604 boolean allBracketsSpecified = true; 605 for (int i = mCpuScalingPolicies.size() - 1; i >= 0; i--) { 606 int policy = mCpuScalingPolicies.keyAt(i); 607 CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i); 608 final int steps = cpuScalingPolicyPower.stepPower.length; 609 cpuScalingPolicyPower.powerBrackets = new int[steps]; 610 if (sPowerArrayMap.get(CPU_POWER_BRACKETS_PREFIX + policy) != null) { 611 anyBracketsSpecified = true; 612 } else { 613 allBracketsSpecified = false; 614 } 615 } 616 if (anyBracketsSpecified && !allBracketsSpecified) { 617 throw new RuntimeException( 618 "Power brackets should be specified for all scaling policies or none"); 619 } 620 621 if (!allBracketsSpecified) { 622 mCpuPowerBracketCount = POWER_BRACKETS_UNSPECIFIED; 623 return; 624 } 625 626 mCpuPowerBracketCount = 0; 627 for (int i = mCpuScalingPolicies.size() - 1; i >= 0; i--) { 628 int policy = mCpuScalingPolicies.keyAt(i); 629 CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i); 630 final Double[] data = sPowerArrayMap.get(CPU_POWER_BRACKETS_PREFIX + policy); 631 if (data.length != cpuScalingPolicyPower.powerBrackets.length) { 632 throw new RuntimeException( 633 "Wrong number of items in " + CPU_POWER_BRACKETS_PREFIX + policy 634 + ", expected: " 635 + cpuScalingPolicyPower.powerBrackets.length); 636 } 637 638 for (int j = 0; j < data.length; j++) { 639 final int bracket = (int) Math.round(data[j]); 640 cpuScalingPolicyPower.powerBrackets[j] = bracket; 641 if (bracket > mCpuPowerBracketCount) { 642 mCpuPowerBracketCount = bracket; 643 } 644 } 645 } 646 mCpuPowerBracketCount++; 647 } 648 649 private static class CpuScalingPolicyPower { 650 public final double policyPower; 651 public final double[] stepPower; 652 public int[] powerBrackets; 653 CpuScalingPolicyPower(double policyPower, double[] stepPower)654 private CpuScalingPolicyPower(double policyPower, double[] stepPower) { 655 this.policyPower = policyPower; 656 this.stepPower = stepPower; 657 } 658 } 659 660 /** 661 * Returns the average additional power in (mA) when the CPU scaling policy <code>policy</code> 662 * is used. 663 * 664 * @param policy Policy ID as per <code>ls /sys/devices/system/cpu/cpufreq</code>. Typically, 665 * policy ID corresponds to the index of the first related CPU, e.g. for "policy6" 666 * <code>/sys/devices/system/cpu/cpufreq/policy6/related_cpus</code> will 667 * contain CPU IDs like <code>6, 7</code> 668 */ getAveragePowerForCpuScalingPolicy(int policy)669 public double getAveragePowerForCpuScalingPolicy(int policy) { 670 CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.get(policy); 671 if (cpuScalingPolicyPower != null) { 672 return cpuScalingPolicyPower.policyPower; 673 } 674 return 0; 675 } 676 677 /** 678 * Returns the average additional power in (mA) when the CPU scaling policy <code>policy</code> 679 * is used at the <code>step</code> frequency step (this is not the frequency itself, but the 680 * integer index of the frequency step). 681 */ getAveragePowerForCpuScalingStep(int policy, int step)682 public double getAveragePowerForCpuScalingStep(int policy, int step) { 683 CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.get(policy); 684 if (cpuScalingPolicyPower != null 685 && step >= 0 && step < cpuScalingPolicyPower.stepPower.length) { 686 return cpuScalingPolicyPower.stepPower[step]; 687 } 688 return 0; 689 } 690 691 private static class CpuClusterKey { 692 public final String freqKey; 693 public final String clusterPowerKey; 694 public final String corePowerKey; 695 public final int numCpus; 696 CpuClusterKey(String freqKey, String clusterPowerKey, String corePowerKey, int numCpus)697 private CpuClusterKey(String freqKey, String clusterPowerKey, 698 String corePowerKey, int numCpus) { 699 this.freqKey = freqKey; 700 this.clusterPowerKey = clusterPowerKey; 701 this.corePowerKey = corePowerKey; 702 this.numCpus = numCpus; 703 } 704 } 705 706 /** 707 * @deprecated Use CpuScalingPolicy instead 708 */ 709 @UnsupportedAppUsage 710 @Deprecated getNumCpuClusters()711 public int getNumCpuClusters() { 712 return mCpuClusters.length; 713 } 714 715 /** 716 * @deprecated Use CpuScalingPolicy instead 717 */ 718 @Deprecated getNumCoresInCpuCluster(int cluster)719 public int getNumCoresInCpuCluster(int cluster) { 720 if (cluster < 0 || cluster >= mCpuClusters.length) { 721 return 0; // index out of bound 722 } 723 return mCpuClusters[cluster].numCpus; 724 } 725 726 /** 727 * @deprecated Use CpuScalingPolicy instead 728 */ 729 @UnsupportedAppUsage 730 @Deprecated getNumSpeedStepsInCpuCluster(int cluster)731 public int getNumSpeedStepsInCpuCluster(int cluster) { 732 if (cluster < 0 || cluster >= mCpuClusters.length) { 733 return 0; // index out of bound 734 } 735 if (sPowerArrayMap.containsKey(mCpuClusters[cluster].freqKey)) { 736 return sPowerArrayMap.get(mCpuClusters[cluster].freqKey).length; 737 } 738 return 1; // Only one speed 739 } 740 741 /** 742 * @deprecated Use getAveragePowerForCpuScalingPolicy 743 */ 744 @Deprecated getAveragePowerForCpuCluster(int cluster)745 public double getAveragePowerForCpuCluster(int cluster) { 746 if (cluster >= 0 && cluster < mCpuClusters.length) { 747 return getAveragePower(mCpuClusters[cluster].clusterPowerKey); 748 } 749 return 0; 750 } 751 752 /** 753 * @deprecated Use getAveragePowerForCpuScalingStep 754 */ 755 @Deprecated getAveragePowerForCpuCore(int cluster, int step)756 public double getAveragePowerForCpuCore(int cluster, int step) { 757 if (cluster >= 0 && cluster < mCpuClusters.length) { 758 return getAveragePower(mCpuClusters[cluster].corePowerKey, step); 759 } 760 return 0; 761 } 762 763 /** 764 * Returns the number of CPU power brackets: groups of states with similar power requirements. 765 * If power brackets are not specified, returns {@link #POWER_BRACKETS_UNSPECIFIED} 766 */ getCpuPowerBracketCount()767 public int getCpuPowerBracketCount() { 768 return mCpuPowerBracketCount; 769 } 770 771 /** 772 * Returns the CPU power bracket corresponding to the specified scaling policy and frequency 773 * step 774 */ getCpuPowerBracketForScalingStep(int policy, int step)775 public int getCpuPowerBracketForScalingStep(int policy, int step) { 776 CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.get(policy); 777 if (cpuScalingPolicyPower != null 778 && step >= 0 && step < cpuScalingPolicyPower.powerBrackets.length) { 779 return cpuScalingPolicyPower.powerBrackets[step]; 780 } 781 return 0; 782 } 783 784 private int mNumDisplays; 785 initDisplays()786 private void initDisplays() { 787 // Figure out how many displays are listed in the power profile. 788 mNumDisplays = 0; 789 while (!Double.isNaN( 790 getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, mNumDisplays, Double.NaN)) 791 || !Double.isNaN( 792 getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, mNumDisplays, Double.NaN)) 793 || !Double.isNaN( 794 getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, mNumDisplays, 795 Double.NaN))) { 796 mNumDisplays++; 797 } 798 799 // Handle legacy display power constants. 800 final Double deprecatedAmbientDisplay = sPowerItemMap.get(POWER_AMBIENT_DISPLAY); 801 boolean legacy = false; 802 if (deprecatedAmbientDisplay != null && mNumDisplays == 0) { 803 final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_AMBIENT, 0); 804 Slog.w(TAG, POWER_AMBIENT_DISPLAY + " is deprecated! Use " + key + " instead."); 805 sPowerItemMap.put(key, deprecatedAmbientDisplay); 806 legacy = true; 807 } 808 809 final Double deprecatedScreenOn = sPowerItemMap.get(POWER_SCREEN_ON); 810 if (deprecatedScreenOn != null && mNumDisplays == 0) { 811 final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_SCREEN_ON, 0); 812 Slog.w(TAG, POWER_SCREEN_ON + " is deprecated! Use " + key + " instead."); 813 sPowerItemMap.put(key, deprecatedScreenOn); 814 legacy = true; 815 } 816 817 final Double deprecatedScreenFull = sPowerItemMap.get(POWER_SCREEN_FULL); 818 if (deprecatedScreenFull != null && mNumDisplays == 0) { 819 final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_SCREEN_FULL, 0); 820 Slog.w(TAG, POWER_SCREEN_FULL + " is deprecated! Use " + key + " instead."); 821 sPowerItemMap.put(key, deprecatedScreenFull); 822 legacy = true; 823 } 824 if (legacy) { 825 mNumDisplays = 1; 826 } 827 } 828 829 /** 830 * Returns the number built in displays on the device as defined in the power_profile.xml. 831 */ getNumDisplays()832 public int getNumDisplays() { 833 return mNumDisplays; 834 } 835 initModem()836 private void initModem() { 837 handleDeprecatedModemConstant(ModemPowerProfile.MODEM_DRAIN_TYPE_SLEEP, 838 POWER_MODEM_CONTROLLER_SLEEP, 0); 839 handleDeprecatedModemConstant(ModemPowerProfile.MODEM_DRAIN_TYPE_IDLE, 840 POWER_MODEM_CONTROLLER_IDLE, 0); 841 handleDeprecatedModemConstant( 842 ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT | ModemPowerProfile.MODEM_DRAIN_TYPE_RX, 843 POWER_MODEM_CONTROLLER_RX, 0); 844 handleDeprecatedModemConstant( 845 ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT | ModemPowerProfile.MODEM_DRAIN_TYPE_TX 846 | ModemPowerProfile.MODEM_TX_LEVEL_0, POWER_MODEM_CONTROLLER_TX, 0); 847 handleDeprecatedModemConstant( 848 ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT | ModemPowerProfile.MODEM_DRAIN_TYPE_TX 849 | ModemPowerProfile.MODEM_TX_LEVEL_1, POWER_MODEM_CONTROLLER_TX, 1); 850 handleDeprecatedModemConstant( 851 ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT | ModemPowerProfile.MODEM_DRAIN_TYPE_TX 852 | ModemPowerProfile.MODEM_TX_LEVEL_2, POWER_MODEM_CONTROLLER_TX, 2); 853 handleDeprecatedModemConstant( 854 ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT | ModemPowerProfile.MODEM_DRAIN_TYPE_TX 855 | ModemPowerProfile.MODEM_TX_LEVEL_3, POWER_MODEM_CONTROLLER_TX, 3); 856 handleDeprecatedModemConstant( 857 ModemPowerProfile.MODEM_RAT_TYPE_DEFAULT | ModemPowerProfile.MODEM_DRAIN_TYPE_TX 858 | ModemPowerProfile.MODEM_TX_LEVEL_4, POWER_MODEM_CONTROLLER_TX, 4); 859 } 860 handleDeprecatedModemConstant(int key, String deprecatedKey, int level)861 private void handleDeprecatedModemConstant(int key, String deprecatedKey, int level) { 862 final double drain = sModemPowerProfile.getAverageBatteryDrainMa(key); 863 if (!Double.isNaN(drain)) return; // Value already set, don't overwrite it. 864 865 final double deprecatedDrain = getAveragePower(deprecatedKey, level); 866 sModemPowerProfile.setPowerConstant(key, Double.toString(deprecatedDrain)); 867 } 868 869 /** 870 * Returns the number of memory bandwidth buckets defined in power_profile.xml, or a 871 * default value if the subsystem has no recorded value. 872 * 873 * @return the number of memory bandwidth buckets. 874 */ getNumElements(String key)875 public int getNumElements(String key) { 876 if (sPowerItemMap.containsKey(key)) { 877 return 1; 878 } else if (sPowerArrayMap.containsKey(key)) { 879 return sPowerArrayMap.get(key).length; 880 } 881 return 0; 882 } 883 884 /** 885 * Returns the average current in mA consumed by the subsystem, or the given 886 * default value if the subsystem has no recorded value. 887 * 888 * @param type the subsystem type 889 * @param defaultValue the value to return if the subsystem has no recorded value. 890 * @return the average current in milliAmps. 891 */ getAveragePowerOrDefault(String type, double defaultValue)892 public double getAveragePowerOrDefault(String type, double defaultValue) { 893 if (sPowerItemMap.containsKey(type)) { 894 return sPowerItemMap.get(type); 895 } else if (sPowerArrayMap.containsKey(type)) { 896 return sPowerArrayMap.get(type)[0]; 897 } else { 898 return defaultValue; 899 } 900 } 901 902 /** 903 * Returns the average current in mA consumed by the subsystem 904 * 905 * @param type the subsystem type 906 * @return the average current in milliAmps. 907 */ 908 @UnsupportedAppUsage getAveragePower(String type)909 public double getAveragePower(String type) { 910 return getAveragePowerOrDefault(type, 0); 911 } 912 913 /** 914 * Returns the average current in mA consumed by a subsystem's specified operation, or the given 915 * default value if the subsystem has no recorded value. 916 * 917 * @param key that describes a subsystem's battery draining operation 918 * The key is built from multiple constant, see {@link Subsystem} and 919 * {@link ModemPowerProfile}. 920 * @param defaultValue the value to return if the subsystem has no recorded value. 921 * @return the average current in milliAmps. 922 */ getAverageBatteryDrainOrDefaultMa(long key, double defaultValue)923 public double getAverageBatteryDrainOrDefaultMa(long key, double defaultValue) { 924 final long subsystemType = key & SUBSYSTEM_MASK; 925 final int subsystemFields = (int) (key & SUBSYSTEM_FIELDS_MASK); 926 927 final double value; 928 if (subsystemType == SUBSYSTEM_MODEM) { 929 value = sModemPowerProfile.getAverageBatteryDrainMa(subsystemFields); 930 } else { 931 value = Double.NaN; 932 } 933 934 if (Double.isNaN(value)) return defaultValue; 935 return value; 936 } 937 938 /** 939 * Returns the average current in mA consumed by a subsystem's specified operation. 940 * 941 * @param key that describes a subsystem's battery draining operation 942 * The key is built from multiple constant, see {@link Subsystem} and 943 * {@link ModemPowerProfile}. 944 * @return the average current in milliAmps. 945 */ getAverageBatteryDrainMa(long key)946 public double getAverageBatteryDrainMa(long key) { 947 return getAverageBatteryDrainOrDefaultMa(key, 0); 948 } 949 950 /** 951 * Returns the average current in mA consumed by the subsystem for the given level. 952 * 953 * @param type the subsystem type 954 * @param level the level of power at which the subsystem is running. For instance, the 955 * signal strength of the cell network between 0 and 4 (if there are 4 bars max.) 956 * If there is no data for multiple levels, the level is ignored. 957 * @return the average current in milliAmps. 958 */ 959 @UnsupportedAppUsage getAveragePower(String type, int level)960 public double getAveragePower(String type, int level) { 961 if (sPowerItemMap.containsKey(type)) { 962 return sPowerItemMap.get(type); 963 } else if (sPowerArrayMap.containsKey(type)) { 964 final Double[] values = sPowerArrayMap.get(type); 965 if (values.length > level && level >= 0) { 966 return values[level]; 967 } else if (level < 0 || values.length == 0) { 968 return 0; 969 } else { 970 return values[values.length - 1]; 971 } 972 } else { 973 return 0; 974 } 975 } 976 977 /** 978 * Returns the average current in mA consumed by an ordinaled subsystem, or the given 979 * default value if the subsystem has no recorded value. 980 * 981 * @param group the subsystem {@link PowerGroup}. 982 * @param ordinal which entity in the {@link PowerGroup}. 983 * @param defaultValue the value to return if the subsystem has no recorded value. 984 * @return the average current in milliAmps. 985 */ getAveragePowerForOrdinal(@owerGroup String group, int ordinal, double defaultValue)986 public double getAveragePowerForOrdinal(@PowerGroup String group, int ordinal, 987 double defaultValue) { 988 final String type = getOrdinalPowerType(group, ordinal); 989 return getAveragePowerOrDefault(type, defaultValue); 990 } 991 992 /** 993 * Returns the average current in mA consumed by an ordinaled subsystem. 994 * 995 * @param group the subsystem {@link PowerGroup}. 996 * @param ordinal which entity in the {@link PowerGroup}. 997 * @return the average current in milliAmps. 998 */ getAveragePowerForOrdinal(@owerGroup String group, int ordinal)999 public double getAveragePowerForOrdinal(@PowerGroup String group, int ordinal) { 1000 return getAveragePowerForOrdinal(group, ordinal, 0); 1001 } 1002 1003 /** 1004 * Returns the battery capacity, if available, in milli Amp Hours. If not available, 1005 * it returns zero. 1006 * 1007 * @return the battery capacity in mAh 1008 */ 1009 @UnsupportedAppUsage getBatteryCapacity()1010 public double getBatteryCapacity() { 1011 return getAveragePower(POWER_BATTERY_CAPACITY); 1012 } 1013 1014 /** 1015 * Dump power constants into PowerProfileProto 1016 */ dumpDebug(ProtoOutputStream proto)1017 public void dumpDebug(ProtoOutputStream proto) { 1018 // cpu.suspend 1019 writePowerConstantToProto(proto, POWER_CPU_SUSPEND, PowerProfileProto.CPU_SUSPEND); 1020 1021 // cpu.idle 1022 writePowerConstantToProto(proto, POWER_CPU_IDLE, PowerProfileProto.CPU_IDLE); 1023 1024 // cpu.active 1025 writePowerConstantToProto(proto, POWER_CPU_ACTIVE, PowerProfileProto.CPU_ACTIVE); 1026 1027 // cpu.clusters.cores 1028 // cpu.cluster_power.cluster 1029 // cpu.core_speeds.cluster 1030 // cpu.core_power.cluster 1031 for (int cluster = 0; cluster < mCpuClusters.length; cluster++) { 1032 final long token = proto.start(PowerProfileProto.CPU_CLUSTER); 1033 proto.write(PowerProfileProto.CpuCluster.ID, cluster); 1034 proto.write(PowerProfileProto.CpuCluster.CLUSTER_POWER, 1035 sPowerItemMap.get(mCpuClusters[cluster].clusterPowerKey)); 1036 proto.write(PowerProfileProto.CpuCluster.CORES, mCpuClusters[cluster].numCpus); 1037 for (Double speed : sPowerArrayMap.get(mCpuClusters[cluster].freqKey)) { 1038 proto.write(PowerProfileProto.CpuCluster.SPEED, speed); 1039 } 1040 for (Double corePower : sPowerArrayMap.get(mCpuClusters[cluster].corePowerKey)) { 1041 proto.write(PowerProfileProto.CpuCluster.CORE_POWER, corePower); 1042 } 1043 proto.end(token); 1044 } 1045 1046 // wifi.scan 1047 writePowerConstantToProto(proto, POWER_WIFI_SCAN, PowerProfileProto.WIFI_SCAN); 1048 1049 // wifi.on 1050 writePowerConstantToProto(proto, POWER_WIFI_ON, PowerProfileProto.WIFI_ON); 1051 1052 // wifi.active 1053 writePowerConstantToProto(proto, POWER_WIFI_ACTIVE, PowerProfileProto.WIFI_ACTIVE); 1054 1055 // wifi.controller.idle 1056 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_IDLE, 1057 PowerProfileProto.WIFI_CONTROLLER_IDLE); 1058 1059 // wifi.controller.rx 1060 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_RX, 1061 PowerProfileProto.WIFI_CONTROLLER_RX); 1062 1063 // wifi.controller.tx 1064 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_TX, 1065 PowerProfileProto.WIFI_CONTROLLER_TX); 1066 1067 // wifi.controller.tx_levels 1068 writePowerConstantArrayToProto(proto, POWER_WIFI_CONTROLLER_TX_LEVELS, 1069 PowerProfileProto.WIFI_CONTROLLER_TX_LEVELS); 1070 1071 // wifi.controller.voltage 1072 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE, 1073 PowerProfileProto.WIFI_CONTROLLER_OPERATING_VOLTAGE); 1074 1075 // bluetooth.controller.idle 1076 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_IDLE, 1077 PowerProfileProto.BLUETOOTH_CONTROLLER_IDLE); 1078 1079 // bluetooth.controller.rx 1080 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_RX, 1081 PowerProfileProto.BLUETOOTH_CONTROLLER_RX); 1082 1083 // bluetooth.controller.tx 1084 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_TX, 1085 PowerProfileProto.BLUETOOTH_CONTROLLER_TX); 1086 1087 // bluetooth.controller.voltage 1088 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, 1089 PowerProfileProto.BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE); 1090 1091 // modem.controller.sleep 1092 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_SLEEP, 1093 PowerProfileProto.MODEM_CONTROLLER_SLEEP); 1094 1095 // modem.controller.idle 1096 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_IDLE, 1097 PowerProfileProto.MODEM_CONTROLLER_IDLE); 1098 1099 // modem.controller.rx 1100 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_RX, 1101 PowerProfileProto.MODEM_CONTROLLER_RX); 1102 1103 // modem.controller.tx 1104 writePowerConstantArrayToProto(proto, POWER_MODEM_CONTROLLER_TX, 1105 PowerProfileProto.MODEM_CONTROLLER_TX); 1106 1107 // modem.controller.voltage 1108 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE, 1109 PowerProfileProto.MODEM_CONTROLLER_OPERATING_VOLTAGE); 1110 1111 // gps.on 1112 writePowerConstantToProto(proto, POWER_GPS_ON, PowerProfileProto.GPS_ON); 1113 1114 // gps.signalqualitybased 1115 writePowerConstantArrayToProto(proto, POWER_GPS_SIGNAL_QUALITY_BASED, 1116 PowerProfileProto.GPS_SIGNAL_QUALITY_BASED); 1117 1118 // gps.voltage 1119 writePowerConstantToProto(proto, POWER_GPS_OPERATING_VOLTAGE, 1120 PowerProfileProto.GPS_OPERATING_VOLTAGE); 1121 1122 // bluetooth.on 1123 writePowerConstantToProto(proto, POWER_BLUETOOTH_ON, PowerProfileProto.BLUETOOTH_ON); 1124 1125 // bluetooth.active 1126 writePowerConstantToProto(proto, POWER_BLUETOOTH_ACTIVE, 1127 PowerProfileProto.BLUETOOTH_ACTIVE); 1128 1129 // bluetooth.at 1130 writePowerConstantToProto(proto, POWER_BLUETOOTH_AT_CMD, 1131 PowerProfileProto.BLUETOOTH_AT_CMD); 1132 1133 // ambient.on 1134 writePowerConstantToProto(proto, POWER_AMBIENT_DISPLAY, PowerProfileProto.AMBIENT_DISPLAY); 1135 1136 // screen.on 1137 writePowerConstantToProto(proto, POWER_SCREEN_ON, PowerProfileProto.SCREEN_ON); 1138 1139 // radio.on 1140 writePowerConstantToProto(proto, POWER_RADIO_ON, PowerProfileProto.RADIO_ON); 1141 1142 // radio.scanning 1143 writePowerConstantToProto(proto, POWER_RADIO_SCANNING, PowerProfileProto.RADIO_SCANNING); 1144 1145 // radio.active 1146 writePowerConstantToProto(proto, POWER_RADIO_ACTIVE, PowerProfileProto.RADIO_ACTIVE); 1147 1148 // screen.full 1149 writePowerConstantToProto(proto, POWER_SCREEN_FULL, PowerProfileProto.SCREEN_FULL); 1150 1151 // audio 1152 writePowerConstantToProto(proto, POWER_AUDIO, PowerProfileProto.AUDIO); 1153 1154 // video 1155 writePowerConstantToProto(proto, POWER_VIDEO, PowerProfileProto.VIDEO); 1156 1157 // camera.flashlight 1158 writePowerConstantToProto(proto, POWER_FLASHLIGHT, PowerProfileProto.FLASHLIGHT); 1159 1160 // memory.bandwidths 1161 writePowerConstantToProto(proto, POWER_MEMORY, PowerProfileProto.MEMORY); 1162 1163 // camera.avg 1164 writePowerConstantToProto(proto, POWER_CAMERA, PowerProfileProto.CAMERA); 1165 1166 // wifi.batchedscan 1167 writePowerConstantToProto(proto, POWER_WIFI_BATCHED_SCAN, 1168 PowerProfileProto.WIFI_BATCHED_SCAN); 1169 1170 // battery.capacity 1171 writePowerConstantToProto(proto, POWER_BATTERY_CAPACITY, 1172 PowerProfileProto.BATTERY_CAPACITY); 1173 } 1174 1175 /** 1176 * Dump the PowerProfile values. 1177 */ dump(PrintWriter pw)1178 public void dump(PrintWriter pw) { 1179 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw); 1180 sPowerItemMap.forEach((key, value) -> { 1181 ipw.print(key, value); 1182 ipw.println(); 1183 }); 1184 sPowerArrayMap.forEach((key, value) -> { 1185 ipw.print(key, Arrays.toString(value)); 1186 ipw.println(); 1187 }); 1188 ipw.println("Modem values:"); 1189 ipw.increaseIndent(); 1190 sModemPowerProfile.dump(ipw); 1191 ipw.decreaseIndent(); 1192 } 1193 1194 // Writes items in sPowerItemMap to proto if exists. writePowerConstantToProto(ProtoOutputStream proto, String key, long fieldId)1195 private void writePowerConstantToProto(ProtoOutputStream proto, String key, long fieldId) { 1196 if (sPowerItemMap.containsKey(key)) { 1197 proto.write(fieldId, sPowerItemMap.get(key)); 1198 } 1199 } 1200 1201 // Writes items in sPowerArrayMap to proto if exists. writePowerConstantArrayToProto(ProtoOutputStream proto, String key, long fieldId)1202 private void writePowerConstantArrayToProto(ProtoOutputStream proto, String key, long fieldId) { 1203 if (sPowerArrayMap.containsKey(key)) { 1204 for (Double d : sPowerArrayMap.get(key)) { 1205 proto.write(fieldId, d); 1206 } 1207 } 1208 } 1209 1210 // Creates the key for an ordinaled power constant from the group and ordinal. getOrdinalPowerType(@owerGroup String group, int ordinal)1211 private static String getOrdinalPowerType(@PowerGroup String group, int ordinal) { 1212 return group + ordinal; 1213 } 1214 } 1215