Merge change 3857 into donut

* changes:
  Allow arrays of values for power profile data.
This commit is contained in:
Android (Google) Code Review
2009-06-10 19:50:22 -07:00
3 changed files with 218 additions and 45 deletions

View File

@@ -30,9 +30,11 @@ import android.util.PrintWriterPrinter;
import android.util.Printer; import android.util.Printer;
import android.util.SparseArray; import android.util.SparseArray;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
@@ -53,7 +55,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS' private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version // Current on-disk Parcel version
private static final int VERSION = 38; private static final int VERSION = 39;
private final File mFile; private final File mFile;
private final File mBackupFile; private final File mBackupFile;
@@ -149,6 +151,15 @@ public final class BatteryStatsImpl extends BatteryStats {
long mLastWriteTime = 0; // Milliseconds 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. * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
*/ */
@@ -894,6 +905,39 @@ public final class BatteryStatsImpl extends BatteryStats {
return kwlt; 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) { public void doUnplug(long batteryUptime, long batteryRealtime) {
for (int iu = mUidStats.size() - 1; iu >= 0; iu--) { for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
Uid u = mUidStats.valueAt(iu); Uid u = mUidStats.valueAt(iu);
@@ -905,6 +949,14 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i = mUnpluggables.size() - 1; i >= 0; i--) { for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime); 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) { public void doPlug(long batteryUptime, long batteryRealtime) {
@@ -922,6 +974,13 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i = mUnpluggables.size() - 1; i >= 0; i--) { for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).plug(batteryUptime, batteryRealtime); 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) { public void noteStartGps(int uid) {
@@ -1039,6 +1098,7 @@ public final class BatteryStatsImpl extends BatteryStats {
break; break;
} }
} }
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != bin) { if (mPhoneDataConnectionType != bin) {
if (mPhoneDataConnectionType >= 0) { if (mPhoneDataConnectionType >= 0) {
mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this); mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this);
@@ -2702,6 +2762,43 @@ public final class BatteryStatsImpl extends BatteryStats {
return getBatteryRealtimeLocked(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 @Override
public int getDischargeStartLevel() { public int getDischargeStartLevel() {
synchronized(this) { synchronized(this) {
@@ -3227,6 +3324,18 @@ public final class BatteryStatsImpl extends BatteryStats {
mDischargeCurrentLevel = in.readInt(); mDischargeCurrentLevel = in.readInt();
mLastWriteTime = in.readLong(); 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(); mKernelWakelockStats.clear();
int NKW = in.readInt(); int NKW = in.readInt();
for (int ikw = 0; ikw < NKW; ikw++) { for (int ikw = 0; ikw < NKW; ikw++) {
@@ -3301,6 +3410,14 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(mDischargeCurrentLevel); out.writeInt(mDischargeCurrentLevel);
out.writeLong(mLastWriteTime); 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()); out.writeInt(mKernelWakelockStats.size());
for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
SamplingTimer kwlt = ent.getValue(); SamplingTimer kwlt = ent.getValue();

View File

@@ -26,6 +26,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
/** /**
@@ -118,26 +119,28 @@ public class PowerProfile {
*/ */
public static final String POWER_VIDEO = "dsp.video"; 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_DEVICE = "device";
private static final String TAG_ITEM = "item"; 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"; 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 // Read the XML file for the given profile (normally only one per
// device) // device)
if (sPowerMap.size() == 0) { if (sPowerMap.size() == 0) {
readPowerValuesFromXml(context, profile); readPowerValuesFromXml(context);
} }
} }
private void readPowerValuesFromXml(Context context, CharSequence profile) { private void readPowerValuesFromXml(Context context) {
// FIXME int id = com.android.internal.R.xml.power_profile;
//int id = context.getResources().getIdentifier(profile.toString(), "xml",
// "com.android.internal");
int id = com.android.internal.R.xml.power_profile_default;
XmlResourceParser parser = context.getResources().getXml(id); XmlResourceParser parser = context.getResources().getXml(id);
boolean parsingArray = false;
ArrayList<Double> array = new ArrayList<Double>();
String arrayName = null;
try { try {
XmlUtils.beginDocument(parser, TAG_DEVICE); XmlUtils.beginDocument(parser, TAG_DEVICE);
@@ -146,20 +149,37 @@ public class PowerProfile {
XmlUtils.nextElement(parser); XmlUtils.nextElement(parser);
String element = parser.getName(); String element = parser.getName();
if (element == null || !(element.equals(TAG_ITEM))) { if (element == null) break;
break;
}
String name = parser.getAttributeValue(null, ATTR_NAME); if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
if (parser.next() == XmlPullParser.TEXT) { // Finish array
String power = parser.getText(); sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
double value = 0; parsingArray = false;
try {
value = Double.valueOf(power);
} catch (NumberFormatException nfe) {
}
sPowerMap.put(name, value);
} }
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);
}
}
}
}
if (parsingArray) {
sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
} }
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -177,7 +197,40 @@ public class PowerProfile {
*/ */
public double getAveragePower(String type) { public double getAveragePower(String type) {
if (sPowerMap.containsKey(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 { } else {
return 0; return 0;
} }

View File

@@ -19,19 +19,22 @@
<device name="Android"> <device name="Android">
<item name="none">0</item> <item name="none">0</item>
<item name="screen.on">30</item> <item name="screen.on">0.1</item>
<item name="bluetooth.active">103</item> <item name="bluetooth.active">0.1</item>
<item name="bluetooth.on">5</item> <item name="bluetooth.on">0.1</item>
<item name="screen.full">114</item> <item name="screen.full">0.1</item>
<item name="wifi.on">23</item> <item name="wifi.on">0.1</item>
<item name="wifi.active">200</item> <item name="wifi.active">0.1</item>
<item name="wifi.scan">200</item> <item name="wifi.scan">0.1</item>
<item name="cpu.idle">1.6</item> <item name="cpu.idle">0.1</item>
<item name="cpu.normal">100</item> <item name="cpu.normal">0.2</item>
<item name="cpu.full">140</item> <item name="cpu.full">1</item>
<item name="dsp.audio">70</item> <item name="dsp.audio">0.1</item>
<item name="dsp.video">100</item> <item name="dsp.video">0.1</item>
<item name="radio.on">3</item> <item name="radio.active">1</item>
<item name="radio.active">175</item> <item name="gps.on">1</item>
<item name="gps.on">120</item> <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
<value>1</value>
<value>0.1</value>
</array>
</device> </device>