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.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();

View File

@@ -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;
}

View File

@@ -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>