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 awake (when a wake lock is held).  This
     51      * should be 0 on devices that can go into full CPU power collapse even
     52      * when a wake lock is held.  Otherwise, this is the power consumption in
     53      * addition to POWERR_CPU_IDLE due to a wake lock being held but with no
     54      * CPU activity.
     55      */
     56     public static final String POWER_CPU_AWAKE = "cpu.awake";
     57 
     58     /**
     59      * Power consumption when CPU is in power collapse mode.
     60      */
     61     public static final String POWER_CPU_ACTIVE = "cpu.active";
     62 
     63     /**
     64      * Power consumption when WiFi driver is scanning for networks.
     65      */
     66     public static final String POWER_WIFI_SCAN = "wifi.scan";
     67 
     68     /**
     69      * Power consumption when WiFi driver is on.
     70      */
     71     public static final String POWER_WIFI_ON = "wifi.on";
     72 
     73     /**
     74      * Power consumption when WiFi driver is transmitting/receiving.
     75      */
     76     public static final String POWER_WIFI_ACTIVE = "wifi.active";
     77 
     78     /**
     79      * Power consumption when GPS is on.
     80      */
     81     public static final String POWER_GPS_ON = "gps.on";
     82 
     83     /**
     84      * Power consumption when Bluetooth driver is on.
     85      */
     86     public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
     87 
     88     /**
     89      * Power consumption when Bluetooth driver is transmitting/receiving.
     90      */
     91     public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
     92 
     93     /**
     94      * Power consumption when Bluetooth driver gets an AT command.
     95      */
     96     public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
     97 
     98     /**
     99      * Power consumption when screen is on, not including the backlight power.
    100      */
    101     public static final String POWER_SCREEN_ON = "screen.on";
    102 
    103     /**
    104      * Power consumption when cell radio is on but not on a call.
    105      */
    106     public static final String POWER_RADIO_ON = "radio.on";
    107 
    108     /**
    109      * Power consumption when cell radio is hunting for a signal.
    110      */
    111     public static final String POWER_RADIO_SCANNING = "radio.scanning";
    112 
    113     /**
    114      * Power consumption when talking on the phone.
    115      */
    116     public static final String POWER_RADIO_ACTIVE = "radio.active";
    117 
    118     /**
    119      * Power consumption at full backlight brightness. If the backlight is at
    120      * 50% brightness, then this should be multiplied by 0.5
    121      */
    122     public static final String POWER_SCREEN_FULL = "screen.full";
    123 
    124     /**
    125      * Power consumed by the audio hardware when playing back audio content. This is in addition
    126      * to the CPU power, probably due to a DSP and / or amplifier.
    127      */
    128     public static final String POWER_AUDIO = "dsp.audio";
    129 
    130     /**
    131      * Power consumed by any media hardware when playing back video content. This is in addition
    132      * to the CPU power, probably due to a DSP.
    133      */
    134     public static final String POWER_VIDEO = "dsp.video";
    135 
    136     /**
    137      * Power consumption when camera flashlight is on.
    138      */
    139     public static final String POWER_FLASHLIGHT = "camera.flashlight";
    140 
    141     public static final String POWER_CPU_SPEEDS = "cpu.speeds";
    142 
    143     /**
    144      * Power consumed by wif batched scaning.  Broken down into bins by
    145      * Channels Scanned per Hour.  May do 1-720 scans per hour of 1-100 channels
    146      * for a range of 1-72,000.  Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)!
    147      */
    148     public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan";
    149 
    150     /**
    151      * Battery capacity in milliAmpHour (mAh).
    152      */
    153     public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
    154 
    155     static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>();
    156 
    157     private static final String TAG_DEVICE = "device";
    158     private static final String TAG_ITEM = "item";
    159     private static final String TAG_ARRAY = "array";
    160     private static final String TAG_ARRAYITEM = "value";
    161     private static final String ATTR_NAME = "name";
    162 
    163     public PowerProfile(Context context) {
    164         // Read the XML file for the given profile (normally only one per
    165         // device)
    166         if (sPowerMap.size() == 0) {
    167             readPowerValuesFromXml(context);
    168         }
    169     }
    170 
    171     private void readPowerValuesFromXml(Context context) {
    172         int id = com.android.internal.R.xml.power_profile;
    173         XmlResourceParser parser = context.getResources().getXml(id);
    174         boolean parsingArray = false;
    175         ArrayList<Double> array = new ArrayList<Double>();
    176         String arrayName = null;
    177 
    178         try {
    179             XmlUtils.beginDocument(parser, TAG_DEVICE);
    180 
    181             while (true) {
    182                 XmlUtils.nextElement(parser);
    183 
    184                 String element = parser.getName();
    185                 if (element == null) break;
    186 
    187                 if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
    188                     // Finish array
    189                     sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
    190                     parsingArray = false;
    191                 }
    192                 if (element.equals(TAG_ARRAY)) {
    193                     parsingArray = true;
    194                     array.clear();
    195                     arrayName = parser.getAttributeValue(null, ATTR_NAME);
    196                 } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) {
    197                     String name = null;
    198                     if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME);
    199                     if (parser.next() == XmlPullParser.TEXT) {
    200                         String power = parser.getText();
    201                         double value = 0;
    202                         try {
    203                             value = Double.valueOf(power);
    204                         } catch (NumberFormatException nfe) {
    205                         }
    206                         if (element.equals(TAG_ITEM)) {
    207                             sPowerMap.put(name, value);
    208                         } else if (parsingArray) {
    209                             array.add(value);
    210                         }
    211                     }
    212                 }
    213             }
    214             if (parsingArray) {
    215                 sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
    216             }
    217         } catch (XmlPullParserException e) {
    218             throw new RuntimeException(e);
    219         } catch (IOException e) {
    220             throw new RuntimeException(e);
    221         } finally {
    222             parser.close();
    223         }
    224     }
    225 
    226     /**
    227      * Returns the average current in mA consumed by the subsystem
    228      * @param type the subsystem type
    229      * @return the average current in milliAmps.
    230      */
    231     public double getAveragePower(String type) {
    232         if (sPowerMap.containsKey(type)) {
    233             Object data = sPowerMap.get(type);
    234             if (data instanceof Double[]) {
    235                 return ((Double[])data)[0];
    236             } else {
    237                 return (Double) sPowerMap.get(type);
    238             }
    239         } else {
    240             return 0;
    241         }
    242     }
    243 
    244     /**
    245      * Returns the average current in mA consumed by the subsystem for the given level.
    246      * @param type the subsystem type
    247      * @param level the level of power at which the subsystem is running. For instance, the
    248      *  signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
    249      *  If there is no data for multiple levels, the level is ignored.
    250      * @return the average current in milliAmps.
    251      */
    252     public double getAveragePower(String type, int level) {
    253         if (sPowerMap.containsKey(type)) {
    254             Object data = sPowerMap.get(type);
    255             if (data instanceof Double[]) {
    256                 final Double[] values = (Double[]) data;
    257                 if (values.length > level && level >= 0) {
    258                     return values[level];
    259                 } else if (level < 0) {
    260                     return 0;
    261                 } else {
    262                     return values[values.length - 1];
    263                 }
    264             } else {
    265                 return (Double) data;
    266             }
    267         } else {
    268             return 0;
    269         }
    270     }
    271 
    272     /**
    273      * Returns the battery capacity, if available, in milli Amp Hours. If not available,
    274      * it returns zero.
    275      * @return the battery capacity in mAh
    276      */
    277     public double getBatteryCapacity() {
    278         return getAveragePower(POWER_BATTERY_CAPACITY);
    279     }
    280 
    281     /**
    282      * Returns the number of speeds that the CPU can be run at.
    283      * @return
    284      */
    285     public int getNumSpeedSteps() {
    286         Object value = sPowerMap.get(POWER_CPU_SPEEDS);
    287         if (value != null && value instanceof Double[]) {
    288             return ((Double[])value).length;
    289         }
    290         return 1; // Only one speed
    291     }
    292 }
    293