PowerProfile.java revision e43530ab571e901f94361078c7c1f970a0bd27f2
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 17package com.android.internal.os; 18 19 20import android.content.Context; 21import android.content.res.XmlResourceParser; 22 23import com.android.internal.util.XmlUtils; 24 25import org.xmlpull.v1.XmlPullParser; 26import org.xmlpull.v1.XmlPullParserException; 27 28import java.io.IOException; 29import java.util.ArrayList; 30import java.util.HashMap; 31 32/** 33 * Reports power consumption values for various device activities. Reads values from an XML file. 34 * Customize the XML file for different devices. 35 * [hidden] 36 */ 37public class PowerProfile { 38 39 /** 40 * No power consumption, or accounted for elsewhere. 41 */ 42 public static final String POWER_NONE = "none"; 43 44 /** 45 * Power consumption when CPU is in power collapse mode. 46 */ 47 public static final String POWER_CPU_IDLE = "cpu.idle"; 48 49 /** 50 * Power consumption when CPU is in power collapse mode. 51 */ 52 public static final String POWER_CPU_ACTIVE = "cpu.active"; 53 54 /** 55 * Power consumption when WiFi driver is scanning for networks. 56 */ 57 public static final String POWER_WIFI_SCAN = "wifi.scan"; 58 59 /** 60 * Power consumption when WiFi driver is on. 61 */ 62 public static final String POWER_WIFI_ON = "wifi.on"; 63 64 /** 65 * Power consumption when WiFi driver is transmitting/receiving. 66 */ 67 public static final String POWER_WIFI_ACTIVE = "wifi.active"; 68 69 /** 70 * Power consumption when GPS is on. 71 */ 72 public static final String POWER_GPS_ON = "gps.on"; 73 74 /** 75 * Power consumption when Bluetooth driver is on. 76 */ 77 public static final String POWER_BLUETOOTH_ON = "bluetooth.on"; 78 79 /** 80 * Power consumption when Bluetooth driver is transmitting/receiving. 81 */ 82 public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active"; 83 84 /** 85 * Power consumption when Bluetooth driver gets an AT command. 86 */ 87 public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at"; 88 89 /** 90 * Power consumption when screen is on, not including the backlight power. 91 */ 92 public static final String POWER_SCREEN_ON = "screen.on"; 93 94 /** 95 * Power consumption when cell radio is on but not on a call. 96 */ 97 public static final String POWER_RADIO_ON = "radio.on"; 98 99 /** 100 * Power consumption when talking on the phone. 101 */ 102 public static final String POWER_RADIO_ACTIVE = "radio.active"; 103 104 /** 105 * Power consumption at full backlight brightness. If the backlight is at 106 * 50% brightness, then this should be multiplied by 0.5 107 */ 108 public static final String POWER_SCREEN_FULL = "screen.full"; 109 110 /** 111 * Power consumed by the audio hardware when playing back audio content. This is in addition 112 * to the CPU power, probably due to a DSP and / or amplifier. 113 */ 114 public static final String POWER_AUDIO = "dsp.audio"; 115 116 /** 117 * Power consumed by any media hardware when playing back video content. This is in addition 118 * to the CPU power, probably due to a DSP. 119 */ 120 public static final String POWER_VIDEO = "dsp.video"; 121 122 public static final String POWER_CPU_SPEEDS = "cpu.speeds"; 123 124 static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>(); 125 126 private static final String TAG_DEVICE = "device"; 127 private static final String TAG_ITEM = "item"; 128 private static final String TAG_ARRAY = "array"; 129 private static final String TAG_ARRAYITEM = "value"; 130 private static final String ATTR_NAME = "name"; 131 132 public PowerProfile(Context context) { 133 // Read the XML file for the given profile (normally only one per 134 // device) 135 if (sPowerMap.size() == 0) { 136 readPowerValuesFromXml(context); 137 } 138 } 139 140 private void readPowerValuesFromXml(Context context) { 141 int id = com.android.internal.R.xml.power_profile; 142 XmlResourceParser parser = context.getResources().getXml(id); 143 boolean parsingArray = false; 144 ArrayList<Double> array = new ArrayList<Double>(); 145 String arrayName = null; 146 147 try { 148 XmlUtils.beginDocument(parser, TAG_DEVICE); 149 150 while (true) { 151 XmlUtils.nextElement(parser); 152 153 String element = parser.getName(); 154 if (element == null) break; 155 156 if (parsingArray && !element.equals(TAG_ARRAYITEM)) { 157 // Finish array 158 sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); 159 parsingArray = false; 160 } 161 if (element.equals(TAG_ARRAY)) { 162 parsingArray = true; 163 array.clear(); 164 arrayName = parser.getAttributeValue(null, ATTR_NAME); 165 } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) { 166 String name = null; 167 if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME); 168 if (parser.next() == XmlPullParser.TEXT) { 169 String power = parser.getText(); 170 double value = 0; 171 try { 172 value = Double.valueOf(power); 173 } catch (NumberFormatException nfe) { 174 } 175 if (element.equals(TAG_ITEM)) { 176 sPowerMap.put(name, value); 177 } else if (parsingArray) { 178 array.add(value); 179 } 180 } 181 } 182 } 183 if (parsingArray) { 184 sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); 185 } 186 } catch (XmlPullParserException e) { 187 throw new RuntimeException(e); 188 } catch (IOException e) { 189 throw new RuntimeException(e); 190 } finally { 191 parser.close(); 192 } 193 } 194 195 /** 196 * Returns the average current in mA consumed by the subsystem 197 * @param type the subsystem type 198 * @return the average current in milliAmps. 199 */ 200 public double getAveragePower(String type) { 201 if (sPowerMap.containsKey(type)) { 202 Object data = sPowerMap.get(type); 203 if (data instanceof Double[]) { 204 return ((Double[])data)[0]; 205 } else { 206 return (Double) sPowerMap.get(type); 207 } 208 } else { 209 return 0; 210 } 211 } 212 213 /** 214 * Returns the average current in mA consumed by the subsystem for the given level. 215 * @param type the subsystem type 216 * @param level the level of power at which the subsystem is running. For instance, the 217 * signal strength of the cell network between 0 and 4 (if there are 4 bars max.) 218 * If there is no data for multiple levels, the level is ignored. 219 * @return the average current in milliAmps. 220 */ 221 public double getAveragePower(String type, int level) { 222 if (sPowerMap.containsKey(type)) { 223 Object data = sPowerMap.get(type); 224 if (data instanceof Double[]) { 225 final Double[] values = (Double[]) data; 226 if (values.length > level && level >= 0) { 227 return values[level]; 228 } else if (level < 0) { 229 return 0; 230 } else { 231 return values[values.length - 1]; 232 } 233 } else { 234 return (Double) data; 235 } 236 } else { 237 return 0; 238 } 239 } 240 241 public int getNumSpeedSteps() { 242 Object value = sPowerMap.get(POWER_CPU_SPEEDS); 243 if (value != null && value instanceof Double[]) { 244 return ((Double[])value).length; 245 } 246 return 1; // Only one speed 247 } 248} 249