Home | History | Annotate | Download | only in os
      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;
     21 import android.content.res.XmlResourceParser;
     22 
     23 import com.android.internal.util.XmlUtils;
     24 
     25 import org.xmlpull.v1.XmlPullParser;
     26 import org.xmlpull.v1.XmlPullParserException;
     27 
     28 import java.io.IOException;
     29 import java.util.ArrayList;
     30 import 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  */
     37 public 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 cell radio is hunting for a signal.
    101      */
    102     public static final String POWER_RADIO_SCANNING = "radio.scanning";
    103 
    104     /**
    105      * Power consumption when talking on the phone.
    106      */
    107     public static final String POWER_RADIO_ACTIVE = "radio.active";
    108 
    109     /**
    110      * Power consumption at full backlight brightness. If the backlight is at
    111      * 50% brightness, then this should be multiplied by 0.5
    112      */
    113     public static final String POWER_SCREEN_FULL = "screen.full";
    114 
    115     /**
    116      * Power consumed by the audio hardware when playing back audio content. This is in addition
    117      * to the CPU power, probably due to a DSP and / or amplifier.
    118      */
    119     public static final String POWER_AUDIO = "dsp.audio";
    120 
    121     /**
    122      * Power consumed by any media hardware when playing back video content. This is in addition
    123      * to the CPU power, probably due to a DSP.
    124      */
    125     public static final String POWER_VIDEO = "dsp.video";
    126 
    127     public static final String POWER_CPU_SPEEDS = "cpu.speeds";
    128 
    129     static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>();
    130 
    131     private static final String TAG_DEVICE = "device";
    132     private static final String TAG_ITEM = "item";
    133     private static final String TAG_ARRAY = "array";
    134     private static final String TAG_ARRAYITEM = "value";
    135     private static final String ATTR_NAME = "name";
    136 
    137     public PowerProfile(Context context) {
    138         // Read the XML file for the given profile (normally only one per
    139         // device)
    140         if (sPowerMap.size() == 0) {
    141             readPowerValuesFromXml(context);
    142         }
    143     }
    144 
    145     private void readPowerValuesFromXml(Context context) {
    146         int id = com.android.internal.R.xml.power_profile;
    147         XmlResourceParser parser = context.getResources().getXml(id);
    148         boolean parsingArray = false;
    149         ArrayList<Double> array = new ArrayList<Double>();
    150         String arrayName = null;
    151 
    152         try {
    153             XmlUtils.beginDocument(parser, TAG_DEVICE);
    154 
    155             while (true) {
    156                 XmlUtils.nextElement(parser);
    157 
    158                 String element = parser.getName();
    159                 if (element == null) break;
    160 
    161                 if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
    162                     // Finish array
    163                     sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
    164                     parsingArray = false;
    165                 }
    166                 if (element.equals(TAG_ARRAY)) {
    167                     parsingArray = true;
    168                     array.clear();
    169                     arrayName = parser.getAttributeValue(null, ATTR_NAME);
    170                 } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) {
    171                     String name = null;
    172                     if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME);
    173                     if (parser.next() == XmlPullParser.TEXT) {
    174                         String power = parser.getText();
    175                         double value = 0;
    176                         try {
    177                             value = Double.valueOf(power);
    178                         } catch (NumberFormatException nfe) {
    179                         }
    180                         if (element.equals(TAG_ITEM)) {
    181                             sPowerMap.put(name, value);
    182                         } else if (parsingArray) {
    183                             array.add(value);
    184                         }
    185                     }
    186                 }
    187             }
    188             if (parsingArray) {
    189                 sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
    190             }
    191         } catch (XmlPullParserException e) {
    192             throw new RuntimeException(e);
    193         } catch (IOException e) {
    194             throw new RuntimeException(e);
    195         } finally {
    196             parser.close();
    197         }
    198     }
    199 
    200     /**
    201      * Returns the average current in mA consumed by the subsystem
    202      * @param type the subsystem type
    203      * @return the average current in milliAmps.
    204      */
    205     public double getAveragePower(String type) {
    206         if (sPowerMap.containsKey(type)) {
    207             Object data = sPowerMap.get(type);
    208             if (data instanceof Double[]) {
    209                 return ((Double[])data)[0];
    210             } else {
    211                 return (Double) sPowerMap.get(type);
    212             }
    213         } else {
    214             return 0;
    215         }
    216     }
    217 
    218     /**
    219      * Returns the average current in mA consumed by the subsystem for the given level.
    220      * @param type the subsystem type
    221      * @param level the level of power at which the subsystem is running. For instance, the
    222      *  signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
    223      *  If there is no data for multiple levels, the level is ignored.
    224      * @return the average current in milliAmps.
    225      */
    226     public double getAveragePower(String type, int level) {
    227         if (sPowerMap.containsKey(type)) {
    228             Object data = sPowerMap.get(type);
    229             if (data instanceof Double[]) {
    230                 final Double[] values = (Double[]) data;
    231                 if (values.length > level && level >= 0) {
    232                     return values[level];
    233                 } else if (level < 0) {
    234                     return 0;
    235                 } else {
    236                     return values[values.length - 1];
    237                 }
    238             } else {
    239                 return (Double) data;
    240             }
    241         } else {
    242             return 0;
    243         }
    244     }
    245 
    246     public int getNumSpeedSteps() {
    247         Object value = sPowerMap.get(POWER_CPU_SPEEDS);
    248         if (value != null && value instanceof Double[]) {
    249             return ((Double[])value).length;
    250         }
    251         return 1; // Only one speed
    252     }
    253 }
    254