blob: f4436d383a219a8a631aee353cf6fb2928d6bb38 [file] [log] [blame]
Amith Yamasani244fa5c2009-05-22 14:36:07 -07001/*
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
17package com.android.internal.os;
18
19
20import android.content.Context;
Adam Lesinskie08af192015-03-25 16:42:59 -070021import android.content.res.Resources;
Amith Yamasani244fa5c2009-05-22 14:36:07 -070022import android.content.res.XmlResourceParser;
23
Mike Ma3d422c32017-10-25 11:08:57 -070024import com.android.internal.annotations.VisibleForTesting;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080025import com.android.internal.util.XmlUtils;
Amith Yamasani244fa5c2009-05-22 14:36:07 -070026
27import org.xmlpull.v1.XmlPullParser;
28import org.xmlpull.v1.XmlPullParserException;
29
30import java.io.IOException;
Amith Yamasani3718aaa2009-06-09 06:32:35 -070031import java.util.ArrayList;
Amith Yamasani244fa5c2009-05-22 14:36:07 -070032import java.util.HashMap;
33
34/**
35 * Reports power consumption values for various device activities. Reads values from an XML file.
36 * Customize the XML file for different devices.
37 * [hidden]
38 */
39public class PowerProfile {
40
41 /**
42 * No power consumption, or accounted for elsewhere.
43 */
44 public static final String POWER_NONE = "none";
45
46 /**
Mike Ma3d422c32017-10-25 11:08:57 -070047 * POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
48 * POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
49 * be zero on devices that can go into full CPU power collapse even when a wake
50 * lock is held. Otherwise, this is the power consumption in addition to
51 * POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity.
52 * POWER_CPU_ACTIVE: Power consumption when CPU is running, excluding power consumed by clusters
53 * and cores.
54 *
55 * CPU Power Equation (assume two clusters):
56 * Total power = POWER_CPU_SUSPEND (always added)
57 * + POWER_CPU_IDLE (skip this and below if in power collapse mode)
58 * + POWER_CPU_ACTIVE (skip this and below if CPU is not running, but a wakelock
59 * is held)
60 * + cluster_power.cluster0 + cluster_power.cluster1 (skip cluster not running)
61 * + core_power.cluster0 * num running cores in cluster 0
62 * + core_power.cluster1 * num running cores in cluster 1
Amith Yamasani244fa5c2009-05-22 14:36:07 -070063 */
Mike Ma3d422c32017-10-25 11:08:57 -070064 public static final String POWER_CPU_SUSPEND = "cpu.suspend";
Amith Yamasani244fa5c2009-05-22 14:36:07 -070065 public static final String POWER_CPU_IDLE = "cpu.idle";
Amith Yamasanie43530a2009-08-21 13:11:37 -070066 public static final String POWER_CPU_ACTIVE = "cpu.active";
Amith Yamasani244fa5c2009-05-22 14:36:07 -070067
68 /**
69 * Power consumption when WiFi driver is scanning for networks.
70 */
71 public static final String POWER_WIFI_SCAN = "wifi.scan";
72
73 /**
74 * Power consumption when WiFi driver is on.
75 */
76 public static final String POWER_WIFI_ON = "wifi.on";
77
78 /**
79 * Power consumption when WiFi driver is transmitting/receiving.
80 */
81 public static final String POWER_WIFI_ACTIVE = "wifi.active";
82
Adam Lesinskie08af192015-03-25 16:42:59 -070083 //
84 // Updated power constants. These are not estimated, they are real world
85 // currents and voltages for the underlying bluetooth and wifi controllers.
86 //
87
88 public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle";
89 public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx";
90 public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx";
Roshan Pius2a91e4a2016-03-31 16:33:54 -070091 public static final String POWER_WIFI_CONTROLLER_TX_LEVELS = "wifi.controller.tx_levels";
Adam Lesinskie08af192015-03-25 16:42:59 -070092 public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage";
93
94 public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle";
95 public static final String POWER_BLUETOOTH_CONTROLLER_RX = "bluetooth.controller.rx";
96 public static final String POWER_BLUETOOTH_CONTROLLER_TX = "bluetooth.controller.tx";
97 public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE =
98 "bluetooth.controller.voltage";
Adam Lesinski33dac552015-03-09 15:24:48 -070099
Siddharth Ray2038af82018-01-17 17:40:26 -0800100 public static final String POWER_MODEM_CONTROLLER_SLEEP = "modem.controller.sleep";
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800101 public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle";
102 public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx";
103 public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx";
104 public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE =
105 "modem.controller.voltage";
106
Siddharth Ray0ed2e952018-01-22 11:32:14 -0800107 /**
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700108 * Power consumption when GPS is on.
109 */
110 public static final String POWER_GPS_ON = "gps.on";
111
112 /**
Siddharth Ray0ed2e952018-01-22 11:32:14 -0800113 * GPS power parameters based on signal quality
114 */
115 public static final String POWER_GPS_SIGNAL_QUALITY_BASED = "gps.signalqualitybased";
116 public static final String POWER_GPS_OPERATING_VOLTAGE = "gps.voltage";
117
118 /**
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700119 * Power consumption when Bluetooth driver is on.
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800120 * @deprecated
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700121 */
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800122 @Deprecated
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700123 public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
124
125 /**
126 * Power consumption when Bluetooth driver is transmitting/receiving.
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800127 * @deprecated
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700128 */
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800129 @Deprecated
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700130 public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
131
132 /**
Amith Yamasani3f7e35c2009-07-13 16:02:45 -0700133 * Power consumption when Bluetooth driver gets an AT command.
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800134 * @deprecated
Amith Yamasani3f7e35c2009-07-13 16:02:45 -0700135 */
Adam Lesinski21f76aa2016-01-25 12:27:06 -0800136 @Deprecated
Amith Yamasani3f7e35c2009-07-13 16:02:45 -0700137 public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
138
Adam Lesinski33dac552015-03-09 15:24:48 -0700139
140 /**
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700141 * Power consumption when screen is on, not including the backlight power.
142 */
143 public static final String POWER_SCREEN_ON = "screen.on";
144
145 /**
146 * Power consumption when cell radio is on but not on a call.
147 */
148 public static final String POWER_RADIO_ON = "radio.on";
149
150 /**
Amith Yamasanif37447b2009-10-08 18:28:01 -0700151 * Power consumption when cell radio is hunting for a signal.
152 */
153 public static final String POWER_RADIO_SCANNING = "radio.scanning";
154
155 /**
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700156 * Power consumption when talking on the phone.
157 */
158 public static final String POWER_RADIO_ACTIVE = "radio.active";
159
160 /**
161 * Power consumption at full backlight brightness. If the backlight is at
162 * 50% brightness, then this should be multiplied by 0.5
163 */
164 public static final String POWER_SCREEN_FULL = "screen.full";
165
166 /**
167 * Power consumed by the audio hardware when playing back audio content. This is in addition
168 * to the CPU power, probably due to a DSP and / or amplifier.
169 */
170 public static final String POWER_AUDIO = "dsp.audio";
171
172 /**
173 * Power consumed by any media hardware when playing back video content. This is in addition
174 * to the CPU power, probably due to a DSP.
175 */
176 public static final String POWER_VIDEO = "dsp.video";
177
Dianne Hackbornabc7c492014-06-30 16:57:46 -0700178 /**
Ruben Brunk5b1308f2015-06-03 18:49:27 -0700179 * Average power consumption when camera flashlight is on.
Dianne Hackbornabc7c492014-06-30 16:57:46 -0700180 */
181 public static final String POWER_FLASHLIGHT = "camera.flashlight";
182
Ruben Brunk5b1308f2015-06-03 18:49:27 -0700183 /**
James Carr2dd7e5e2016-07-20 18:48:39 -0700184 * Power consumption when DDR is being used.
185 */
186 public static final String POWER_MEMORY = "memory.bandwidths";
187
188 /**
Ruben Brunk5b1308f2015-06-03 18:49:27 -0700189 * Average power consumption when the camera is on over all standard use cases.
190 *
191 * TODO: Add more fine-grained camera power metrics.
192 */
193 public static final String POWER_CAMERA = "camera.avg";
194
Amith Yamasani169741b2010-05-27 10:37:54 -0700195 /**
Robert Greenwalta029ea12013-09-25 16:38:12 -0700196 * Power consumed by wif batched scaning. Broken down into bins by
197 * Channels Scanned per Hour. May do 1-720 scans per hour of 1-100 channels
198 * for a range of 1-72,000. Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)!
199 */
200 public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan";
201
202 /**
Amith Yamasani169741b2010-05-27 10:37:54 -0700203 * Battery capacity in milliAmpHour (mAh).
204 */
205 public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
206
Mike Ma3d422c32017-10-25 11:08:57 -0700207 /**
208 * A map from Power Use Item to its power consumption.
209 */
210 static final HashMap<String, Double> sPowerItemMap = new HashMap<>();
211 /**
212 * A map from Power Use Item to an array of its power consumption
213 * (for items with variable power e.g. CPU).
214 */
215 static final HashMap<String, Double[]> sPowerArrayMap = new HashMap<>();
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700216
217 private static final String TAG_DEVICE = "device";
218 private static final String TAG_ITEM = "item";
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700219 private static final String TAG_ARRAY = "array";
220 private static final String TAG_ARRAYITEM = "value";
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700221 private static final String ATTR_NAME = "name";
222
jackqdyulei0e3504c2017-08-03 15:46:52 -0700223 private static final Object sLock = new Object();
224
Mike Ma3d422c32017-10-25 11:08:57 -0700225 @VisibleForTesting
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700226 public PowerProfile(Context context) {
Mike Ma3d422c32017-10-25 11:08:57 -0700227 this(context, false);
228 }
229
230 /**
231 * For PowerProfileTest
232 */
233 @VisibleForTesting
234 public PowerProfile(Context context, boolean forTest) {
235 // Read the XML file for the given profile (normally only one per device)
jackqdyulei0e3504c2017-08-03 15:46:52 -0700236 synchronized (sLock) {
Mike Ma3d422c32017-10-25 11:08:57 -0700237 if (sPowerItemMap.size() == 0 && sPowerArrayMap.size() == 0) {
238 readPowerValuesFromXml(context, forTest);
jackqdyulei0e3504c2017-08-03 15:46:52 -0700239 }
240 initCpuClusters();
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700241 }
242 }
243
Mike Ma3d422c32017-10-25 11:08:57 -0700244 private void readPowerValuesFromXml(Context context, boolean forTest) {
245 final int id = forTest ? com.android.internal.R.xml.power_profile_test :
246 com.android.internal.R.xml.power_profile;
Adam Lesinskie08af192015-03-25 16:42:59 -0700247 final Resources resources = context.getResources();
248 XmlResourceParser parser = resources.getXml(id);
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700249 boolean parsingArray = false;
Mike Ma3d422c32017-10-25 11:08:57 -0700250 ArrayList<Double> array = new ArrayList<>();
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700251 String arrayName = null;
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700252
253 try {
254 XmlUtils.beginDocument(parser, TAG_DEVICE);
255
256 while (true) {
257 XmlUtils.nextElement(parser);
258
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700259 String element = parser.getName();
260 if (element == null) break;
Robert Greenwalta029ea12013-09-25 16:38:12 -0700261
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700262 if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
263 // Finish array
Mike Ma3d422c32017-10-25 11:08:57 -0700264 sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()]));
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700265 parsingArray = false;
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700266 }
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700267 if (element.equals(TAG_ARRAY)) {
268 parsingArray = true;
269 array.clear();
270 arrayName = parser.getAttributeValue(null, ATTR_NAME);
271 } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) {
272 String name = null;
273 if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME);
274 if (parser.next() == XmlPullParser.TEXT) {
275 String power = parser.getText();
276 double value = 0;
277 try {
278 value = Double.valueOf(power);
279 } catch (NumberFormatException nfe) {
280 }
281 if (element.equals(TAG_ITEM)) {
Mike Ma3d422c32017-10-25 11:08:57 -0700282 sPowerItemMap.put(name, value);
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700283 } else if (parsingArray) {
284 array.add(value);
285 }
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700286 }
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700287 }
288 }
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700289 if (parsingArray) {
Mike Ma3d422c32017-10-25 11:08:57 -0700290 sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()]));
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700291 }
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700292 } catch (XmlPullParserException e) {
293 throw new RuntimeException(e);
294 } catch (IOException e) {
295 throw new RuntimeException(e);
296 } finally {
297 parser.close();
298 }
Adam Lesinskie08af192015-03-25 16:42:59 -0700299
300 // Now collect other config variables.
Adam Lesinski6832f392015-09-05 18:05:40 -0700301 int[] configResIds = new int[]{
Adam Lesinskie08af192015-03-25 16:42:59 -0700302 com.android.internal.R.integer.config_bluetooth_idle_cur_ma,
303 com.android.internal.R.integer.config_bluetooth_rx_cur_ma,
304 com.android.internal.R.integer.config_bluetooth_tx_cur_ma,
305 com.android.internal.R.integer.config_bluetooth_operating_voltage_mv,
Adam Lesinskie08af192015-03-25 16:42:59 -0700306 };
307
Adam Lesinski6832f392015-09-05 18:05:40 -0700308 String[] configResIdKeys = new String[]{
Adam Lesinskie08af192015-03-25 16:42:59 -0700309 POWER_BLUETOOTH_CONTROLLER_IDLE,
310 POWER_BLUETOOTH_CONTROLLER_RX,
311 POWER_BLUETOOTH_CONTROLLER_TX,
312 POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE,
Adam Lesinskie08af192015-03-25 16:42:59 -0700313 };
314
315 for (int i = 0; i < configResIds.length; i++) {
Roshan Pius2a91e4a2016-03-31 16:33:54 -0700316 String key = configResIdKeys[i];
317 // if we already have some of these parameters in power_profile.xml, ignore the
318 // value in config.xml
Mike Ma3d422c32017-10-25 11:08:57 -0700319 if ((sPowerItemMap.containsKey(key) && sPowerItemMap.get(key) > 0)) {
Roshan Pius2a91e4a2016-03-31 16:33:54 -0700320 continue;
321 }
Adam Lesinskie08af192015-03-25 16:42:59 -0700322 int value = resources.getInteger(configResIds[i]);
323 if (value > 0) {
Mike Ma3d422c32017-10-25 11:08:57 -0700324 sPowerItemMap.put(key, (double) value);
Adam Lesinskie08af192015-03-25 16:42:59 -0700325 }
326 }
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700327 }
328
Adam Lesinski6832f392015-09-05 18:05:40 -0700329 private CpuClusterKey[] mCpuClusters;
330
Mike Ma3d422c32017-10-25 11:08:57 -0700331 private static final String CPU_PER_CLUSTER_CORE_COUNT = "cpu.clusters.cores";
332 private static final String CPU_CLUSTER_POWER_COUNT = "cpu.cluster_power.cluster";
333 private static final String CPU_CORE_SPEED_PREFIX = "cpu.core_speeds.cluster";
334 private static final String CPU_CORE_POWER_PREFIX = "cpu.core_power.cluster";
Adam Lesinski6832f392015-09-05 18:05:40 -0700335
Adam Lesinski6832f392015-09-05 18:05:40 -0700336 private void initCpuClusters() {
Mike Ma3d422c32017-10-25 11:08:57 -0700337 if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
338 final Double[] data = sPowerArrayMap.get(CPU_PER_CLUSTER_CORE_COUNT);
339 mCpuClusters = new CpuClusterKey[data.length];
340 for (int cluster = 0; cluster < data.length; cluster++) {
341 int numCpusInCluster = (int) Math.round(data[cluster]);
342 mCpuClusters[cluster] = new CpuClusterKey(
343 CPU_CORE_SPEED_PREFIX + cluster, CPU_CLUSTER_POWER_COUNT + cluster,
344 CPU_CORE_POWER_PREFIX + cluster, numCpusInCluster);
345 }
346 } else {
Adam Lesinski6832f392015-09-05 18:05:40 -0700347 // Default to single.
348 mCpuClusters = new CpuClusterKey[1];
Mike Ma3d422c32017-10-25 11:08:57 -0700349 int numCpus = 1;
350 if (sPowerItemMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
351 numCpus = (int) Math.round(sPowerItemMap.get(CPU_PER_CLUSTER_CORE_COUNT));
Adam Lesinski6832f392015-09-05 18:05:40 -0700352 }
Mike Ma3d422c32017-10-25 11:08:57 -0700353 mCpuClusters[0] = new CpuClusterKey(CPU_CORE_SPEED_PREFIX + 0,
354 CPU_CLUSTER_POWER_COUNT + 0, CPU_CORE_POWER_PREFIX + 0, numCpus);
Adam Lesinski6832f392015-09-05 18:05:40 -0700355 }
356 }
357
358 public static class CpuClusterKey {
Mike Ma3d422c32017-10-25 11:08:57 -0700359 private final String freqKey;
360 private final String clusterPowerKey;
361 private final String corePowerKey;
Adam Lesinski6832f392015-09-05 18:05:40 -0700362 private final int numCpus;
363
Mike Ma3d422c32017-10-25 11:08:57 -0700364 private CpuClusterKey(String freqKey, String clusterPowerKey,
365 String corePowerKey, int numCpus) {
366 this.freqKey = freqKey;
367 this.clusterPowerKey = clusterPowerKey;
368 this.corePowerKey = corePowerKey;
Adam Lesinski6832f392015-09-05 18:05:40 -0700369 this.numCpus = numCpus;
370 }
371 }
372
373 public int getNumCpuClusters() {
374 return mCpuClusters.length;
375 }
376
Mike Ma3d422c32017-10-25 11:08:57 -0700377 public int getNumCoresInCpuCluster(int cluster) {
378 return mCpuClusters[cluster].numCpus;
Adam Lesinski6832f392015-09-05 18:05:40 -0700379 }
380
Mike Ma3d422c32017-10-25 11:08:57 -0700381 public int getNumSpeedStepsInCpuCluster(int cluster) {
382 if (cluster < 0 || cluster >= mCpuClusters.length) {
383 return 0; // index out of bound
384 }
385 if (sPowerArrayMap.containsKey(mCpuClusters[cluster].freqKey)) {
386 return sPowerArrayMap.get(mCpuClusters[cluster].freqKey).length;
Adam Lesinski6832f392015-09-05 18:05:40 -0700387 }
388 return 1; // Only one speed
389 }
390
Mike Ma3d422c32017-10-25 11:08:57 -0700391 public double getAveragePowerForCpuCluster(int cluster) {
Adam Lesinski6832f392015-09-05 18:05:40 -0700392 if (cluster >= 0 && cluster < mCpuClusters.length) {
Mike Ma3d422c32017-10-25 11:08:57 -0700393 return getAveragePower(mCpuClusters[cluster].clusterPowerKey);
394 }
395 return 0;
396 }
397
398 public double getAveragePowerForCpuCore(int cluster, int step) {
399 if (cluster >= 0 && cluster < mCpuClusters.length) {
400 return getAveragePower(mCpuClusters[cluster].corePowerKey, step);
Adam Lesinski6832f392015-09-05 18:05:40 -0700401 }
402 return 0;
403 }
404
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700405 /**
James Carr2dd7e5e2016-07-20 18:48:39 -0700406 * Returns the number of memory bandwidth buckets defined in power_profile.xml, or a
407 * default value if the subsystem has no recorded value.
408 * @return the number of memory bandwidth buckets.
409 */
410 public int getNumElements(String key) {
Mike Ma3d422c32017-10-25 11:08:57 -0700411 if (sPowerItemMap.containsKey(key)) {
412 return 1;
413 } else if (sPowerArrayMap.containsKey(key)) {
414 return sPowerArrayMap.get(key).length;
James Carr2dd7e5e2016-07-20 18:48:39 -0700415 }
416 return 0;
417 }
418
419 /**
Adam Lesinski33dac552015-03-09 15:24:48 -0700420 * Returns the average current in mA consumed by the subsystem, or the given
421 * default value if the subsystem has no recorded value.
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700422 * @param type the subsystem type
Adam Lesinski33dac552015-03-09 15:24:48 -0700423 * @param defaultValue the value to return if the subsystem has no recorded value.
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700424 * @return the average current in milliAmps.
425 */
Adam Lesinski33dac552015-03-09 15:24:48 -0700426 public double getAveragePowerOrDefault(String type, double defaultValue) {
Mike Ma3d422c32017-10-25 11:08:57 -0700427 if (sPowerItemMap.containsKey(type)) {
428 return sPowerItemMap.get(type);
429 } else if (sPowerArrayMap.containsKey(type)) {
430 return sPowerArrayMap.get(type)[0];
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700431 } else {
Adam Lesinski33dac552015-03-09 15:24:48 -0700432 return defaultValue;
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700433 }
434 }
Adam Lesinski33dac552015-03-09 15:24:48 -0700435
436 /**
437 * Returns the average current in mA consumed by the subsystem
438 * @param type the subsystem type
439 * @return the average current in milliAmps.
440 */
441 public double getAveragePower(String type) {
442 return getAveragePowerOrDefault(type, 0);
443 }
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700444
445 /**
Amith Yamasanie43530a2009-08-21 13:11:37 -0700446 * Returns the average current in mA consumed by the subsystem for the given level.
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700447 * @param type the subsystem type
448 * @param level the level of power at which the subsystem is running. For instance, the
Amith Yamasanie43530a2009-08-21 13:11:37 -0700449 * signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700450 * If there is no data for multiple levels, the level is ignored.
451 * @return the average current in milliAmps.
452 */
453 public double getAveragePower(String type, int level) {
Mike Ma3d422c32017-10-25 11:08:57 -0700454 if (sPowerItemMap.containsKey(type)) {
455 return sPowerItemMap.get(type);
456 } else if (sPowerArrayMap.containsKey(type)) {
457 final Double[] values = sPowerArrayMap.get(type);
458 if (values.length > level && level >= 0) {
459 return values[level];
460 } else if (level < 0 || values.length == 0) {
461 return 0;
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700462 } else {
Mike Ma3d422c32017-10-25 11:08:57 -0700463 return values[values.length - 1];
Amith Yamasani3718aaa2009-06-09 06:32:35 -0700464 }
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700465 } else {
466 return 0;
467 }
468 }
Amith Yamasanie43530a2009-08-21 13:11:37 -0700469
Amith Yamasani169741b2010-05-27 10:37:54 -0700470 /**
471 * Returns the battery capacity, if available, in milli Amp Hours. If not available,
472 * it returns zero.
473 * @return the battery capacity in mAh
474 */
475 public double getBatteryCapacity() {
476 return getAveragePower(POWER_BATTERY_CAPACITY);
477 }
Amith Yamasani244fa5c2009-05-22 14:36:07 -0700478}