Start tracking radio up time.
We now always turn on network state tracking for mobile,
and push this information down to battery stats.
In battery stats we use this to both log the changes in
the history and keep track of the total time the mobile
radio was active.
Power computation is switched over to using this information
to help determine power use, which will hopefully make it
more accurate (not counting inaccuracies in knowing when it
actually goes down).
Note yet done is aggregating this data per-uid, to better
emphasize which apps are causing the radio to be up. Right
now we just spread the total time across all uids weighted
by the total number of packets they have sent and received.
Also put in the battery stats infrastructure for bluetooth to
address issue #12973036: Improve power_profile.xml
Change-Id: I39d11b7ff6ae4f336f253d1cba308d8569de7e0d
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 345ff82..a9b6073 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -549,8 +549,9 @@
public static final int STATE_SENSOR_ON_FLAG = 1<<30;
public static final int STATE_GPS_ON_FLAG = 1<<29;
public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<28;
- public static final int STATE_WIFI_SCAN_FLAG = 1<<29;
+ public static final int STATE_WIFI_SCAN_FLAG = 1<<27;
public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<26;
+ public static final int STATE_MOBILE_RADIO_ACTIVE_FLAG = 1<<25;
public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
// These are on the lower bits used for the command; if they change
// we need to write another int of data.
@@ -882,6 +883,15 @@
*/
public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
+ /**
+ * Returns the time in microseconds that the mobile network has been active
+ * (in a high power state).
+ *
+ * {@hide}
+ */
+ public abstract long getMobileRadioActiveTime(long batteryRealtime, int which);
+
+
public static final int DATA_CONNECTION_NONE = 0;
public static final int DATA_CONNECTION_GPRS = 1;
public static final int DATA_CONNECTION_EDGE = 2;
@@ -933,6 +943,7 @@
new BitDescription(HistoryItem.STATE_WIFI_FULL_LOCK_FLAG, "wifi_full_lock", "Wl"),
new BitDescription(HistoryItem.STATE_WIFI_SCAN_FLAG, "wifi_scan", "Ws"),
new BitDescription(HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG, "wifi_multicast", "Wm"),
+ new BitDescription(HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG, "mobile_radio", "Pr"),
new BitDescription(HistoryItem.STATE_WIFI_RUNNING_FLAG, "wifi_running", "Wr"),
new BitDescription(HistoryItem.STATE_PHONE_SCANNING_FLAG, "phone_scanning", "Psc"),
new BitDescription(HistoryItem.STATE_AUDIO_ON_FLAG, "audio", "a"),
@@ -993,6 +1004,33 @@
public abstract int getBluetoothPingCount();
+ public static final int BLUETOOTH_INACTIVE = 0;
+ public static final int BLUETOOTH_ACTIVE_LOW = 1;
+ public static final int BLUETOOTH_ACTIVE_MEDIUM = 2;
+ public static final int BLUETOOTH_ACTIVE_HIGH = 3;
+
+ static final String[] BLUETOOTH_ACTIVE_NAMES = {
+ "none", "low", "med", "high"
+ };
+
+ public static final int NUM_BLUETOOTH_ACTIVE_TYPES = BLUETOOTH_ACTIVE_HIGH+1;
+
+ /**
+ * Returns the time in microseconds that Bluetooth has been running in the
+ * given active state.
+ *
+ * {@hide}
+ */
+ public abstract long getBluetoothActiveTime(int activeType,
+ long batteryRealtime, int which);
+
+ /**
+ * Returns the number of times the Bluetooth has entered the given active state.
+ *
+ * {@hide}
+ */
+ public abstract int getBluetoothActiveCount(int activeType, int which);
+
public static final int NETWORK_MOBILE_RX_DATA = 0;
public static final int NETWORK_MOBILE_TX_DATA = 1;
public static final int NETWORK_WIFI_RX_DATA = 2;
@@ -1026,19 +1064,6 @@
public abstract long getBatteryUptime(long curTime);
/**
- * @deprecated use getRadioDataUptime
- */
- public long getRadioDataUptimeMs() {
- return getRadioDataUptime() / 1000;
- }
-
- /**
- * Returns the time that the radio was on for data transfers.
- * @return the uptime in microseconds while unplugged
- */
- public abstract long getRadioDataUptime();
-
- /**
* Returns the current battery realtime in microseconds.
*
* @param curTime the amount of elapsed realtime in microseconds.
@@ -1374,7 +1399,7 @@
wifiRunningTime / 1000, bluetoothOnTime / 1000,
mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
fullWakeLockTimeTotal, partialWakeLockTimeTotal,
- getInputEventCount(which));
+ getInputEventCount(which), getMobileRadioActiveTime(batteryRealtime, which));
// Dump screen brightness stats
Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -1395,7 +1420,7 @@
args[i] = getPhoneSignalStrengthCount(i, which);
}
dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
-
+
// Dump network type stats
args = new Object[NUM_DATA_CONNECTION_TYPES];
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
@@ -1408,7 +1433,7 @@
dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
if (which == STATS_SINCE_UNPLUGGED) {
- dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
+ dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
getDischargeCurrentLevel());
}
@@ -1906,9 +1931,8 @@
sb.setLength(0);
sb.append(prefix);
- sb.append(" Radio data uptime when unplugged: ");
- sb.append(getRadioDataUptime() / 1000);
- sb.append(" ms");
+ sb.append(" Mobile radio active time: ");
+ formatTimeMs(sb, getMobileRadioActiveTime(batteryRealtime, which) / 1000);
pw.println(sb.toString());
sb.setLength(0);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 9a04760..18d5668 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -51,6 +51,7 @@
void noteScreenOff();
void noteInputEvent();
void noteUserActivity(int uid, int event);
+ void noteDataConnectionActive(String label, boolean active);
void notePhoneOn();
void notePhoneOff();
void notePhoneSignalStrength(in SignalStrength signalStrength);
@@ -63,6 +64,7 @@
void noteWifiStopped(in WorkSource ws);
void noteBluetoothOn();
void noteBluetoothOff();
+ void noteBluetoothActiveState(int actType);
void noteFullWifiLockAcquired(int uid);
void noteFullWifiLockReleased(int uid);
void noteWifiScanStarted(int uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index c22a5e9..8a15c99 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -640,7 +640,8 @@
final long mobileTx = mStats.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
final long mobileData = mobileRx + mobileTx;
- final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
+ final long radioDataUptimeMs
+ = mStats.getMobileRadioActiveTime(mBatteryRealtime, mStatsType) / 1000;
final double mobilePps = radioDataUptimeMs != 0
? mobileData / (double)radioDataUptimeMs
: (((double)MOBILE_BPS) / 8 / 2048);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 82dcbdb..e50e281 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -55,11 +55,9 @@
import com.android.internal.util.JournaledFile;
import com.google.android.collect.Sets;
-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;
@@ -88,7 +86,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 79 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 84 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -276,6 +274,13 @@
boolean mBluetoothOn;
StopwatchTimer mBluetoothOnTimer;
+ int mBluetoothActiveType = -1;
+ final StopwatchTimer[] mBluetoothActiveTimer =
+ new StopwatchTimer[NUM_BLUETOOTH_ACTIVE_TYPES];
+
+ boolean mMobileRadioActive;
+ StopwatchTimer mMobileRadioActiveTimer;
+
/** Bluetooth headset object */
BluetoothHeadset mBtHeadset;
@@ -310,9 +315,6 @@
long mLastWriteTime = 0; // Milliseconds
- private long mRadioDataUptime;
- private long mRadioDataStart;
-
private int mBluetoothPingCount;
private int mBluetoothPingStart = -1;
@@ -1432,44 +1434,6 @@
return kwlt;
}
- /**
- * Radio uptime in microseconds when transferring data. This value is very approximate.
- * @return
- */
- private long getCurrentRadioDataUptime() {
- 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) * 1000;
- } catch (NumberFormatException nfe) {
- // Nothing
- } catch (IOException ioe) {
- // Nothing
- }
- return 0;
- }
-
- /**
- * @deprecated use getRadioDataUptime
- */
- public long getRadioDataUptimeMs() {
- return getRadioDataUptime() / 1000;
- }
-
- /**
- * Returns the duration that the cell radio was up for data transfers.
- */
- public long getRadioDataUptime() {
- if (mRadioDataStart == -1) {
- return mRadioDataUptime;
- } else {
- return getCurrentRadioDataUptime() - mRadioDataStart;
- }
- }
-
private int getCurrentBluetoothPingCount() {
if (mBtHeadset != null) {
List<BluetoothDevice> deviceList = mBtHeadset.getConnectedDevices();
@@ -1520,14 +1484,16 @@
}
// Part of initial delta int that specifies the time delta.
- static final int DELTA_TIME_MASK = 0xfffff;
- static final int DELTA_TIME_LONG = 0xfffff; // The delta is a following long
- static final int DELTA_TIME_INT = 0xffffe; // The delta is a following int
- static final int DELTA_TIME_ABS = 0xffffd; // Following is an entire abs update.
+ static final int DELTA_TIME_MASK = 0x7ffff;
+ static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long
+ static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int
+ static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update.
// Flag in delta int: a new battery level int follows.
- static final int DELTA_BATTERY_LEVEL_FLAG = 0x00100000;
+ static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000;
// Flag in delta int: a new full state and battery status int follows.
- static final int DELTA_STATE_FLAG = 0x00200000;
+ static final int DELTA_STATE_FLAG = 0x00100000;
+ // Flag in delta int: a new full state2 int follows.
+ static final int DELTA_STATE2_FLAG = 0x00200000;
// Flag in delta int: contains a wakelock tag.
static final int DELTA_WAKELOCK_FLAG = 0x00400000;
// Flag in delta int: contains an event description.
@@ -1963,10 +1929,6 @@
mUnpluggables.get(i).unplug(elapsedRealtime, batteryUptime, batteryRealtime);
}
- // Track radio awake time
- mRadioDataStart = getCurrentRadioDataUptime();
- mRadioDataUptime = 0;
-
// Track bt headset ping count
mBluetoothPingStart = getCurrentBluetoothPingCount();
mBluetoothPingCount = 0;
@@ -1977,10 +1939,6 @@
mUnpluggables.get(i).plug(elapsedRealtime, batteryUptime, batteryRealtime);
}
- // Track radio awake time
- mRadioDataUptime = getRadioDataUptime();
- mRadioDataStart = -1;
-
// Track bt headset ping count
mBluetoothPingCount = getBluetoothPingCount();
mBluetoothPingStart = -1;
@@ -2378,6 +2336,27 @@
getUidStatsLocked(uid).noteUserActivityLocked(event);
}
+ public void noteDataConnectionActive(String label, boolean active) {
+ try {
+ int type = Integer.parseInt(label);
+ if (ConnectivityManager.isNetworkTypeMobile(type)) {
+ if (mMobileRadioActive != active) {
+ if (active) mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+ else mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(SystemClock.elapsedRealtime());
+ mMobileRadioActive = active;
+ if (active) mMobileRadioActiveTimer.startRunningLocked(this);
+ else mMobileRadioActiveTimer.stopRunningLocked(this);
+ }
+ }
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Bad data connection label: " + label, e);
+ return;
+ }
+ }
+
public void notePhoneOnLocked() {
if (!mPhoneOn) {
mHistoryCur.states |= HistoryItem.STATE_PHONE_IN_CALL_FLAG;
@@ -2763,6 +2742,17 @@
}
}
+ public void noteBluetoothActiveStateLocked(int actType) {
+ if (DEBUG) Log.i(TAG, "Bluetooth active -> " + actType);
+ if (mBluetoothActiveType != actType) {
+ if (mBluetoothActiveType >= 0) {
+ mBluetoothActiveTimer[mBluetoothActiveType].stopRunningLocked(this);
+ }
+ mBluetoothActiveType = actType;
+ mBluetoothActiveTimer[actType].startRunningLocked(this);
+ }
+ }
+
int mWifiFullLockNesting = 0;
public void noteFullWifiLockAcquiredLocked(int uid) {
@@ -2971,6 +2961,10 @@
return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
+ @Override public long getMobileRadioActiveTime(long batteryRealtime, int which) {
+ return mMobileRadioActiveTimer.getTotalTimeLocked(batteryRealtime, which);
+ }
+
@Override public long getWifiOnTime(long batteryRealtime, int which) {
return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@@ -2983,6 +2977,16 @@
return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
+ @Override public long getBluetoothActiveTime(int actType,
+ long batteryRealtime, int which) {
+ return mBluetoothActiveTimer[actType].getTotalTimeLocked(
+ batteryRealtime, which);
+ }
+
+ @Override public int getBluetoothActiveCount(int actType, int which) {
+ return mBluetoothActiveTimer[actType].getCountLocked(which);
+ }
+
@Override
public long getNetworkActivityBytes(int type, int which) {
if (type >= 0 && type < mNetworkByteActivityCounters.length) {
@@ -4966,9 +4970,13 @@
mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
}
+ mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables);
mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ mBluetoothActiveTimer[i] = new StopwatchTimer(null, -500-i, null, mUnpluggables);
+ }
mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
mOnBattery = mOnBatteryInternal = false;
@@ -5225,9 +5233,13 @@
mNetworkByteActivityCounters[i].reset(false);
mNetworkPacketActivityCounters[i].reset(false);
}
+ mMobileRadioActiveTimer.reset(this, false);
mWifiOnTimer.reset(this, false);
mGlobalWifiRunningTimer.reset(this, false);
mBluetoothOnTimer.reset(this, false);
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ mBluetoothActiveTimer[i].reset(this, false);
+ }
for (int i=0; i<mUidStats.size(); i++) {
if (mUidStats.valueAt(i).reset()) {
@@ -6119,12 +6131,17 @@
mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
}
+ mMobileRadioActive = false;
+ mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
mWifiOn = false;
mWifiOnTimer.readSummaryFromParcelLocked(in);
mGlobalWifiRunning = false;
mGlobalWifiRunningTimer.readSummaryFromParcelLocked(in);
mBluetoothOn = false;
mBluetoothOnTimer.readSummaryFromParcelLocked(in);
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ mBluetoothActiveTimer[i].readSummaryFromParcelLocked(in);
+ }
int NKW = in.readInt();
if (NKW > 10000) {
@@ -6340,9 +6357,13 @@
mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
}
+ mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ mBluetoothActiveTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+ }
out.writeInt(mKernelWakelockStats.size());
for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
@@ -6574,12 +6595,18 @@
mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
}
+ mMobileRadioActive = false;
+ mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables, in);
mWifiOn = false;
mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mGlobalWifiRunning = false;
mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mBluetoothOn = false;
mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ mBluetoothActiveTimer[i] = new StopwatchTimer(null, -500-i,
+ null, mUnpluggables, in);
+ }
mUptime = in.readLong();
mUptimeStart = in.readLong();
mLastUptime = 0;
@@ -6604,9 +6631,6 @@
mDischargeAmountScreenOffSinceCharge = in.readInt();
mLastWriteTime = in.readLong();
- mRadioDataUptime = in.readLong();
- mRadioDataStart = -1;
-
mBluetoothPingCount = in.readInt();
mBluetoothPingStart = -1;
@@ -6685,9 +6709,13 @@
mNetworkByteActivityCounters[i].writeToParcel(out);
mNetworkPacketActivityCounters[i].writeToParcel(out);
}
+ mMobileRadioActiveTimer.writeToParcel(out, batteryRealtime);
mWifiOnTimer.writeToParcel(out, batteryRealtime);
mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ mBluetoothActiveTimer[i].writeToParcel(out, batteryRealtime);
+ }
out.writeLong(mUptime);
out.writeLong(mUptimeStart);
out.writeLong(mRealtime);
@@ -6709,9 +6737,6 @@
out.writeInt(mDischargeAmountScreenOffSinceCharge);
out.writeLong(mLastWriteTime);
- // Write radio uptime for data
- out.writeLong(getRadioDataUptime());
-
out.writeInt(getBluetoothPingCount());
if (inclUids) {
@@ -6786,12 +6811,18 @@
pr.println("*** Data connection type #" + i + ":");
mPhoneDataConnectionsTimer[i].logState(pr, " ");
}
+ pr.println("*** Mobile network active timer:");
+ mMobileRadioActiveTimer.logState(pr, " ");
pr.println("*** Wifi timer:");
mWifiOnTimer.logState(pr, " ");
pr.println("*** WifiRunning timer:");
mGlobalWifiRunningTimer.logState(pr, " ");
pr.println("*** Bluetooth timer:");
mBluetoothOnTimer.logState(pr, " ");
+ for (int i=0; i<NUM_BLUETOOTH_ACTIVE_TYPES; i++) {
+ pr.println("*** Bluetooth active type #" + i + ":");
+ mBluetoothActiveTimer[i].logState(pr, " ");
+ }
}
super.dumpLocked(context, pw, isUnpluggedOnly, reqUid, historyOnly);
}