Merge branch 'readonly-p4-donut' into donut
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 0e9102f..39d36de 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -89,7 +89,7 @@
/**
* Bump the version on this if the checkin format changes.
*/
- private static final int BATTERY_STATS_CHECKIN_VERSION = 4;
+ private static final int BATTERY_STATS_CHECKIN_VERSION = 5;
private static final long BYTES_PER_KB = 1024;
private static final long BYTES_PER_MB = 1048576; // 1024^2
@@ -100,6 +100,7 @@
private static final String PROCESS_DATA = "pr";
private static final String SENSOR_DATA = "sr";
private static final String WAKELOCK_DATA = "wl";
+ private static final String KERNEL_WAKELOCK_DATA = "kwl";
private static final String NETWORK_DATA = "nt";
private static final String USER_ACTIVITY_DATA = "ua";
private static final String BATTERY_DATA = "bt";
@@ -126,7 +127,7 @@
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
*/
- public abstract int getCount(int which);
+ public abstract int getCountLocked(int which);
/**
* Temporary for debugging.
@@ -145,7 +146,7 @@
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
*/
- public abstract int getCount(int which);
+ public abstract int getCountLocked(int which);
/**
* Returns the total time in microseconds associated with this Timer for the
@@ -155,7 +156,7 @@
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
* @return a time in microseconds
*/
- public abstract long getTotalTime(long batteryRealtime, int which);
+ public abstract long getTotalTimeLocked(long batteryRealtime, int which);
/**
* Temporary for debugging.
@@ -518,6 +519,8 @@
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long computeRealtime(long curTime, int which);
+
+ public abstract Map<String, ? extends Timer> getKernelWakelockStats();
private final static void formatTime(StringBuilder out, long seconds) {
long days = seconds / (60 * 60 * 24);
@@ -607,14 +610,14 @@
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
- long totalTimeMicros = timer.getTotalTime(batteryRealtime, which);
+ long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
long totalTimeMillis = (totalTimeMicros + 500) / 1000;
- int count = timer.getCount(which);
+ int count = timer.getCountLocked(which);
if (totalTimeMillis != 0) {
sb.append(linePrefix);
sb.append(formatTimeMs(totalTimeMillis));
- sb.append(name);
+ sb.append(name != null ? name : "");
sb.append(' ');
sb.append('(');
sb.append(count);
@@ -637,18 +640,17 @@
* @return the line prefix
*/
private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
- String name, int which, String linePrefix) {
+ String name, int which, String linePrefix) {
long totalTimeMicros = 0;
int count = 0;
if (timer != null) {
- totalTimeMicros = timer.getTotalTime(now, which);
- count = timer.getCount(which);
+ totalTimeMicros = timer.getTotalTimeLocked(now, which);
+ count = timer.getCountLocked(which);
}
sb.append(linePrefix);
sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
sb.append(',');
- sb.append(name);
- sb.append(',');
+ sb.append(name != null ? name + "," : "");
sb.append(count);
return ",";
}
@@ -730,12 +732,12 @@
Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
if (fullWakeTimer != null) {
- fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which);
+ fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
}
Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
if (partialWakeTimer != null) {
- partialWakeLockTimeTotal += partialWakeTimer.getTotalTime(
+ partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
batteryRealtime, which);
}
}
@@ -783,6 +785,17 @@
getDischargeCurrentLevel());
}
+ Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+ if (kernelWakelocks.size() > 0) {
+ for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+ sb.setLength(0);
+ printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
+
+ dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(),
+ sb.toString());
+ }
+ }
+
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
Uid u = uidStats.valueAt(iu);
@@ -821,12 +834,12 @@
Uid.Wakelock wl = ent.getValue();
String linePrefix = "";
sb.setLength(0);
- linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
- "f", which, linePrefix);
- linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
- "p", which, linePrefix);
- linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
- "w", which, linePrefix);
+ linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
+ batteryRealtime, "f", which, linePrefix);
+ linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
+ batteryRealtime, "p", which, linePrefix);
+ linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
+ batteryRealtime, "w", which, linePrefix);
// Only log if we had at lease one wakelock...
if (sb.length() > 0) {
@@ -844,8 +857,8 @@
Timer timer = se.getSensorTime();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
- long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
- int count = timer.getCount(which);
+ long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
if (totalTime != 0) {
dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
}
@@ -971,6 +984,26 @@
long fullWakeLockTimeTotalMicros = 0;
long partialWakeLockTimeTotalMicros = 0;
+ Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+ if (kernelWakelocks.size() > 0) {
+ for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+
+ String linePrefix = ": ";
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Kernel Wake lock ");
+ sb.append(ent.getKey());
+ linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which,
+ linePrefix);
+ if (!linePrefix.equals(": ")) {
+ sb.append(" realtime");
+ } else {
+ sb.append(": (nothing executed)");
+ }
+ pw.println(sb.toString());
+ }
+ }
+
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
rxTotal += u.getTcpBytesReceived(which);
@@ -984,13 +1017,13 @@
Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
if (fullWakeTimer != null) {
- fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime(
+ fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
batteryRealtime, which);
}
Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
if (partialWakeTimer != null) {
- partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime(
+ partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
batteryRealtime, which);
}
}
@@ -1179,8 +1212,9 @@
Timer timer = se.getSensorTime();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
- long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
- int count = timer.getCount(which);
+ long totalTime = (timer.getTotalTimeLocked(
+ batteryRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
//timer.logState();
if (totalTime != 0) {
sb.append(formatTimeMs(totalTime));
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index cd86fbe..e4412a3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -680,6 +680,8 @@
/** @hide */
public static final int PROC_SPACE_TERM = (int)' ';
/** @hide */
+ public static final int PROC_TAB_TERM = (int)'\t';
+ /** @hide */
public static final int PROC_COMBINE = 0x100;
/** @hide */
public static final int PROC_PARENS = 0x200;
@@ -693,6 +695,10 @@
/** @hide */
public static final native boolean readProcFile(String file, int[] format,
String[] outStrings, long[] outLongs, float[] outFloats);
+
+ /** @hide */
+ public static final native boolean parseProcLine(byte[] buffer, int startIndex,
+ int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats);
/**
* Gets the total Pss value for a given process, in bytes.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f492ad1..58a9be85 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -21,6 +21,7 @@
import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
+import android.os.Process;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -33,7 +34,10 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
/**
* All information we are collecting about things that can happen that impact
@@ -48,7 +52,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 32;
+ private static final int VERSION = 34;
private final File mFile;
private final File mBackupFile;
@@ -63,11 +67,11 @@
// elapsed time by the number of active timers to arrive at that timer's share of the time.
// In order to do this, we must refresh each timer whenever the number of active timers
// changes.
- final ArrayList<Timer> mPartialTimers = new ArrayList<Timer>();
- final ArrayList<Timer> mFullTimers = new ArrayList<Timer>();
- final ArrayList<Timer> mWindowTimers = new ArrayList<Timer>();
- final SparseArray<ArrayList<Timer>> mSensorTimers
- = new SparseArray<ArrayList<Timer>>();
+ final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
+ final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
+ final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
+ final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
+ = new SparseArray<ArrayList<StopwatchTimer>>();
// These are the objects that will want to do something when the device
// is unplugged from power.
@@ -88,31 +92,33 @@
long mLastRealtime;
boolean mScreenOn;
- Timer mScreenOnTimer;
+ StopwatchTimer mScreenOnTimer;
int mScreenBrightnessBin = -1;
- final Timer[] mScreenBrightnessTimer = new Timer[NUM_SCREEN_BRIGHTNESS_BINS];
+ final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
Counter mInputEventCounter;
boolean mPhoneOn;
- Timer mPhoneOnTimer;
+ StopwatchTimer mPhoneOnTimer;
int mPhoneSignalStrengthBin = -1;
- final Timer[] mPhoneSignalStrengthsTimer = new Timer[NUM_SIGNAL_STRENGTH_BINS];
+ final StopwatchTimer[] mPhoneSignalStrengthsTimer =
+ new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
int mPhoneDataConnectionType = -1;
- final Timer[] mPhoneDataConnectionsTimer = new Timer[NUM_DATA_CONNECTION_TYPES];
+ final StopwatchTimer[] mPhoneDataConnectionsTimer =
+ new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
boolean mWifiOn;
- Timer mWifiOnTimer;
+ StopwatchTimer mWifiOnTimer;
int mWifiOnUid = -1;
boolean mWifiRunning;
- Timer mWifiRunningTimer;
+ StopwatchTimer mWifiRunningTimer;
boolean mBluetoothOn;
- Timer mBluetoothOnTimer;
+ StopwatchTimer mBluetoothOnTimer;
/**
* These provide time bases that discount the time the device is plugged
@@ -135,6 +141,37 @@
int mDischargeCurrentLevel;
long mLastWriteTime = 0; // Milliseconds
+
+ /*
+ * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
+ */
+ private final HashMap<String, SamplingTimer> mKernelWakelockStats =
+ new HashMap<String, SamplingTimer>();
+
+ public Map<String, ? extends SamplingTimer> getKernelWakelockStats() {
+ return mKernelWakelockStats;
+ }
+
+ private static int sKernelWakelockUpdateVersion = 0;
+
+ private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
+ Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name
+ Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count
+ Process.PROC_TAB_TERM,
+ Process.PROC_TAB_TERM,
+ Process.PROC_TAB_TERM,
+ Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime
+ };
+
+ private final String[] mProcWakelocksName = new String[3];
+ private final long[] mProcWakelocksData = new long[3];
+
+ /*
+ * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
+ * to mKernelWakelockStats.
+ */
+ private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
+ new HashMap<String, KernelWakelockStats>();
// For debugging
public BatteryStatsImpl() {
@@ -200,7 +237,7 @@
}
@Override
- public int getCount(int which) {
+ public int getCountLocked(int which) {
int val;
if (which == STATS_LAST) {
val = mLastCount;
@@ -242,11 +279,9 @@
/**
* State for keeping track of timing information.
*/
- public static final class Timer extends BatteryStats.Timer implements Unpluggable {
+ public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
final int mType;
- final ArrayList<Timer> mTimerPool;
-
- int mNesting;
+
int mCount;
int mLoadedCount;
@@ -281,24 +316,10 @@
* power.
*/
long mUnpluggedTime;
-
- /**
- * The last time at which we updated the timer. If mNesting is > 0,
- * subtract this from the current battery time to find the amount of
- * time we have been running since we last computed an update.
- */
- long mUpdateTime;
- /**
- * The total time at which the timer was acquired, to determine if
- * was actually held for an interesting duration.
- */
- long mAcquireTime;
-
- Timer(int type, ArrayList<Timer> timerPool,
- ArrayList<Unpluggable> unpluggables, Parcel in) {
+ Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
mType = type;
- mTimerPool = timerPool;
+
mCount = in.readInt();
mLoadedCount = in.readInt();
mLastCount = in.readInt();
@@ -306,17 +327,19 @@
mTotalTime = in.readLong();
mLoadedTime = in.readLong();
mLastTime = in.readLong();
- mUpdateTime = in.readLong();
mUnpluggedTime = in.readLong();
unpluggables.add(this);
}
- Timer(int type, ArrayList<Timer> timerPool,
- ArrayList<Unpluggable> unpluggables) {
+ Timer(int type, ArrayList<Unpluggable> unpluggables) {
mType = type;
- mTimerPool = timerPool;
unpluggables.add(this);
}
+
+ protected abstract long computeRunTimeLocked(long curBatteryRealtime);
+
+ protected abstract int computeCurrentCountLocked();
+
public void writeToParcel(Parcel out, long batteryRealtime) {
out.writeInt(mCount);
@@ -326,7 +349,6 @@
out.writeLong(computeRunTimeLocked(batteryRealtime));
out.writeLong(mLoadedTime);
out.writeLong(mLastTime);
- out.writeLong(mUpdateTime);
out.writeLong(mUnpluggedTime);
}
@@ -346,19 +368,15 @@
}
public void plug(long batteryUptime, long batteryRealtime) {
- if (mNesting > 0) {
- if (DEBUG && mType < 0) {
- Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
- + " old mTotalTime=" + mTotalTime
- + " old mUpdateTime=" + mUpdateTime);
- }
- mTotalTime = computeRunTimeLocked(batteryRealtime);
- mUpdateTime = batteryRealtime;
- if (DEBUG && mType < 0) {
- Log.v(TAG, "plug #" + mType
- + ": new mTotalTime=" + mTotalTime
- + " old mUpdateTime=" + mUpdateTime);
- }
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
+ + " old mTotalTime=" + mTotalTime);
+ }
+ mTotalTime = computeRunTimeLocked(batteryRealtime);
+ mCount = computeCurrentCountLocked();
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "plug #" + mType
+ + ": new mTotalTime=" + mTotalTime);
}
}
@@ -380,7 +398,7 @@
}
@Override
- public long getTotalTime(long batteryRealtime, int which) {
+ public long getTotalTimeLocked(long batteryRealtime, int which) {
long val;
if (which == STATS_LAST) {
val = mLastTime;
@@ -397,12 +415,12 @@
}
@Override
- public int getCount(int which) {
+ public int getCountLocked(int which) {
int val;
if (which == STATS_LAST) {
val = mLastCount;
} else {
- val = mCount;
+ val = computeCurrentCountLocked();
if (which == STATS_UNPLUGGED) {
val -= mUnpluggedCount;
} else if (which != STATS_TOTAL) {
@@ -414,14 +432,239 @@
}
public void logState(Printer pw, String prefix) {
- pw.println(prefix + "mNesting=" + mNesting + " mCount=" + mCount
+ pw.println(prefix + " mCount=" + mCount
+ " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+ " mUnpluggedCount=" + mUnpluggedCount);
pw.println(prefix + "mTotalTime=" + mTotalTime
+ " mLoadedTime=" + mLoadedTime);
pw.println(prefix + "mLastTime=" + mLastTime
+ " mUnpluggedTime=" + mUnpluggedTime);
- pw.println(prefix + "mUpdateTime=" + mUpdateTime
+ }
+
+
+ void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
+ long runTime = computeRunTimeLocked(batteryRealtime);
+ // Divide by 1000 for backwards compatibility
+ out.writeLong((runTime + 500) / 1000);
+ out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
+ out.writeInt(mCount);
+ out.writeInt(mCount - mLoadedCount);
+ }
+
+ void readSummaryFromParcelLocked(Parcel in) {
+ // Multiply by 1000 for backwards compatibility
+ mTotalTime = mLoadedTime = in.readLong() * 1000;
+ mLastTime = in.readLong() * 1000;
+ mUnpluggedTime = mTotalTime;
+ mCount = mLoadedCount = in.readInt();
+ mLastCount = in.readInt();
+ mUnpluggedCount = mCount;
+ }
+ }
+
+ public static final class SamplingTimer extends Timer {
+
+ /**
+ * The most recent reported count from /proc/wakelocks.
+ */
+ int mCurrentReportedCount;
+
+ /**
+ * The reported count from /proc/wakelocks when unplug() was last
+ * called.
+ */
+ int mUnpluggedReportedCount;
+
+ /**
+ * The most recent reported total_time from /proc/wakelocks.
+ */
+ long mCurrentReportedTotalTime;
+
+
+ /**
+ * The reported total_time from /proc/wakelocks when unplug() was last
+ * called.
+ */
+ long mUnpluggedReportedTotalTime;
+
+ /**
+ * Whether we are currently in a discharge cycle.
+ */
+ boolean mInDischarge;
+
+ /**
+ * Whether we are currently recording reported values.
+ */
+ boolean mTrackingReportedValues;
+
+ /*
+ * A sequnce counter, incremented once for each update of the stats.
+ */
+ int mUpdateVersion;
+
+ SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
+ super(0, unpluggables, in);
+ mCurrentReportedCount = in.readInt();
+ mUnpluggedReportedCount = in.readInt();
+ mCurrentReportedTotalTime = in.readLong();
+ mUnpluggedReportedTotalTime = in.readLong();
+ mTrackingReportedValues = in.readInt() == 1;
+ mInDischarge = inDischarge;
+ }
+
+ SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
+ boolean trackReportedValues) {
+ super(0, unpluggables);
+ mTrackingReportedValues = trackReportedValues;
+ mInDischarge = inDischarge;
+ }
+
+ public void setStale() {
+ mTrackingReportedValues = false;
+ mUnpluggedReportedTotalTime = 0;
+ mUnpluggedReportedCount = 0;
+ }
+
+ public void setUpdateVersion(int version) {
+ mUpdateVersion = version;
+ }
+
+ public int getUpdateVersion() {
+ return mUpdateVersion;
+ }
+
+ public void updateCurrentReportedCount(int count) {
+ if (mInDischarge && mUnpluggedReportedCount == 0) {
+ // Updating the reported value for the first time.
+ mUnpluggedReportedCount = count;
+ // If we are receiving an update update mTrackingReportedValues;
+ mTrackingReportedValues = true;
+ }
+ mCurrentReportedCount = count;
+ }
+
+ public void updateCurrentReportedTotalTime(long totalTime) {
+ if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
+ // Updating the reported value for the first time.
+ mUnpluggedReportedTotalTime = totalTime;
+ // If we are receiving an update update mTrackingReportedValues;
+ mTrackingReportedValues = true;
+ }
+ mCurrentReportedTotalTime = totalTime;
+ }
+
+ public void unplug(long batteryUptime, long batteryRealtime) {
+ super.unplug(batteryUptime, batteryRealtime);
+ if (mTrackingReportedValues) {
+ mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
+ mUnpluggedReportedCount = mCurrentReportedCount;
+ }
+ mInDischarge = true;
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ super.plug(batteryUptime, batteryRealtime);
+ mInDischarge = false;
+ }
+
+ public void logState(Printer pw, String prefix) {
+ super.logState(pw, prefix);
+ pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
+ + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
+ + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
+ + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
+ }
+
+ protected long computeRunTimeLocked(long curBatteryRealtime) {
+ return mTotalTime + (mInDischarge && mTrackingReportedValues
+ ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
+ }
+
+ protected int computeCurrentCountLocked() {
+ return mCount + (mInDischarge && mTrackingReportedValues
+ ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
+ }
+
+ public void writeToParcel(Parcel out, long batteryRealtime) {
+ super.writeToParcel(out, batteryRealtime);
+ out.writeInt(mCurrentReportedCount);
+ out.writeInt(mUnpluggedReportedCount);
+ out.writeLong(mCurrentReportedTotalTime);
+ out.writeLong(mUnpluggedReportedTotalTime);
+ out.writeInt(mTrackingReportedValues ? 1 : 0);
+ }
+
+ void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
+ super.writeSummaryFromParcelLocked(out, batteryRealtime);
+ out.writeLong(mCurrentReportedTotalTime);
+ out.writeInt(mCurrentReportedCount);
+ out.writeInt(mTrackingReportedValues ? 1 : 0);
+ }
+
+ void readSummaryFromParcelLocked(Parcel in) {
+ super.readSummaryFromParcelLocked(in);
+ mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
+ mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
+ mTrackingReportedValues = in.readInt() == 1;
+ }
+ }
+
+ /**
+ * State for keeping track of timing information.
+ */
+ public static final class StopwatchTimer extends Timer {
+ final ArrayList<StopwatchTimer> mTimerPool;
+ int mNesting;
+
+
+ /**
+ * The last time at which we updated the timer. If mNesting is > 0,
+ * subtract this from the current battery time to find the amount of
+ * time we have been running since we last computed an update.
+ */
+ long mUpdateTime;
+
+ /**
+ * The total time at which the timer was acquired, to determine if
+ * was actually held for an interesting duration.
+ */
+ long mAcquireTime;
+
+
+ StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+ ArrayList<Unpluggable> unpluggables, Parcel in) {
+ super(type, unpluggables, in);
+ mTimerPool = timerPool;
+ mUpdateTime = in.readLong();
+ }
+
+ StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+ ArrayList<Unpluggable> unpluggables) {
+ super(type, unpluggables);
+ mTimerPool = timerPool;
+ }
+
+ public void writeToParcel(Parcel out, long batteryRealtime) {
+ super.writeToParcel(out, batteryRealtime);
+ out.writeLong(mUpdateTime);
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ if (mNesting > 0) {
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
+ }
+ super.plug(batteryUptime, batteryRealtime);
+ mUpdateTime = batteryRealtime;
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
+ }
+ }
+ }
+
+ public void logState(Printer pw, String prefix) {
+ super.logState(pw, prefix);
+ pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime
+ " mAcquireTime=" + mAcquireTime);
}
@@ -484,12 +727,12 @@
// Update the total time for all other running Timers with the same type as this Timer
// due to a change in timer count
private static void refreshTimersLocked(final BatteryStatsImpl stats,
- final ArrayList<Timer> pool) {
+ final ArrayList<StopwatchTimer> pool) {
final long realtime = SystemClock.elapsedRealtime() * 1000;
final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
final int N = pool.size();
for (int i=N-1; i>= 0; i--) {
- final Timer t = pool.get(i);
+ final StopwatchTimer t = pool.get(i);
long heldTime = batteryRealtime - t.mUpdateTime;
if (heldTime > 0) {
t.mTotalTime += heldTime / N;
@@ -498,34 +741,146 @@
}
}
- private long computeRunTimeLocked(long curBatteryRealtime) {
+ @Override
+ protected long computeRunTimeLocked(long curBatteryRealtime) {
return mTotalTime + (mNesting > 0
? (curBatteryRealtime - mUpdateTime)
/ (mTimerPool != null ? mTimerPool.size() : 1)
: 0);
}
- void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
- long runTime = computeRunTimeLocked(batteryRealtime);
- // Divide by 1000 for backwards compatibility
- out.writeLong((runTime + 500) / 1000);
- out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
- out.writeInt(mCount);
- out.writeInt(mCount - mLoadedCount);
+ @Override
+ protected int computeCurrentCountLocked() {
+ return mCount;
}
void readSummaryFromParcelLocked(Parcel in) {
- // Multiply by 1000 for backwards compatibility
- mTotalTime = mLoadedTime = in.readLong() * 1000;
- mLastTime = in.readLong() * 1000;
- mUnpluggedTime = mTotalTime;
- mCount = mLoadedCount = in.readInt();
- mLastCount = in.readInt();
- mUnpluggedCount = mCount;
+ super.readSummaryFromParcelLocked(in);
mNesting = 0;
}
}
+ private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
+
+ byte[] buffer = new byte[4096];
+ int len;
+
+ try {
+ FileInputStream is = new FileInputStream("/proc/wakelocks");
+ len = is.read(buffer);
+ is.close();
+
+ if (len > 0) {
+ int i;
+ for (i=0; i<len; i++) {
+ if (buffer[i] == '\0') {
+ len = i;
+ break;
+ }
+ }
+ }
+ } catch (java.io.FileNotFoundException e) {
+ return null;
+ } catch (java.io.IOException e) {
+ return null;
+ }
+
+ return parseProcWakelocks(buffer, len);
+ }
+
+ private final Map<String, KernelWakelockStats> parseProcWakelocks(
+ byte[] wlBuffer, int len) {
+ String name;
+ int count;
+ long totalTime;
+ int startIndex, endIndex;
+ int numUpdatedWlNames = 0;
+
+ // Advance past the first line.
+ int i;
+ for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
+ startIndex = endIndex = i + 1;
+
+ synchronized(this) {
+ Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
+
+ sKernelWakelockUpdateVersion++;
+ while (endIndex < len) {
+ for (endIndex=startIndex;
+ endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
+ endIndex++);
+ endIndex++; // endIndex is an exclusive upper bound.
+
+ String[] nameStringArray = mProcWakelocksName;
+ long[] wlData = mProcWakelocksData;
+ Process.parseProcLine(wlBuffer, startIndex, endIndex, PROC_WAKELOCKS_FORMAT,
+ nameStringArray, wlData, null);
+
+ name = nameStringArray[0];
+ count = (int) wlData[1];
+ // convert nanoseconds to microseconds with rounding.
+ totalTime = (wlData[2] + 500) / 1000;
+
+ if (name.length() > 0) {
+ if (!m.containsKey(name)) {
+ m.put(name, new KernelWakelockStats(count, totalTime,
+ sKernelWakelockUpdateVersion));
+ numUpdatedWlNames++;
+ } else {
+ KernelWakelockStats kwlStats = m.get(name);
+ if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
+ kwlStats.mCount += count;
+ kwlStats.mTotalTime += totalTime;
+ } else {
+ kwlStats.mCount = count;
+ kwlStats.mTotalTime = totalTime;
+ kwlStats.mVersion = sKernelWakelockUpdateVersion;
+ numUpdatedWlNames++;
+ }
+ }
+ }
+ startIndex = endIndex;
+ }
+
+ if (m.size() != numUpdatedWlNames) {
+ // Don't report old data.
+ Iterator<KernelWakelockStats> itr = m.values().iterator();
+ while (itr.hasNext()) {
+ if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
+ itr.remove();
+ }
+ }
+ }
+ return m;
+ }
+ }
+
+ private class KernelWakelockStats {
+ public int mCount;
+ public long mTotalTime;
+ public int mVersion;
+
+ KernelWakelockStats(int count, long totalTime, int version) {
+ mCount = count;
+ mTotalTime = totalTime;
+ mVersion = version;
+ }
+ }
+
+ /*
+ * Get the KernelWakelockTimer associated with name, and create a new one if one
+ * doesn't already exist.
+ */
+ public SamplingTimer getKernelWakelockTimerLocked(String name) {
+ SamplingTimer kwlt = mKernelWakelockStats.get(name);
+ if (kwlt == null) {
+ kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
+ true /* track reported values */);
+ mKernelWakelockStats.put(name, kwlt);
+ }
+ return kwlt;
+ }
+
public void doUnplug(long batteryUptime, long batteryRealtime) {
for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
Uid u = mUidStats.valueAt(iu);
@@ -760,53 +1115,53 @@
}
@Override public long getScreenOnTime(long batteryRealtime, int which) {
- return mScreenOnTimer.getTotalTime(batteryRealtime, which);
+ return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getScreenBrightnessTime(int brightnessBin,
long batteryRealtime, int which) {
- return mScreenBrightnessTimer[brightnessBin].getTotalTime(
+ return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
batteryRealtime, which);
}
@Override public int getInputEventCount(int which) {
- return mInputEventCounter.getCount(which);
+ return mInputEventCounter.getCountLocked(which);
}
@Override public long getPhoneOnTime(long batteryRealtime, int which) {
- return mPhoneOnTimer.getTotalTime(batteryRealtime, which);
+ return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getPhoneSignalStrengthTime(int strengthBin,
long batteryRealtime, int which) {
- return mPhoneSignalStrengthsTimer[strengthBin].getTotalTime(
+ return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
batteryRealtime, which);
}
@Override public int getPhoneSignalStrengthCount(int dataType, int which) {
- return mPhoneDataConnectionsTimer[dataType].getCount(which);
+ return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
@Override public long getPhoneDataConnectionTime(int dataType,
long batteryRealtime, int which) {
- return mPhoneDataConnectionsTimer[dataType].getTotalTime(
+ return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
batteryRealtime, which);
}
@Override public int getPhoneDataConnectionCount(int dataType, int which) {
- return mPhoneDataConnectionsTimer[dataType].getCount(which);
+ return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
@Override public long getWifiOnTime(long batteryRealtime, int which) {
- return mWifiOnTimer.getTotalTime(batteryRealtime, which);
+ return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getWifiRunningTime(long batteryRealtime, int which) {
- return mWifiRunningTimer.getTotalTime(batteryRealtime, which);
+ return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public long getBluetoothOnTime(long batteryRealtime, int which) {
- return mBluetoothOnTimer.getTotalTime(batteryRealtime, which);
+ return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override public boolean getIsOnBattery() {
@@ -836,13 +1191,13 @@
long mStartedTcpBytesSent = -1;
boolean mWifiTurnedOn;
- Timer mWifiTurnedOnTimer;
+ StopwatchTimer mWifiTurnedOnTimer;
boolean mFullWifiLockOut;
- Timer mFullWifiLockTimer;
+ StopwatchTimer mFullWifiLockTimer;
boolean mScanWifiLockOut;
- Timer mScanWifiLockTimer;
+ StopwatchTimer mScanWifiLockTimer;
Counter[] mUserActivityCounters;
@@ -868,9 +1223,9 @@
public Uid(int uid) {
mUid = uid;
- mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables);
- mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables);
- mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables);
+ mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
+ mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
+ mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
}
@Override
@@ -980,17 +1335,17 @@
@Override
public long getWifiTurnedOnTime(long batteryRealtime, int which) {
- return mWifiTurnedOnTimer.getTotalTime(batteryRealtime, which);
+ return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override
public long getFullWifiLockTime(long batteryRealtime, int which) {
- return mFullWifiLockTimer.getTotalTime(batteryRealtime, which);
+ return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override
public long getScanWifiLockTime(long batteryRealtime, int which) {
- return mScanWifiLockTimer.getTotalTime(batteryRealtime, which);
+ return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
}
@Override
@@ -1013,7 +1368,7 @@
if (mUserActivityCounters == null) {
return 0;
}
- return mUserActivityCounters[type].getCount(which);
+ return mUserActivityCounters[type].getCountLocked(which);
}
void initUserActivityLocked() {
@@ -1120,11 +1475,11 @@
mTcpBytesReceivedAtLastUnplug = in.readLong();
mTcpBytesSentAtLastUnplug = in.readLong();
mWifiTurnedOn = false;
- mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables, in);
+ mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in);
mFullWifiLockOut = false;
- mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in);
+ mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in);
mScanWifiLockOut = false;
- mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
+ mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
if (in.readInt() == 0) {
mUserActivityCounters = null;
} else {
@@ -1142,17 +1497,17 @@
/**
* How long (in ms) this uid has been keeping the device partially awake.
*/
- Timer mTimerPartial;
+ StopwatchTimer mTimerPartial;
/**
* How long (in ms) this uid has been keeping the device fully awake.
*/
- Timer mTimerFull;
+ StopwatchTimer mTimerFull;
/**
* How long (in ms) this uid has had a window keeping the device awake.
*/
- Timer mTimerWindow;
+ StopwatchTimer mTimerWindow;
/**
* Reads a possibly null Timer from a Parcel. The timer is associated with the
@@ -1161,13 +1516,13 @@
* @param in the Parcel to be read from.
* return a new Timer, or null.
*/
- private Timer readTimerFromParcel(int type, ArrayList<Timer> pool,
+ private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
ArrayList<Unpluggable> unpluggables, Parcel in) {
if (in.readInt() == 0) {
return null;
}
- return new Timer(type, pool, unpluggables, in);
+ return new StopwatchTimer(type, pool, unpluggables, in);
}
void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -1198,24 +1553,24 @@
public final class Sensor extends BatteryStats.Uid.Sensor {
final int mHandle;
- Timer mTimer;
+ StopwatchTimer mTimer;
public Sensor(int handle) {
mHandle = handle;
}
- private Timer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
+ private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
Parcel in) {
if (in.readInt() == 0) {
return null;
}
- ArrayList<Timer> pool = mSensorTimers.get(mHandle);
+ ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
if (pool == null) {
- pool = new ArrayList<Timer>();
+ pool = new ArrayList<StopwatchTimer>();
mSensorTimers.put(mHandle, pool);
}
- return new Timer(0, pool, unpluggables, in);
+ return new StopwatchTimer(0, pool, unpluggables, in);
}
void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -1816,32 +2171,32 @@
return ss;
}
- public Timer getWakeTimerLocked(String name, int type) {
+ public StopwatchTimer getWakeTimerLocked(String name, int type) {
Wakelock wl = mWakelockStats.get(name);
if (wl == null) {
wl = new Wakelock();
mWakelockStats.put(name, wl);
}
- Timer t = null;
+ StopwatchTimer t = null;
switch (type) {
case WAKE_TYPE_PARTIAL:
t = wl.mTimerPartial;
if (t == null) {
- t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
+ t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
wl.mTimerPartial = t;
}
return t;
case WAKE_TYPE_FULL:
t = wl.mTimerFull;
if (t == null) {
- t = new Timer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
+ t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
wl.mTimerFull = t;
}
return t;
case WAKE_TYPE_WINDOW:
t = wl.mTimerWindow;
if (t == null) {
- t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
+ t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
wl.mTimerWindow = t;
}
return t;
@@ -1850,7 +2205,7 @@
}
}
- public Timer getSensorTimerLocked(int sensor, boolean create) {
+ public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
Sensor se = mSensorStats.get(sensor);
if (se == null) {
if (!create) {
@@ -1859,36 +2214,36 @@
se = new Sensor(sensor);
mSensorStats.put(sensor, se);
}
- Timer t = se.mTimer;
+ StopwatchTimer t = se.mTimer;
if (t != null) {
return t;
}
- ArrayList<Timer> timers = mSensorTimers.get(sensor);
+ ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
if (timers == null) {
- timers = new ArrayList<Timer>();
+ timers = new ArrayList<StopwatchTimer>();
mSensorTimers.put(sensor, timers);
}
- t = new Timer(BatteryStats.SENSOR, timers, mUnpluggables);
+ t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
se.mTimer = t;
return t;
}
public void noteStartWakeLocked(String name, int type) {
- Timer t = getWakeTimerLocked(name, type);
+ StopwatchTimer t = getWakeTimerLocked(name, type);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
}
}
public void noteStopWakeLocked(String name, int type) {
- Timer t = getWakeTimerLocked(name, type);
+ StopwatchTimer t = getWakeTimerLocked(name, type);
if (t != null) {
t.stopRunningLocked(BatteryStatsImpl.this);
}
}
public void noteStartSensor(int sensor) {
- Timer t = getSensorTimerLocked(sensor, true);
+ StopwatchTimer t = getSensorTimerLocked(sensor, true);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
}
@@ -1896,21 +2251,21 @@
public void noteStopSensor(int sensor) {
// Don't create a timer if one doesn't already exist
- Timer t = getSensorTimerLocked(sensor, false);
+ StopwatchTimer t = getSensorTimerLocked(sensor, false);
if (t != null) {
t.stopRunningLocked(BatteryStatsImpl.this);
}
}
public void noteStartGps() {
- Timer t = getSensorTimerLocked(Sensor.GPS, true);
+ StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
}
}
public void noteStopGps() {
- Timer t = getSensorTimerLocked(Sensor.GPS, false);
+ StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
if (t != null) {
t.stopRunningLocked(BatteryStatsImpl.this);
}
@@ -1925,21 +2280,21 @@
mFile = new File(filename);
mBackupFile = new File(filename + ".bak");
mStartCount++;
- mScreenOnTimer = new Timer(-1, null, mUnpluggables);
+ mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i] = new Timer(-100-i, null, mUnpluggables);
+ mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
}
mInputEventCounter = new Counter(mUnpluggables);
- mPhoneOnTimer = new Timer(-2, null, mUnpluggables);
+ mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
- mPhoneSignalStrengthsTimer[i] = new Timer(-200-i, null, mUnpluggables);
+ mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
}
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i] = new Timer(-300-i, null, mUnpluggables);
+ mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
}
- mWifiOnTimer = new Timer(-3, null, mUnpluggables);
- mWifiRunningTimer = new Timer(-4, null, mUnpluggables);
- mBluetoothOnTimer = new Timer(-5, null, mUnpluggables);
+ mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
+ mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
+ mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
mOnBattery = mOnBatteryInternal = false;
mTrackBatteryPastUptime = 0;
mTrackBatteryPastRealtime = 0;
@@ -1967,6 +2322,7 @@
public void setOnBattery(boolean onBattery, int level) {
synchronized(this) {
+ updateKernelWakelocksLocked();
if (mOnBattery != onBattery) {
mOnBattery = mOnBatteryInternal = onBattery;
@@ -1998,6 +2354,35 @@
public void recordCurrentLevel(int level) {
mDischargeCurrentLevel = level;
}
+
+ public void updateKernelWakelocksLocked() {
+ Map<String, KernelWakelockStats> m = readKernelWakelockStats();
+
+ for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
+ String name = ent.getKey();
+ KernelWakelockStats kws = ent.getValue();
+
+ SamplingTimer kwlt = mKernelWakelockStats.get(name);
+ if (kwlt == null) {
+ kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
+ true /* track reported values */);
+ mKernelWakelockStats.put(name, kwlt);
+ }
+ kwlt.updateCurrentReportedCount(kws.mCount);
+ kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
+ kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
+ }
+
+ if (m.size() != mKernelWakelockStats.size()) {
+ // Set timers to stale if they didn't appear in /proc/wakelocks this time.
+ for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+ SamplingTimer st = ent.getValue();
+ if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
+ st.setStale();
+ }
+ }
+ }
+ }
public long getAwakeTimeBattery() {
return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
@@ -2296,6 +2681,14 @@
mBluetoothOn = false;
mBluetoothOnTimer.readSummaryFromParcelLocked(in);
+ int NKW = in.readInt();
+ for (int ikw = 0; ikw < NKW; ikw++) {
+ if (in.readInt() != 0) {
+ String kwltName = in.readString();
+ getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
+ }
+ }
+
final int NU = in.readInt();
for (int iu = 0; iu < NU; iu++) {
int uid = in.readInt();
@@ -2420,6 +2813,18 @@
mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ out.writeInt(mKernelWakelockStats.size());
+ for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+ Timer kwlt = ent.getValue();
+ if (kwlt != null) {
+ out.writeInt(1);
+ out.writeString(ent.getKey());
+ ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
final int NU = mUidStats.size();
out.writeInt(NU);
for (int iu = 0; iu < NU; iu++) {
@@ -2548,25 +2953,25 @@
mBatteryRealtime = in.readLong();
mBatteryLastRealtime = in.readLong();
mScreenOn = false;
- mScreenOnTimer = new Timer(-1, null, mUnpluggables, in);
+ mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- mScreenBrightnessTimer[i] = new Timer(-100-i, null, mUnpluggables, in);
+ mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
}
mInputEventCounter = new Counter(mUnpluggables, in);
mPhoneOn = false;
- mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in);
+ mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
- mPhoneSignalStrengthsTimer[i] = new Timer(-200-i, null, mUnpluggables, in);
+ mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
}
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
- mPhoneDataConnectionsTimer[i] = new Timer(-300-i, null, mUnpluggables, in);
+ mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
}
mWifiOn = false;
- mWifiOnTimer = new Timer(-2, null, mUnpluggables, in);
+ mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mWifiRunning = false;
- mWifiRunningTimer = new Timer(-2, null, mUnpluggables, in);
+ mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mBluetoothOn = false;
- mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in);
+ mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mUptime = in.readLong();
mUptimeStart = in.readLong();
mLastUptime = in.readLong();
@@ -2585,6 +2990,16 @@
mDischargeCurrentLevel = in.readInt();
mLastWriteTime = in.readLong();
+ mKernelWakelockStats.clear();
+ int NKW = in.readInt();
+ for (int ikw = 0; ikw < NKW; ikw++) {
+ if (in.readInt() != 0) {
+ String wakelockName = in.readString();
+ SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
+ mKernelWakelockStats.put(wakelockName, kwlt);
+ }
+ }
+
mPartialTimers.clear();
mFullTimers.clear();
mWindowTimers.clear();
@@ -2648,6 +3063,18 @@
out.writeInt(mDischargeCurrentLevel);
out.writeLong(mLastWriteTime);
+ out.writeInt(mKernelWakelockStats.size());
+ for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+ SamplingTimer kwlt = ent.getValue();
+ if (kwlt != null) {
+ out.writeInt(1);
+ out.writeString(ent.getKey());
+ Timer.writeTimerToParcel(out, kwlt, batteryRealtime);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
int size = mUidStats.size();
out.writeInt(size);
for (int i = 0; i < size; i++) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 3feccde..bd56605 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -516,39 +516,10 @@
PROC_OUT_FLOAT = 0x4000,
};
-jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
- jstring file, jintArray format, jobjectArray outStrings,
- jlongArray outLongs, jfloatArray outFloats)
+jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
+ char* buffer, jint startIndex, jint endIndex, jintArray format,
+ jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
{
- if (file == NULL || format == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", NULL);
- return JNI_FALSE;
- }
-
- const char* file8 = env->GetStringUTFChars(file, NULL);
- if (file8 == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
- return JNI_FALSE;
- }
- int fd = open(file8, O_RDONLY);
- env->ReleaseStringUTFChars(file, file8);
-
- if (fd < 0) {
- //LOGW("Unable to open process file: %s\n", file8);
- return JNI_FALSE;
- }
-
- char buffer[256];
- const int len = read(fd, buffer, sizeof(buffer)-1);
- close(fd);
-
- if (len < 0) {
- //LOGW("Unable to open process file: %s fd=%d\n", file8, fd);
- return JNI_FALSE;
- }
- buffer[len] = 0;
-
- //LOGI("Process file %s: %s\n", file8, buffer);
const jsize NF = env->GetArrayLength(format);
const jsize NS = outStrings ? env->GetArrayLength(outStrings) : 0;
@@ -575,7 +546,7 @@
return JNI_FALSE;
}
- jsize i = 0;
+ jsize i = startIndex;
jsize di = 0;
jboolean res = JNI_TRUE;
@@ -587,30 +558,30 @@
}
const char term = (char)(mode&PROC_TERM_MASK);
const jsize start = i;
- if (i >= len) {
+ if (i >= endIndex) {
res = JNI_FALSE;
break;
}
jsize end = -1;
if ((mode&PROC_PARENS) != 0) {
- while (buffer[i] != ')' && i < len) {
+ while (buffer[i] != ')' && i < endIndex) {
i++;
}
end = i;
i++;
}
- while (buffer[i] != term && i < len) {
+ while (buffer[i] != term && i < endIndex) {
i++;
}
if (end < 0) {
end = i;
}
- if (i < len) {
+ if (i < endIndex) {
i++;
if ((mode&PROC_COMBINE) != 0) {
- while (buffer[i] == term && i < len) {
+ while (buffer[i] == term && i < endIndex) {
i++;
}
}
@@ -649,6 +620,58 @@
return res;
}
+jboolean android_os_Process_parseProcLine(JNIEnv* env, jobject clazz,
+ jbyteArray buffer, jint startIndex, jint endIndex, jintArray format,
+ jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
+{
+ jbyte* bufferArray = env->GetByteArrayElements(buffer, NULL);
+
+ jboolean result = android_os_Process_parseProcLineArray(env, clazz,
+ (char*) bufferArray, startIndex, endIndex, format, outStrings,
+ outLongs, outFloats);
+
+ env->ReleaseByteArrayElements(buffer, bufferArray, 0);
+
+ return result;
+}
+
+jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
+ jstring file, jintArray format, jobjectArray outStrings,
+ jlongArray outLongs, jfloatArray outFloats)
+{
+ if (file == NULL || format == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return JNI_FALSE;
+ }
+
+ const char* file8 = env->GetStringUTFChars(file, NULL);
+ if (file8 == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return JNI_FALSE;
+ }
+ int fd = open(file8, O_RDONLY);
+ env->ReleaseStringUTFChars(file, file8);
+
+ if (fd < 0) {
+ //LOGW("Unable to open process file: %s\n", file8);
+ return JNI_FALSE;
+ }
+
+ char buffer[256];
+ const int len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0) {
+ //LOGW("Unable to open process file: %s fd=%d\n", file8, fd);
+ return JNI_FALSE;
+ }
+ buffer[len] = 0;
+
+ return android_os_Process_parseProcLineArray(env, clazz, buffer, 0, len,
+ format, outStrings, outLongs, outFloats);
+
+}
+
void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
jobject binderObject)
{
@@ -728,6 +751,7 @@
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
{"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
{"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_readProcFile},
+ {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
{"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
{"getPss", "(I)J", (void*)android_os_Process_getPss},
//{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
@@ -746,4 +770,3 @@
env, kProcessPathName,
methods, NELEM(methods));
}
-