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