diff options
author | Amith Yamasani <yamasani@google.com> | 2009-06-09 06:32:35 -0700 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2009-06-10 19:45:28 -0700 |
commit | 3718aaabe6259dcf86a3666ff92d16e4be5da555 (patch) | |
tree | 1f5228a19fea42af66fa63da0fa76f0a2ebb01c6 | |
parent | b81645c868b3d596b5ac56822959feb629a8651e (diff) | |
download | frameworks_base-3718aaabe6259dcf86a3666ff92d16e4be5da555.zip frameworks_base-3718aaabe6259dcf86a3666ff92d16e4be5da555.tar.gz frameworks_base-3718aaabe6259dcf86a3666ff92d16e4be5da555.tar.bz2 |
Allow arrays of values for power profile data.
Parse arrays for data that has different levels with non-linear
power increase.
Track radio data awake_time from kernel and mobile/total data
transfers.
Use dummy values for default power_profile.xml. Actual values will
be in a product overlay.
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 135 | ||||
-rw-r--r-- | core/java/com/android/internal/os/PowerProfile.java | 95 | ||||
-rw-r--r-- | core/res/res/xml/power_profile.xml (renamed from core/res/res/xml/power_profile_default.xml) | 33 |
3 files changed, 218 insertions, 45 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 99a381c..16a3bad 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -30,9 +30,11 @@ import android.util.PrintWriterPrinter; import android.util.Printer; import android.util.SparseArray; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; @@ -53,7 +55,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 38; + private static final int VERSION = 39; private final File mFile; private final File mBackupFile; @@ -94,7 +96,7 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mScreenOn; StopwatchTimer mScreenOnTimer; - + int mScreenBrightnessBin = -1; final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -137,10 +139,10 @@ public final class BatteryStatsImpl extends BatteryStats { long mTrackBatteryUptimeStart; long mTrackBatteryPastRealtime; long mTrackBatteryRealtimeStart; - + long mUnpluggedBatteryUptime; long mUnpluggedBatteryRealtime; - + /* * These keep track of battery levels (1-100) at the last plug event and the last unplug event. */ @@ -149,6 +151,15 @@ public final class BatteryStatsImpl extends BatteryStats { long mLastWriteTime = 0; // Milliseconds + // Mobile data transferred while on battery + private long[] mMobileDataTx = new long[4]; + private long[] mMobileDataRx = new long[4]; + private long[] mTotalDataTx = new long[4]; + private long[] mTotalDataRx = new long[4]; + + private long mRadioDataUptime; + private long mRadioDataStart; + /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ @@ -893,7 +904,40 @@ public final class BatteryStatsImpl extends BatteryStats { } return kwlt; } - + + private void doDataPlug(long[] dataTransfer, long currentBytes) { + dataTransfer[STATS_LAST] = dataTransfer[STATS_UNPLUGGED]; + dataTransfer[STATS_UNPLUGGED] = -1; + } + + private void doDataUnplug(long[] dataTransfer, long currentBytes) { + dataTransfer[STATS_UNPLUGGED] = currentBytes; + } + + private long getCurrentRadioDataUptimeMs() { + try { + File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms"); + if (!awakeTimeFile.exists()) return 0; + BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile)); + String line = br.readLine(); + br.close(); + return Long.parseLong(line); + } catch (NumberFormatException nfe) { + // Nothing + } catch (IOException ioe) { + // Nothing + } + return 0; + } + + public long getRadioDataUptimeMs() { + if (mRadioDataStart == -1) { + return mRadioDataUptime; + } else { + return getCurrentRadioDataUptimeMs() - mRadioDataStart; + } + } + public void doUnplug(long batteryUptime, long batteryRealtime) { for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { Uid u = mUidStats.valueAt(iu); @@ -905,8 +949,16 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i = mUnpluggables.size() - 1; i >= 0; i--) { mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); } + // Track total mobile data + doDataUnplug(mMobileDataRx, NetStat.getMobileRxBytes()); + doDataUnplug(mMobileDataTx, NetStat.getMobileTxBytes()); + doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes()); + doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes()); + // Track radio awake time + mRadioDataStart = getCurrentRadioDataUptimeMs(); + mRadioDataUptime = 0; } - + public void doPlug(long batteryUptime, long batteryRealtime) { for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { Uid u = mUidStats.valueAt(iu); @@ -922,8 +974,15 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i = mUnpluggables.size() - 1; i >= 0; i--) { mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); } + doDataPlug(mMobileDataRx, NetStat.getMobileRxBytes()); + doDataPlug(mMobileDataTx, NetStat.getMobileTxBytes()); + doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes()); + doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes()); + // Track radio awake time + mRadioDataUptime = getRadioDataUptimeMs(); + mRadioDataStart = -1; } - + public void noteStartGps(int uid) { mUidStats.get(uid).noteStartGps(); } @@ -931,7 +990,7 @@ public final class BatteryStatsImpl extends BatteryStats { public void noteStopGps(int uid) { mUidStats.get(uid).noteStopGps(); } - + public void noteScreenOnLocked() { if (!mScreenOn) { mScreenOn = true; @@ -1039,6 +1098,7 @@ public final class BatteryStatsImpl extends BatteryStats { break; } } + if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); if (mPhoneDataConnectionType != bin) { if (mPhoneDataConnectionType >= 0) { mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); @@ -2701,7 +2761,44 @@ public final class BatteryStatsImpl extends BatteryStats { public long getBatteryRealtime(long curTime) { return getBatteryRealtimeLocked(curTime); } - + + private long getTcpBytes(long current, long[] dataBytes, int which) { + if (which == STATS_LAST) { + return dataBytes[STATS_LAST]; + } else { + if (which == STATS_UNPLUGGED) { + if (dataBytes[STATS_UNPLUGGED] < 0) { + return dataBytes[STATS_LAST]; + } else { + return current - dataBytes[STATS_UNPLUGGED]; + } + } else if (which == STATS_TOTAL) { + return (current - dataBytes[STATS_CURRENT]) + dataBytes[STATS_TOTAL]; + } + return current - dataBytes[STATS_CURRENT]; + } + } + + /** Only STATS_UNPLUGGED works properly */ + public long getMobileTcpBytesSent(int which) { + return getTcpBytes(NetStat.getMobileTxBytes(), mMobileDataTx, which); + } + + /** Only STATS_UNPLUGGED works properly */ + public long getMobileTcpBytesReceived(int which) { + return getTcpBytes(NetStat.getMobileRxBytes(), mMobileDataRx, which); + } + + /** Only STATS_UNPLUGGED works properly */ + public long getTotalTcpBytesSent(int which) { + return getTcpBytes(NetStat.getTotalTxBytes(), mTotalDataTx, which); + } + + /** Only STATS_UNPLUGGED works properly */ + public long getTotalTcpBytesReceived(int which) { + return getTcpBytes(NetStat.getTotalRxBytes(), mTotalDataRx, which); + } + @Override public int getDischargeStartLevel() { synchronized(this) { @@ -3227,6 +3324,18 @@ public final class BatteryStatsImpl extends BatteryStats { mDischargeCurrentLevel = in.readInt(); mLastWriteTime = in.readLong(); + mMobileDataRx[STATS_LAST] = in.readLong(); + mMobileDataRx[STATS_UNPLUGGED] = -1; + mMobileDataTx[STATS_LAST] = in.readLong(); + mMobileDataTx[STATS_UNPLUGGED] = -1; + mTotalDataRx[STATS_LAST] = in.readLong(); + mTotalDataRx[STATS_UNPLUGGED] = -1; + mTotalDataTx[STATS_LAST] = in.readLong(); + mTotalDataTx[STATS_UNPLUGGED] = -1; + + mRadioDataUptime = in.readLong(); + mRadioDataStart = -1; + mKernelWakelockStats.clear(); int NKW = in.readInt(); for (int ikw = 0; ikw < NKW; ikw++) { @@ -3301,6 +3410,14 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(mDischargeCurrentLevel); out.writeLong(mLastWriteTime); + out.writeLong(getMobileTcpBytesReceived(STATS_UNPLUGGED)); + out.writeLong(getMobileTcpBytesSent(STATS_UNPLUGGED)); + out.writeLong(getTotalTcpBytesReceived(STATS_UNPLUGGED)); + out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED)); + + // Write radio uptime for data + out.writeLong(getRadioDataUptimeMs()); + out.writeInt(mKernelWakelockStats.size()); for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { SamplingTimer kwlt = ent.getValue(); diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index f08dddd..a37bf6e 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -26,6 +26,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; /** @@ -118,26 +119,28 @@ public class PowerProfile { */ public static final String POWER_VIDEO = "dsp.video"; - static final HashMap<String, Double> sPowerMap = new HashMap<String, Double>(); + static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>(); private static final String TAG_DEVICE = "device"; private static final String TAG_ITEM = "item"; + private static final String TAG_ARRAY = "array"; + private static final String TAG_ARRAYITEM = "value"; private static final String ATTR_NAME = "name"; - public PowerProfile(Context context, CharSequence profile) { + public PowerProfile(Context context) { // Read the XML file for the given profile (normally only one per // device) if (sPowerMap.size() == 0) { - readPowerValuesFromXml(context, profile); + readPowerValuesFromXml(context); } } - private void readPowerValuesFromXml(Context context, CharSequence profile) { - // FIXME - //int id = context.getResources().getIdentifier(profile.toString(), "xml", - // "com.android.internal"); - int id = com.android.internal.R.xml.power_profile_default; + private void readPowerValuesFromXml(Context context) { + int id = com.android.internal.R.xml.power_profile; XmlResourceParser parser = context.getResources().getXml(id); + boolean parsingArray = false; + ArrayList<Double> array = new ArrayList<Double>(); + String arrayName = null; try { XmlUtils.beginDocument(parser, TAG_DEVICE); @@ -145,22 +148,39 @@ public class PowerProfile { while (true) { XmlUtils.nextElement(parser); - String element = parser.getName(); - if (element == null || !(element.equals(TAG_ITEM))) { - break; + String element = parser.getName(); + if (element == null) break; + + if (parsingArray && !element.equals(TAG_ARRAYITEM)) { + // Finish array + sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); + parsingArray = false; } - - String name = parser.getAttributeValue(null, ATTR_NAME); - if (parser.next() == XmlPullParser.TEXT) { - String power = parser.getText(); - double value = 0; - try { - value = Double.valueOf(power); - } catch (NumberFormatException nfe) { + if (element.equals(TAG_ARRAY)) { + parsingArray = true; + array.clear(); + arrayName = parser.getAttributeValue(null, ATTR_NAME); + } else if (element.equals(TAG_ITEM) || element.equals(TAG_ARRAYITEM)) { + String name = null; + if (!parsingArray) name = parser.getAttributeValue(null, ATTR_NAME); + if (parser.next() == XmlPullParser.TEXT) { + String power = parser.getText(); + double value = 0; + try { + value = Double.valueOf(power); + } catch (NumberFormatException nfe) { + } + if (element.equals(TAG_ITEM)) { + sPowerMap.put(name, value); + } else if (parsingArray) { + array.add(value); + } } - sPowerMap.put(name, value); } } + if (parsingArray) { + sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); + } } catch (XmlPullParserException e) { throw new RuntimeException(e); } catch (IOException e) { @@ -177,7 +197,40 @@ public class PowerProfile { */ public double getAveragePower(String type) { if (sPowerMap.containsKey(type)) { - return sPowerMap.get(type); + Object data = sPowerMap.get(type); + if (data instanceof Double[]) { + return ((Double[])data)[0]; + } else { + return (Double) sPowerMap.get(type); + } + } else { + return 0; + } + } + + /** + * Returns the average current in mA consumed by the subsystem for the given level. + * @param type the subsystem type + * @param level the level of power at which the subsystem is running. For instance, the + * signal strength of the cell network between 0 and 4 (if there are 4 bars max.). + * If there is no data for multiple levels, the level is ignored. + * @return the average current in milliAmps. + */ + public double getAveragePower(String type, int level) { + if (sPowerMap.containsKey(type)) { + Object data = sPowerMap.get(type); + if (data instanceof double[]) { + final double[] values = (double[]) data; + if (values.length > level) { + return values[level]; + } else if (values.length < 0) { + return values[0]; + } else { + return values[values.length - 1]; + } + } else { + return (Double) data; + } } else { return 0; } diff --git a/core/res/res/xml/power_profile_default.xml b/core/res/res/xml/power_profile.xml index ceecb1a..859902e 100644 --- a/core/res/res/xml/power_profile_default.xml +++ b/core/res/res/xml/power_profile.xml @@ -19,19 +19,22 @@ <device name="Android"> <item name="none">0</item> - <item name="screen.on">30</item> - <item name="bluetooth.active">103</item> - <item name="bluetooth.on">5</item> - <item name="screen.full">114</item> - <item name="wifi.on">23</item> - <item name="wifi.active">200</item> - <item name="wifi.scan">200</item> - <item name="cpu.idle">1.6</item> - <item name="cpu.normal">100</item> - <item name="cpu.full">140</item> - <item name="dsp.audio">70</item> - <item name="dsp.video">100</item> - <item name="radio.on">3</item> - <item name="radio.active">175</item> - <item name="gps.on">120</item> + <item name="screen.on">0.1</item> + <item name="bluetooth.active">0.1</item> + <item name="bluetooth.on">0.1</item> + <item name="screen.full">0.1</item> + <item name="wifi.on">0.1</item> + <item name="wifi.active">0.1</item> + <item name="wifi.scan">0.1</item> + <item name="cpu.idle">0.1</item> + <item name="cpu.normal">0.2</item> + <item name="cpu.full">1</item> + <item name="dsp.audio">0.1</item> + <item name="dsp.video">0.1</item> + <item name="radio.active">1</item> + <item name="gps.on">1</item> + <array name="radio.on"> <!-- Strength 0 to BINS-1 --> + <value>1</value> + <value>0.1</value> + </array> </device> |