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.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 return mCpuClusters[cluster].numCpus; 397 } 398 399 @UnsupportedAppUsage getNumSpeedStepsInCpuCluster(int cluster)400 public int getNumSpeedStepsInCpuCluster(int cluster) { 401 if (cluster < 0 || cluster >= mCpuClusters.length) { 402 return 0; // index out of bound 403 } 404 if (sPowerArrayMap.containsKey(mCpuClusters[cluster].freqKey)) { 405 return sPowerArrayMap.get(mCpuClusters[cluster].freqKey).length; 406 } 407 return 1; // Only one speed 408 } 409 getAveragePowerForCpuCluster(int cluster)410 public double getAveragePowerForCpuCluster(int cluster) { 411 if (cluster >= 0 && cluster < mCpuClusters.length) { 412 return getAveragePower(mCpuClusters[cluster].clusterPowerKey); 413 } 414 return 0; 415 } 416 getAveragePowerForCpuCore(int cluster, int step)417 public double getAveragePowerForCpuCore(int cluster, int step) { 418 if (cluster >= 0 && cluster < mCpuClusters.length) { 419 return getAveragePower(mCpuClusters[cluster].corePowerKey, step); 420 } 421 return 0; 422 } 423 424 /** 425 * Returns the number of memory bandwidth buckets defined in power_profile.xml, or a 426 * default value if the subsystem has no recorded value. 427 * 428 * @return the number of memory bandwidth buckets. 429 */ getNumElements(String key)430 public int getNumElements(String key) { 431 if (sPowerItemMap.containsKey(key)) { 432 return 1; 433 } else if (sPowerArrayMap.containsKey(key)) { 434 return sPowerArrayMap.get(key).length; 435 } 436 return 0; 437 } 438 439 /** 440 * Returns the average current in mA consumed by the subsystem, or the given 441 * default value if the subsystem has no recorded value. 442 * 443 * @param type the subsystem type 444 * @param defaultValue the value to return if the subsystem has no recorded value. 445 * @return the average current in milliAmps. 446 */ getAveragePowerOrDefault(String type, double defaultValue)447 public double getAveragePowerOrDefault(String type, double defaultValue) { 448 if (sPowerItemMap.containsKey(type)) { 449 return sPowerItemMap.get(type); 450 } else if (sPowerArrayMap.containsKey(type)) { 451 return sPowerArrayMap.get(type)[0]; 452 } else { 453 return defaultValue; 454 } 455 } 456 457 /** 458 * Returns the average current in mA consumed by the subsystem 459 * 460 * @param type the subsystem type 461 * @return the average current in milliAmps. 462 */ 463 @UnsupportedAppUsage getAveragePower(String type)464 public double getAveragePower(String type) { 465 return getAveragePowerOrDefault(type, 0); 466 } 467 468 /** 469 * Returns the average current in mA consumed by the subsystem for the given level. 470 * 471 * @param type the subsystem type 472 * @param level the level of power at which the subsystem is running. For instance, the 473 * signal strength of the cell network between 0 and 4 (if there are 4 bars max.) 474 * If there is no data for multiple levels, the level is ignored. 475 * @return the average current in milliAmps. 476 */ 477 @UnsupportedAppUsage getAveragePower(String type, int level)478 public double getAveragePower(String type, int level) { 479 if (sPowerItemMap.containsKey(type)) { 480 return sPowerItemMap.get(type); 481 } else if (sPowerArrayMap.containsKey(type)) { 482 final Double[] values = sPowerArrayMap.get(type); 483 if (values.length > level && level >= 0) { 484 return values[level]; 485 } else if (level < 0 || values.length == 0) { 486 return 0; 487 } else { 488 return values[values.length - 1]; 489 } 490 } else { 491 return 0; 492 } 493 } 494 495 /** 496 * Returns the battery capacity, if available, in milli Amp Hours. If not available, 497 * it returns zero. 498 * 499 * @return the battery capacity in mAh 500 */ 501 @UnsupportedAppUsage getBatteryCapacity()502 public double getBatteryCapacity() { 503 return getAveragePower(POWER_BATTERY_CAPACITY); 504 } 505 506 /** 507 * Dump power constants into PowerProfileProto 508 */ writeToProto(ProtoOutputStream proto)509 public void writeToProto(ProtoOutputStream proto) { 510 // cpu.suspend 511 writePowerConstantToProto(proto, POWER_CPU_SUSPEND, PowerProfileProto.CPU_SUSPEND); 512 513 // cpu.idle 514 writePowerConstantToProto(proto, POWER_CPU_IDLE, PowerProfileProto.CPU_IDLE); 515 516 // cpu.active 517 writePowerConstantToProto(proto, POWER_CPU_ACTIVE, PowerProfileProto.CPU_ACTIVE); 518 519 // cpu.clusters.cores 520 // cpu.cluster_power.cluster 521 // cpu.core_speeds.cluster 522 // cpu.core_power.cluster 523 for (int cluster = 0; cluster < mCpuClusters.length; cluster++) { 524 final long token = proto.start(PowerProfileProto.CPU_CLUSTER); 525 proto.write(PowerProfileProto.CpuCluster.ID, cluster); 526 proto.write(PowerProfileProto.CpuCluster.CLUSTER_POWER, 527 sPowerItemMap.get(mCpuClusters[cluster].clusterPowerKey)); 528 proto.write(PowerProfileProto.CpuCluster.CORES, mCpuClusters[cluster].numCpus); 529 for (Double speed : sPowerArrayMap.get(mCpuClusters[cluster].freqKey)) { 530 proto.write(PowerProfileProto.CpuCluster.SPEED, speed); 531 } 532 for (Double corePower : sPowerArrayMap.get(mCpuClusters[cluster].corePowerKey)) { 533 proto.write(PowerProfileProto.CpuCluster.CORE_POWER, corePower); 534 } 535 proto.end(token); 536 } 537 538 // wifi.scan 539 writePowerConstantToProto(proto, POWER_WIFI_SCAN, PowerProfileProto.WIFI_SCAN); 540 541 // wifi.on 542 writePowerConstantToProto(proto, POWER_WIFI_ON, PowerProfileProto.WIFI_ON); 543 544 // wifi.active 545 writePowerConstantToProto(proto, POWER_WIFI_ACTIVE, PowerProfileProto.WIFI_ACTIVE); 546 547 // wifi.controller.idle 548 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_IDLE, 549 PowerProfileProto.WIFI_CONTROLLER_IDLE); 550 551 // wifi.controller.rx 552 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_RX, 553 PowerProfileProto.WIFI_CONTROLLER_RX); 554 555 // wifi.controller.tx 556 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_TX, 557 PowerProfileProto.WIFI_CONTROLLER_TX); 558 559 // wifi.controller.tx_levels 560 writePowerConstantArrayToProto(proto, POWER_WIFI_CONTROLLER_TX_LEVELS, 561 PowerProfileProto.WIFI_CONTROLLER_TX_LEVELS); 562 563 // wifi.controller.voltage 564 writePowerConstantToProto(proto, POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE, 565 PowerProfileProto.WIFI_CONTROLLER_OPERATING_VOLTAGE); 566 567 // bluetooth.controller.idle 568 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_IDLE, 569 PowerProfileProto.BLUETOOTH_CONTROLLER_IDLE); 570 571 // bluetooth.controller.rx 572 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_RX, 573 PowerProfileProto.BLUETOOTH_CONTROLLER_RX); 574 575 // bluetooth.controller.tx 576 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_TX, 577 PowerProfileProto.BLUETOOTH_CONTROLLER_TX); 578 579 // bluetooth.controller.voltage 580 writePowerConstantToProto(proto, POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, 581 PowerProfileProto.BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE); 582 583 // modem.controller.sleep 584 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_SLEEP, 585 PowerProfileProto.MODEM_CONTROLLER_SLEEP); 586 587 // modem.controller.idle 588 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_IDLE, 589 PowerProfileProto.MODEM_CONTROLLER_IDLE); 590 591 // modem.controller.rx 592 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_RX, 593 PowerProfileProto.MODEM_CONTROLLER_RX); 594 595 // modem.controller.tx 596 writePowerConstantArrayToProto(proto, POWER_MODEM_CONTROLLER_TX, 597 PowerProfileProto.MODEM_CONTROLLER_TX); 598 599 // modem.controller.voltage 600 writePowerConstantToProto(proto, POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE, 601 PowerProfileProto.MODEM_CONTROLLER_OPERATING_VOLTAGE); 602 603 // gps.on 604 writePowerConstantToProto(proto, POWER_GPS_ON, PowerProfileProto.GPS_ON); 605 606 // gps.signalqualitybased 607 writePowerConstantArrayToProto(proto, POWER_GPS_SIGNAL_QUALITY_BASED, 608 PowerProfileProto.GPS_SIGNAL_QUALITY_BASED); 609 610 // gps.voltage 611 writePowerConstantToProto(proto, POWER_GPS_OPERATING_VOLTAGE, 612 PowerProfileProto.GPS_OPERATING_VOLTAGE); 613 614 // bluetooth.on 615 writePowerConstantToProto(proto, POWER_BLUETOOTH_ON, PowerProfileProto.BLUETOOTH_ON); 616 617 // bluetooth.active 618 writePowerConstantToProto(proto, POWER_BLUETOOTH_ACTIVE, 619 PowerProfileProto.BLUETOOTH_ACTIVE); 620 621 // bluetooth.at 622 writePowerConstantToProto(proto, POWER_BLUETOOTH_AT_CMD, 623 PowerProfileProto.BLUETOOTH_AT_CMD); 624 625 // ambient.on 626 writePowerConstantToProto(proto, POWER_AMBIENT_DISPLAY, PowerProfileProto.AMBIENT_DISPLAY); 627 628 // screen.on 629 writePowerConstantToProto(proto, POWER_SCREEN_ON, PowerProfileProto.SCREEN_ON); 630 631 // radio.on 632 writePowerConstantToProto(proto, POWER_RADIO_ON, PowerProfileProto.RADIO_ON); 633 634 // radio.scanning 635 writePowerConstantToProto(proto, POWER_RADIO_SCANNING, PowerProfileProto.RADIO_SCANNING); 636 637 // radio.active 638 writePowerConstantToProto(proto, POWER_RADIO_ACTIVE, PowerProfileProto.RADIO_ACTIVE); 639 640 // screen.full 641 writePowerConstantToProto(proto, POWER_SCREEN_FULL, PowerProfileProto.SCREEN_FULL); 642 643 // audio 644 writePowerConstantToProto(proto, POWER_AUDIO, PowerProfileProto.AUDIO); 645 646 // video 647 writePowerConstantToProto(proto, POWER_VIDEO, PowerProfileProto.VIDEO); 648 649 // camera.flashlight 650 writePowerConstantToProto(proto, POWER_FLASHLIGHT, PowerProfileProto.FLASHLIGHT); 651 652 // memory.bandwidths 653 writePowerConstantToProto(proto, POWER_MEMORY, PowerProfileProto.MEMORY); 654 655 // camera.avg 656 writePowerConstantToProto(proto, POWER_CAMERA, PowerProfileProto.CAMERA); 657 658 // wifi.batchedscan 659 writePowerConstantToProto(proto, POWER_WIFI_BATCHED_SCAN, 660 PowerProfileProto.WIFI_BATCHED_SCAN); 661 662 // battery.capacity 663 writePowerConstantToProto(proto, POWER_BATTERY_CAPACITY, 664 PowerProfileProto.BATTERY_CAPACITY); 665 } 666 667 // Writes items in sPowerItemMap to proto if exists. writePowerConstantToProto(ProtoOutputStream proto, String key, long fieldId)668 private void writePowerConstantToProto(ProtoOutputStream proto, String key, long fieldId) { 669 if (sPowerItemMap.containsKey(key)) { 670 proto.write(fieldId, sPowerItemMap.get(key)); 671 } 672 } 673 674 // Writes items in sPowerArrayMap to proto if exists. writePowerConstantArrayToProto(ProtoOutputStream proto, String key, long fieldId)675 private void writePowerConstantArrayToProto(ProtoOutputStream proto, String key, long fieldId) { 676 if (sPowerArrayMap.containsKey(key)) { 677 for (Double d : sPowerArrayMap.get(key)) { 678 proto.write(fieldId, d); 679 } 680 } 681 } 682 } 683