Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 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.content.Context; |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 21 | import android.content.res.Resources; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 22 | import android.content.res.XmlResourceParser; |
| 23 | |
Dianne Hackborn | 2269d157 | 2010-02-24 19:54:22 -0800 | [diff] [blame] | 24 | import com.android.internal.util.XmlUtils; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 25 | |
| 26 | import org.xmlpull.v1.XmlPullParser; |
| 27 | import org.xmlpull.v1.XmlPullParserException; |
| 28 | |
| 29 | import java.io.IOException; |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 30 | import java.util.ArrayList; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 31 | import java.util.HashMap; |
| 32 | |
| 33 | /** |
| 34 | * Reports power consumption values for various device activities. Reads values from an XML file. |
| 35 | * Customize the XML file for different devices. |
| 36 | * [hidden] |
| 37 | */ |
| 38 | public class PowerProfile { |
| 39 | |
| 40 | /** |
| 41 | * No power consumption, or accounted for elsewhere. |
| 42 | */ |
| 43 | public static final String POWER_NONE = "none"; |
| 44 | |
| 45 | /** |
| 46 | * Power consumption when CPU is in power collapse mode. |
| 47 | */ |
| 48 | public static final String POWER_CPU_IDLE = "cpu.idle"; |
| 49 | |
| 50 | /** |
Dianne Hackborn | 0c8b4d3 | 2010-11-08 19:10:58 -0800 | [diff] [blame] | 51 | * Power consumption when CPU is awake (when a wake lock is held). This |
| 52 | * should be 0 on devices that can go into full CPU power collapse even |
| 53 | * when a wake lock is held. Otherwise, this is the power consumption in |
Adam Lesinski | 76a267b | 2016-04-20 13:04:59 -0700 | [diff] [blame] | 54 | * addition to POWER_CPU_IDLE due to a wake lock being held but with no |
Dianne Hackborn | 0c8b4d3 | 2010-11-08 19:10:58 -0800 | [diff] [blame] | 55 | * CPU activity. |
| 56 | */ |
| 57 | public static final String POWER_CPU_AWAKE = "cpu.awake"; |
| 58 | |
| 59 | /** |
Amith Yamasani | e43530a | 2009-08-21 13:11:37 -0700 | [diff] [blame] | 60 | * Power consumption when CPU is in power collapse mode. |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 61 | */ |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 62 | @Deprecated |
Amith Yamasani | e43530a | 2009-08-21 13:11:37 -0700 | [diff] [blame] | 63 | public static final String POWER_CPU_ACTIVE = "cpu.active"; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 64 | |
| 65 | /** |
| 66 | * Power consumption when WiFi driver is scanning for networks. |
| 67 | */ |
| 68 | public static final String POWER_WIFI_SCAN = "wifi.scan"; |
| 69 | |
| 70 | /** |
| 71 | * Power consumption when WiFi driver is on. |
| 72 | */ |
| 73 | public static final String POWER_WIFI_ON = "wifi.on"; |
| 74 | |
| 75 | /** |
| 76 | * Power consumption when WiFi driver is transmitting/receiving. |
| 77 | */ |
| 78 | public static final String POWER_WIFI_ACTIVE = "wifi.active"; |
| 79 | |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 80 | // |
| 81 | // Updated power constants. These are not estimated, they are real world |
| 82 | // currents and voltages for the underlying bluetooth and wifi controllers. |
| 83 | // |
| 84 | |
| 85 | public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle"; |
| 86 | public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx"; |
| 87 | public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx"; |
Roshan Pius | 2a91e4a | 2016-03-31 16:33:54 -0700 | [diff] [blame] | 88 | public static final String POWER_WIFI_CONTROLLER_TX_LEVELS = "wifi.controller.tx_levels"; |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 89 | public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage"; |
| 90 | |
| 91 | public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle"; |
| 92 | public static final String POWER_BLUETOOTH_CONTROLLER_RX = "bluetooth.controller.rx"; |
| 93 | public static final String POWER_BLUETOOTH_CONTROLLER_TX = "bluetooth.controller.tx"; |
| 94 | public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE = |
| 95 | "bluetooth.controller.voltage"; |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 96 | |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 97 | public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle"; |
| 98 | public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx"; |
| 99 | public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx"; |
| 100 | public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE = |
| 101 | "modem.controller.voltage"; |
| 102 | |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 103 | /** |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 104 | * Power consumption when GPS is on. |
| 105 | */ |
| 106 | public static final String POWER_GPS_ON = "gps.on"; |
| 107 | |
| 108 | /** |
| 109 | * Power consumption when Bluetooth driver is on. |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 110 | * @deprecated |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 111 | */ |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 112 | @Deprecated |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 113 | public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; |
| 114 | |
| 115 | /** |
| 116 | * Power consumption when Bluetooth driver is transmitting/receiving. |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 117 | * @deprecated |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 118 | */ |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 119 | @Deprecated |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 120 | public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; |
| 121 | |
| 122 | /** |
Amith Yamasani | 3f7e35c | 2009-07-13 16:02:45 -0700 | [diff] [blame] | 123 | * Power consumption when Bluetooth driver gets an AT command. |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 124 | * @deprecated |
Amith Yamasani | 3f7e35c | 2009-07-13 16:02:45 -0700 | [diff] [blame] | 125 | */ |
Adam Lesinski | 21f76aa | 2016-01-25 12:27:06 -0800 | [diff] [blame] | 126 | @Deprecated |
Amith Yamasani | 3f7e35c | 2009-07-13 16:02:45 -0700 | [diff] [blame] | 127 | public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; |
| 128 | |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 129 | |
| 130 | /** |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 131 | * Power consumption when screen is on, not including the backlight power. |
| 132 | */ |
| 133 | public static final String POWER_SCREEN_ON = "screen.on"; |
| 134 | |
| 135 | /** |
| 136 | * Power consumption when cell radio is on but not on a call. |
| 137 | */ |
| 138 | public static final String POWER_RADIO_ON = "radio.on"; |
| 139 | |
| 140 | /** |
Amith Yamasani | f37447b | 2009-10-08 18:28:01 -0700 | [diff] [blame] | 141 | * Power consumption when cell radio is hunting for a signal. |
| 142 | */ |
| 143 | public static final String POWER_RADIO_SCANNING = "radio.scanning"; |
| 144 | |
| 145 | /** |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 146 | * Power consumption when talking on the phone. |
| 147 | */ |
| 148 | public static final String POWER_RADIO_ACTIVE = "radio.active"; |
| 149 | |
| 150 | /** |
| 151 | * Power consumption at full backlight brightness. If the backlight is at |
| 152 | * 50% brightness, then this should be multiplied by 0.5 |
| 153 | */ |
| 154 | public static final String POWER_SCREEN_FULL = "screen.full"; |
| 155 | |
| 156 | /** |
| 157 | * Power consumed by the audio hardware when playing back audio content. This is in addition |
| 158 | * to the CPU power, probably due to a DSP and / or amplifier. |
| 159 | */ |
| 160 | public static final String POWER_AUDIO = "dsp.audio"; |
| 161 | |
| 162 | /** |
| 163 | * Power consumed by any media hardware when playing back video content. This is in addition |
| 164 | * to the CPU power, probably due to a DSP. |
| 165 | */ |
| 166 | public static final String POWER_VIDEO = "dsp.video"; |
| 167 | |
Dianne Hackborn | abc7c49 | 2014-06-30 16:57:46 -0700 | [diff] [blame] | 168 | /** |
Ruben Brunk | 5b1308f | 2015-06-03 18:49:27 -0700 | [diff] [blame] | 169 | * Average power consumption when camera flashlight is on. |
Dianne Hackborn | abc7c49 | 2014-06-30 16:57:46 -0700 | [diff] [blame] | 170 | */ |
| 171 | public static final String POWER_FLASHLIGHT = "camera.flashlight"; |
| 172 | |
Ruben Brunk | 5b1308f | 2015-06-03 18:49:27 -0700 | [diff] [blame] | 173 | /** |
| 174 | * Average power consumption when the camera is on over all standard use cases. |
| 175 | * |
| 176 | * TODO: Add more fine-grained camera power metrics. |
| 177 | */ |
| 178 | public static final String POWER_CAMERA = "camera.avg"; |
| 179 | |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 180 | @Deprecated |
Amith Yamasani | e43530a | 2009-08-21 13:11:37 -0700 | [diff] [blame] | 181 | public static final String POWER_CPU_SPEEDS = "cpu.speeds"; |
| 182 | |
Amith Yamasani | 169741b | 2010-05-27 10:37:54 -0700 | [diff] [blame] | 183 | /** |
Robert Greenwalt | a029ea1 | 2013-09-25 16:38:12 -0700 | [diff] [blame] | 184 | * Power consumed by wif batched scaning. Broken down into bins by |
| 185 | * Channels Scanned per Hour. May do 1-720 scans per hour of 1-100 channels |
| 186 | * for a range of 1-72,000. Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)! |
| 187 | */ |
| 188 | public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan"; |
| 189 | |
| 190 | /** |
Amith Yamasani | 169741b | 2010-05-27 10:37:54 -0700 | [diff] [blame] | 191 | * Battery capacity in milliAmpHour (mAh). |
| 192 | */ |
| 193 | public static final String POWER_BATTERY_CAPACITY = "battery.capacity"; |
| 194 | |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 195 | static final HashMap<String, Object> sPowerMap = new HashMap<>(); |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 196 | |
| 197 | private static final String TAG_DEVICE = "device"; |
| 198 | private static final String TAG_ITEM = "item"; |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 199 | private static final String TAG_ARRAY = "array"; |
| 200 | private static final String TAG_ARRAYITEM = "value"; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 201 | private static final String ATTR_NAME = "name"; |
| 202 | |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 203 | public PowerProfile(Context context) { |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 204 | // Read the XML file for the given profile (normally only one per |
| 205 | // device) |
| 206 | if (sPowerMap.size() == 0) { |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 207 | readPowerValuesFromXml(context); |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 208 | } |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 209 | initCpuClusters(); |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 210 | } |
| 211 | |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 212 | private void readPowerValuesFromXml(Context context) { |
| 213 | int id = com.android.internal.R.xml.power_profile; |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 214 | final Resources resources = context.getResources(); |
| 215 | XmlResourceParser parser = resources.getXml(id); |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 216 | boolean parsingArray = false; |
| 217 | ArrayList<Double> array = new ArrayList<Double>(); |
| 218 | String arrayName = null; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 219 | |
| 220 | try { |
| 221 | XmlUtils.beginDocument(parser, TAG_DEVICE); |
| 222 | |
| 223 | while (true) { |
| 224 | XmlUtils.nextElement(parser); |
| 225 | |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 226 | String element = parser.getName(); |
| 227 | if (element == null) break; |
Robert Greenwalt | a029ea1 | 2013-09-25 16:38:12 -0700 | [diff] [blame] | 228 | |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 229 | if (parsingArray && !element.equals(TAG_ARRAYITEM)) { |
| 230 | // Finish array |
| 231 | sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); |
| 232 | parsingArray = false; |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 233 | } |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 234 | if (element.equals(TAG_ARRAY)) { |
| 235 | parsingArray = true; |
| 236 | array.clear(); |
| 237 | arrayName = parser.getAttributeValue(null, ATTR_NAME); |
| 238 | } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) { |
| 239 | String name = null; |
| 240 | if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME); |
| 241 | if (parser.next() == XmlPullParser.TEXT) { |
| 242 | String power = parser.getText(); |
| 243 | double value = 0; |
| 244 | try { |
| 245 | value = Double.valueOf(power); |
| 246 | } catch (NumberFormatException nfe) { |
| 247 | } |
| 248 | if (element.equals(TAG_ITEM)) { |
| 249 | sPowerMap.put(name, value); |
| 250 | } else if (parsingArray) { |
| 251 | array.add(value); |
| 252 | } |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 253 | } |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 254 | } |
| 255 | } |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 256 | if (parsingArray) { |
| 257 | sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); |
| 258 | } |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 259 | } catch (XmlPullParserException e) { |
| 260 | throw new RuntimeException(e); |
| 261 | } catch (IOException e) { |
| 262 | throw new RuntimeException(e); |
| 263 | } finally { |
| 264 | parser.close(); |
| 265 | } |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 266 | |
| 267 | // Now collect other config variables. |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 268 | int[] configResIds = new int[]{ |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 269 | com.android.internal.R.integer.config_bluetooth_idle_cur_ma, |
| 270 | com.android.internal.R.integer.config_bluetooth_rx_cur_ma, |
| 271 | com.android.internal.R.integer.config_bluetooth_tx_cur_ma, |
| 272 | com.android.internal.R.integer.config_bluetooth_operating_voltage_mv, |
| 273 | com.android.internal.R.integer.config_wifi_idle_receive_cur_ma, |
| 274 | com.android.internal.R.integer.config_wifi_active_rx_cur_ma, |
| 275 | com.android.internal.R.integer.config_wifi_tx_cur_ma, |
| 276 | com.android.internal.R.integer.config_wifi_operating_voltage_mv, |
| 277 | }; |
| 278 | |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 279 | String[] configResIdKeys = new String[]{ |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 280 | POWER_BLUETOOTH_CONTROLLER_IDLE, |
| 281 | POWER_BLUETOOTH_CONTROLLER_RX, |
| 282 | POWER_BLUETOOTH_CONTROLLER_TX, |
| 283 | POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE, |
| 284 | POWER_WIFI_CONTROLLER_IDLE, |
| 285 | POWER_WIFI_CONTROLLER_RX, |
| 286 | POWER_WIFI_CONTROLLER_TX, |
| 287 | POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE, |
| 288 | }; |
| 289 | |
| 290 | for (int i = 0; i < configResIds.length; i++) { |
Roshan Pius | 2a91e4a | 2016-03-31 16:33:54 -0700 | [diff] [blame] | 291 | String key = configResIdKeys[i]; |
| 292 | // if we already have some of these parameters in power_profile.xml, ignore the |
| 293 | // value in config.xml |
| 294 | if ((sPowerMap.containsKey(key) && (Double) sPowerMap.get(key) > 0)) { |
| 295 | continue; |
| 296 | } |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 297 | int value = resources.getInteger(configResIds[i]); |
| 298 | if (value > 0) { |
Roshan Pius | 2a91e4a | 2016-03-31 16:33:54 -0700 | [diff] [blame] | 299 | sPowerMap.put(key, (double) value); |
Adam Lesinski | e08af19 | 2015-03-25 16:42:59 -0700 | [diff] [blame] | 300 | } |
| 301 | } |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 302 | } |
| 303 | |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 304 | private CpuClusterKey[] mCpuClusters; |
| 305 | |
| 306 | private static final String POWER_CPU_CLUSTER_CORE_COUNT = "cpu.clusters.cores"; |
| 307 | private static final String POWER_CPU_CLUSTER_SPEED_PREFIX = "cpu.speeds.cluster"; |
| 308 | private static final String POWER_CPU_CLUSTER_ACTIVE_PREFIX = "cpu.active.cluster"; |
| 309 | |
Ian Rogers | e09ac05 | 2016-05-27 14:31:19 -0700 | [diff] [blame] | 310 | @SuppressWarnings("deprecation") |
Adam Lesinski | 6832f39 | 2015-09-05 18:05:40 -0700 | [diff] [blame] | 311 | private void initCpuClusters() { |
| 312 | // Figure out how many CPU clusters we're dealing with |
| 313 | final Object obj = sPowerMap.get(POWER_CPU_CLUSTER_CORE_COUNT); |
| 314 | if (obj == null || !(obj instanceof Double[])) { |
| 315 | // Default to single. |
| 316 | mCpuClusters = new CpuClusterKey[1]; |
| 317 | mCpuClusters[0] = new CpuClusterKey(POWER_CPU_SPEEDS, POWER_CPU_ACTIVE, 1); |
| 318 | |
| 319 | } else { |
| 320 | final Double[] array = (Double[]) obj; |
| 321 | mCpuClusters = new CpuClusterKey[array.length]; |
| 322 | for (int cluster = 0; cluster < array.length; cluster++) { |
| 323 | int numCpusInCluster = (int) Math.round(array[cluster]); |
| 324 | mCpuClusters[cluster] = new CpuClusterKey( |
| 325 | POWER_CPU_CLUSTER_SPEED_PREFIX + cluster, |
| 326 | POWER_CPU_CLUSTER_ACTIVE_PREFIX + cluster, |
| 327 | numCpusInCluster); |
| 328 | } |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | public static class CpuClusterKey { |
| 333 | private final String timeKey; |
| 334 | private final String powerKey; |
| 335 | private final int numCpus; |
| 336 | |
| 337 | private CpuClusterKey(String timeKey, String powerKey, int numCpus) { |
| 338 | this.timeKey = timeKey; |
| 339 | this.powerKey = powerKey; |
| 340 | this.numCpus = numCpus; |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | public int getNumCpuClusters() { |
| 345 | return mCpuClusters.length; |
| 346 | } |
| 347 | |
| 348 | public int getNumCoresInCpuCluster(int index) { |
| 349 | return mCpuClusters[index].numCpus; |
| 350 | } |
| 351 | |
| 352 | public int getNumSpeedStepsInCpuCluster(int index) { |
| 353 | Object value = sPowerMap.get(mCpuClusters[index].timeKey); |
| 354 | if (value != null && value instanceof Double[]) { |
| 355 | return ((Double[])value).length; |
| 356 | } |
| 357 | return 1; // Only one speed |
| 358 | } |
| 359 | |
| 360 | public double getAveragePowerForCpu(int cluster, int step) { |
| 361 | if (cluster >= 0 && cluster < mCpuClusters.length) { |
| 362 | return getAveragePower(mCpuClusters[cluster].powerKey, step); |
| 363 | } |
| 364 | return 0; |
| 365 | } |
| 366 | |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 367 | /** |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 368 | * Returns the average current in mA consumed by the subsystem, or the given |
| 369 | * default value if the subsystem has no recorded value. |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 370 | * @param type the subsystem type |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 371 | * @param defaultValue the value to return if the subsystem has no recorded value. |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 372 | * @return the average current in milliAmps. |
| 373 | */ |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 374 | public double getAveragePowerOrDefault(String type, double defaultValue) { |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 375 | if (sPowerMap.containsKey(type)) { |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 376 | Object data = sPowerMap.get(type); |
| 377 | if (data instanceof Double[]) { |
| 378 | return ((Double[])data)[0]; |
| 379 | } else { |
| 380 | return (Double) sPowerMap.get(type); |
| 381 | } |
| 382 | } else { |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 383 | return defaultValue; |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 384 | } |
| 385 | } |
Adam Lesinski | 33dac55 | 2015-03-09 15:24:48 -0700 | [diff] [blame] | 386 | |
| 387 | /** |
| 388 | * Returns the average current in mA consumed by the subsystem |
| 389 | * @param type the subsystem type |
| 390 | * @return the average current in milliAmps. |
| 391 | */ |
| 392 | public double getAveragePower(String type) { |
| 393 | return getAveragePowerOrDefault(type, 0); |
| 394 | } |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 395 | |
| 396 | /** |
Amith Yamasani | e43530a | 2009-08-21 13:11:37 -0700 | [diff] [blame] | 397 | * Returns the average current in mA consumed by the subsystem for the given level. |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 398 | * @param type the subsystem type |
| 399 | * @param level the level of power at which the subsystem is running. For instance, the |
Amith Yamasani | e43530a | 2009-08-21 13:11:37 -0700 | [diff] [blame] | 400 | * signal strength of the cell network between 0 and 4 (if there are 4 bars max.) |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 401 | * If there is no data for multiple levels, the level is ignored. |
| 402 | * @return the average current in milliAmps. |
| 403 | */ |
| 404 | public double getAveragePower(String type, int level) { |
| 405 | if (sPowerMap.containsKey(type)) { |
| 406 | Object data = sPowerMap.get(type); |
Amith Yamasani | 32dbefd | 2009-06-19 09:21:17 -0700 | [diff] [blame] | 407 | if (data instanceof Double[]) { |
| 408 | final Double[] values = (Double[]) data; |
| 409 | if (values.length > level && level >= 0) { |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 410 | return values[level]; |
Ruchi Kandoi | be9cbb1 | 2014-07-02 17:47:40 -0700 | [diff] [blame] | 411 | } else if (level < 0 || values.length == 0) { |
Amith Yamasani | 32dbefd | 2009-06-19 09:21:17 -0700 | [diff] [blame] | 412 | return 0; |
Amith Yamasani | 3718aaa | 2009-06-09 06:32:35 -0700 | [diff] [blame] | 413 | } else { |
| 414 | return values[values.length - 1]; |
| 415 | } |
| 416 | } else { |
| 417 | return (Double) data; |
| 418 | } |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 419 | } else { |
| 420 | return 0; |
| 421 | } |
| 422 | } |
Amith Yamasani | e43530a | 2009-08-21 13:11:37 -0700 | [diff] [blame] | 423 | |
Amith Yamasani | 169741b | 2010-05-27 10:37:54 -0700 | [diff] [blame] | 424 | /** |
| 425 | * Returns the battery capacity, if available, in milli Amp Hours. If not available, |
| 426 | * it returns zero. |
| 427 | * @return the battery capacity in mAh |
| 428 | */ |
| 429 | public double getBatteryCapacity() { |
| 430 | return getAveragePower(POWER_BATTERY_CAPACITY); |
| 431 | } |
Amith Yamasani | 244fa5c | 2009-05-22 14:36:07 -0700 | [diff] [blame] | 432 | } |