summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2009-06-09 06:32:35 -0700
committerAmith Yamasani <yamasani@google.com>2009-06-10 19:45:28 -0700
commit3718aaabe6259dcf86a3666ff92d16e4be5da555 (patch)
tree1f5228a19fea42af66fa63da0fa76f0a2ebb01c6
parentb81645c868b3d596b5ac56822959feb629a8651e (diff)
downloadframeworks_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.java135
-rw-r--r--core/java/com/android/internal/os/PowerProfile.java95
-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>