summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/BatteryStats.java188
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java268
-rw-r--r--core/java/com/android/internal/os/ProcessCpuTracker.java77
-rw-r--r--services/core/java/com/android/server/BatteryService.java18
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java77
5 files changed, 537 insertions, 91 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cd45cfb..4dadda2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -592,6 +592,86 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ /**
+ * Optional detailed information that can go into a history step. This is typically
+ * generated each time the battery level changes.
+ */
+ public final static class HistoryStepDetails {
+ // Time (in 1/100 second) spent in user space and the kernel since the last step.
+ public int userTime;
+ public int systemTime;
+
+ // Top three apps using CPU in the last step, with times in 1/100 second.
+ public int appCpuUid1;
+ public int appCpuUTime1;
+ public int appCpuSTime1;
+ public int appCpuUid2;
+ public int appCpuUTime2;
+ public int appCpuSTime2;
+ public int appCpuUid3;
+ public int appCpuUTime3;
+ public int appCpuSTime3;
+
+ // Information from /proc/stat
+ public int statUserTime;
+ public int statSystemTime;
+ public int statIOWaitTime;
+ public int statIrqTime;
+ public int statSoftIrqTime;
+ public int statIdlTime;
+
+ public HistoryStepDetails() {
+ clear();
+ }
+
+ public void clear() {
+ userTime = systemTime = 0;
+ appCpuUid1 = appCpuUid2 = appCpuUid3 = -1;
+ appCpuUTime1 = appCpuSTime1 = appCpuUTime2 = appCpuSTime2
+ = appCpuUTime3 = appCpuSTime3 = 0;
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(userTime);
+ out.writeInt(systemTime);
+ out.writeInt(appCpuUid1);
+ out.writeInt(appCpuUTime1);
+ out.writeInt(appCpuSTime1);
+ out.writeInt(appCpuUid2);
+ out.writeInt(appCpuUTime2);
+ out.writeInt(appCpuSTime2);
+ out.writeInt(appCpuUid3);
+ out.writeInt(appCpuUTime3);
+ out.writeInt(appCpuSTime3);
+ out.writeInt(statUserTime);
+ out.writeInt(statSystemTime);
+ out.writeInt(statIOWaitTime);
+ out.writeInt(statIrqTime);
+ out.writeInt(statSoftIrqTime);
+ out.writeInt(statIdlTime);
+ }
+
+ public void readFromParcel(Parcel in) {
+ userTime = in.readInt();
+ systemTime = in.readInt();
+ appCpuUid1 = in.readInt();
+ appCpuUTime1 = in.readInt();
+ appCpuSTime1 = in.readInt();
+ appCpuUid2 = in.readInt();
+ appCpuUTime2 = in.readInt();
+ appCpuSTime2 = in.readInt();
+ appCpuUid3 = in.readInt();
+ appCpuUTime3 = in.readInt();
+ appCpuSTime3 = in.readInt();
+ statUserTime = in.readInt();
+ statSystemTime = in.readInt();
+ statIOWaitTime = in.readInt();
+ statIrqTime = in.readInt();
+ statSoftIrqTime = in.readInt();
+ statIdlTime = in.readInt();
+ }
+ }
+
public final static class HistoryItem implements Parcelable {
public HistoryItem next;
@@ -687,6 +767,9 @@ public abstract class BatteryStats implements Parcelable {
// Kernel wakeup reason at this point.
public HistoryTag wakeReasonTag;
+ // Non-null when there is more detailed information at this step.
+ public HistoryStepDetails stepDetails;
+
public static final int EVENT_FLAG_START = 0x8000;
public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -3692,10 +3775,115 @@ public abstract class BatteryStats implements Parcelable {
}
}
pw.println();
+ if (rec.stepDetails != null) {
+ if (!checkin) {
+ pw.print(" Details: cpu=");
+ pw.print(rec.stepDetails.userTime);
+ pw.print("u+");
+ pw.print(rec.stepDetails.systemTime);
+ pw.print("s");
+ if (rec.stepDetails.appCpuUid1 >= 0) {
+ pw.print(" (");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
+ rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
+ if (rec.stepDetails.appCpuUid2 >= 0) {
+ pw.print(", ");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
+ rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
+ }
+ if (rec.stepDetails.appCpuUid3 >= 0) {
+ pw.print(", ");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
+ rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
+ }
+ pw.print(')');
+ }
+ pw.println();
+ pw.print(" /proc/stat=");
+ pw.print(rec.stepDetails.statUserTime);
+ pw.print(" usr, ");
+ pw.print(rec.stepDetails.statSystemTime);
+ pw.print(" sys, ");
+ pw.print(rec.stepDetails.statIOWaitTime);
+ pw.print(" io, ");
+ pw.print(rec.stepDetails.statIrqTime);
+ pw.print(" irq, ");
+ pw.print(rec.stepDetails.statSoftIrqTime);
+ pw.print(" sirq, ");
+ pw.print(rec.stepDetails.statIdlTime);
+ pw.print(" idle");
+ int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
+ + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
+ + rec.stepDetails.statSoftIrqTime;
+ int total = totalRun + rec.stepDetails.statIdlTime;
+ if (total > 0) {
+ pw.print(" (");
+ float perc = ((float)totalRun) / ((float)total) * 100;
+ pw.print(String.format("%.1f%%", perc));
+ pw.print(" of ");
+ StringBuilder sb = new StringBuilder(64);
+ formatTimeMsNoSpace(sb, total*10);
+ pw.print(sb);
+ pw.print(")");
+ }
+ pw.println();
+ } else {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
+ pw.print(rec.stepDetails.userTime);
+ pw.print(":");
+ pw.print(rec.stepDetails.systemTime);
+ if (rec.stepDetails.appCpuUid1 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
+ rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
+ if (rec.stepDetails.appCpuUid2 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
+ rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
+ }
+ if (rec.stepDetails.appCpuUid3 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
+ rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
+ }
+ }
+ pw.println();
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
+ pw.print(rec.stepDetails.statUserTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statSystemTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIOWaitTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIrqTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statSoftIrqTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIdlTime);
+ pw.println();
+ }
+ }
oldState = rec.states;
oldState2 = rec.states2;
}
}
+
+ private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
+ UserHandle.formatUid(pw, uid);
+ pw.print("=");
+ pw.print(utime);
+ pw.print("u+");
+ pw.print(stime);
+ pw.print("s");
+ }
+
+ private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
+ pw.print('/');
+ pw.print(uid);
+ pw.print(":");
+ pw.print(utime);
+ pw.print(":");
+ pw.print(stime);
+ }
}
private void printSizeValue(PrintWriter pw, long size) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 20bb95e..d0c7f8c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -94,7 +94,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 116 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 118 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -208,7 +208,7 @@ public final class BatteryStatsImpl extends BatteryStats {
final HistoryItem mHistoryLastLastWritten = new HistoryItem();
final HistoryItem mHistoryReadTmp = new HistoryItem();
final HistoryItem mHistoryAddTmp = new HistoryItem();
- final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<HistoryTag, Integer>();
+ final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap();
String[] mReadHistoryStrings;
int[] mReadHistoryUids;
int mReadHistoryChars;
@@ -227,6 +227,38 @@ public final class BatteryStatsImpl extends BatteryStats {
HistoryItem mHistoryLastEnd;
HistoryItem mHistoryCache;
+ // Used by computeHistoryStepDetails
+ HistoryStepDetails mLastHistoryStepDetails = null;
+ byte mLastHistoryStepLevel = 0;
+ final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
+ /**
+ * Total time (in 1/100 sec) spent executing in user code.
+ */
+ long mLastStepCpuUserTime;
+ long mCurStepCpuUserTime;
+ /**
+ * Total time (in 1/100 sec) spent executing in kernel code.
+ */
+ long mLastStepCpuSystemTime;
+ long mCurStepCpuSystemTime;
+ /**
+ * Times from /proc/stat
+ */
+ long mLastStepStatUserTime;
+ long mLastStepStatSystemTime;
+ long mLastStepStatIOWaitTime;
+ long mLastStepStatIrqTime;
+ long mLastStepStatSoftIrqTime;
+ long mLastStepStatIdleTime;
+ long mCurStepStatUserTime;
+ long mCurStepStatSystemTime;
+ long mCurStepStatIOWaitTime;
+ long mCurStepStatIrqTime;
+ long mCurStepStatSoftIrqTime;
+ long mCurStepStatIdleTime;
+
private HistoryItem mHistoryIterator;
private boolean mReadOverflow;
private boolean mIteratingHistory;
@@ -1938,6 +1970,10 @@ public final class BatteryStatsImpl extends BatteryStats {
static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
static final int STATE_BATTERY_PLUG_SHIFT = 24;
+ // We use the low bit of the battery state int to indicate that we have full details
+ // from a battery level change.
+ static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+
public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
dest.writeInt(DELTA_TIME_ABS);
@@ -1958,7 +1994,11 @@ public final class BatteryStatsImpl extends BatteryStats {
deltaTimeToken = (int)deltaTime;
}
int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
- final int batteryLevelInt = buildBatteryLevelInt(cur);
+ final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
+ ? BATTERY_DELTA_LEVEL_FLAG : 0;
+ final boolean computeStepDetails = includeStepDetails != 0
+ || mLastHistoryStepDetails == null;
+ final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
if (batteryLevelIntChanged) {
firstToken |= DELTA_BATTERY_LEVEL_FLAG;
@@ -2040,12 +2080,26 @@ public final class BatteryStatsImpl extends BatteryStats {
+ cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
+ cur.eventTag.string);
}
+ if (computeStepDetails) {
+ computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
+ if (includeStepDetails != 0) {
+ mCurHistoryStepDetails.writeToParcel(dest);
+ }
+ cur.stepDetails = mCurHistoryStepDetails;
+ mLastHistoryStepDetails = mCurHistoryStepDetails;
+ } else {
+ cur.stepDetails = null;
+ }
+ if (mLastHistoryStepLevel < cur.batteryLevel) {
+ mLastHistoryStepDetails = null;
+ }
+ mLastHistoryStepLevel = cur.batteryLevel;
}
private int buildBatteryLevelInt(HistoryItem h) {
return ((((int)h.batteryLevel)<<25)&0xfe000000)
- | ((((int)h.batteryTemperature)<<14)&0x01ffc000)
- | (((int)h.batteryVoltage)&0x00003fff);
+ | ((((int)h.batteryTemperature)<<14)&0x01ff8000)
+ | ((((int)h.batteryVoltage)<<1)&0x00007fff);
}
private int buildStateInt(HistoryItem h) {
@@ -2063,6 +2117,98 @@ public final class BatteryStatsImpl extends BatteryStats {
| (h.states&(~DELTA_STATE_MASK));
}
+ private void computeHistoryStepDetails(final HistoryStepDetails out,
+ final HistoryStepDetails last) {
+ final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
+
+ // Perform a CPU update right after we do this collection, so we have started
+ // collecting good data for the next step.
+ requestImmediateCpuUpdate();
+
+ if (last == null) {
+ // We are not generating a delta, so all we need to do is reset the stats
+ // we will later be doing a delta from.
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ uid.mLastStepUserTime = uid.mCurStepUserTime;
+ uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ }
+ mLastStepCpuUserTime = mCurStepCpuUserTime;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime;
+ mLastStepStatUserTime = mCurStepStatUserTime;
+ mLastStepStatSystemTime = mCurStepStatSystemTime;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
+ mLastStepStatIrqTime = mCurStepStatIrqTime;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
+ mLastStepStatIdleTime = mCurStepStatIdleTime;
+ tmp.clear();
+ return;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
+ + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
+ + " irq=" + mLastStepStatIrqTime + " sirq="
+ + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
+ Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
+ + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
+ + " irq=" + mCurStepStatIrqTime + " sirq="
+ + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
+ }
+ out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
+ out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
+ out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
+ out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
+ out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
+ out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
+ out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
+ out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
+ out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
+ out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
+ out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
+ final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
+ final int totalTime = totalUTime + totalSTime;
+ uid.mLastStepUserTime = uid.mCurStepUserTime;
+ uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
+ continue;
+ }
+ if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
+ out.appCpuUid3 = uid.mUid;
+ out.appCpuUTime3 = totalUTime;
+ out.appCpuSTime3 = totalSTime;
+ } else {
+ out.appCpuUid3 = out.appCpuUid2;
+ out.appCpuUTime3 = out.appCpuUTime2;
+ out.appCpuSTime3 = out.appCpuSTime2;
+ if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
+ out.appCpuUid2 = uid.mUid;
+ out.appCpuUTime2 = totalUTime;
+ out.appCpuSTime2 = totalSTime;
+ } else {
+ out.appCpuUid2 = out.appCpuUid1;
+ out.appCpuUTime2 = out.appCpuUTime1;
+ out.appCpuSTime2 = out.appCpuSTime1;
+ out.appCpuUid1 = uid.mUid;
+ out.appCpuUTime1 = totalUTime;
+ out.appCpuSTime1 = totalSTime;
+ }
+ }
+ }
+ mLastStepCpuUserTime = mCurStepCpuUserTime;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime;
+ mLastStepStatUserTime = mCurStepStatUserTime;
+ mLastStepStatSystemTime = mCurStepStatSystemTime;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
+ mLastStepStatIrqTime = mCurStepStatIrqTime;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
+ mLastStepStatIdleTime = mCurStepStatIdleTime;
+ }
+
public void readHistoryDelta(Parcel src, HistoryItem cur) {
int firstToken = src.readInt();
int deltaTimeToken = firstToken&DELTA_TIME_MASK;
@@ -2091,8 +2237,9 @@ public final class BatteryStatsImpl extends BatteryStats {
cur.numReadInts += 2;
}
+ final int batteryLevelInt;
if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
- int batteryLevelInt = src.readInt();
+ batteryLevelInt = src.readInt();
cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f);
cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21);
cur.batteryVoltage = (char)(batteryLevelInt&0x3fff);
@@ -2102,6 +2249,8 @@ public final class BatteryStatsImpl extends BatteryStats {
+ " batteryLevel=" + cur.batteryLevel
+ " batteryTemp=" + cur.batteryTemperature
+ " batteryVolt=" + (int)cur.batteryVoltage);
+ } else {
+ batteryLevelInt = 0;
}
if ((firstToken&DELTA_STATE_FLAG) != 0) {
@@ -2180,6 +2329,13 @@ public final class BatteryStatsImpl extends BatteryStats {
} else {
cur.eventCode = HistoryItem.EVENT_NONE;
}
+
+ if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
+ cur.stepDetails = mReadHistoryStepDetails;
+ cur.stepDetails.readFromParcel(src);
+ } else {
+ cur.stepDetails = null;
+ }
}
@Override
@@ -2207,6 +2363,7 @@ public final class BatteryStatsImpl extends BatteryStats {
&& (diffStates2&lastDiffStates2) == 0
&& (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
&& (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
+ && mHistoryLastWritten.stepDetails == null
&& (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
|| cur.eventCode == HistoryItem.EVENT_NONE)
&& mHistoryLastWritten.batteryLevel == cur.batteryLevel
@@ -2632,6 +2789,11 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ private void requestImmediateCpuUpdate() {
+ mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
+ }
+
public void setRecordAllHistoryLocked(boolean enabled) {
mRecordAllHistory = enabled;
if (!enabled) {
@@ -2823,6 +2985,10 @@ public final class BatteryStatsImpl extends BatteryStats {
public int startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ if (!mOnBatteryInternal) {
+ return -1;
+ }
+
final int N = mPartialTimers.size();
if (N == 0) {
mLastPartialTimers.clear();
@@ -2853,7 +3019,23 @@ public final class BatteryStatsImpl extends BatteryStats {
return 0;
}
- public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
+ public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime,
+ int totalUTime, int totalSTime, int statUserTime, int statSystemTime,
+ int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime,
+ long[] cpuSpeedTimes) {
+ if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
+ + " user=" + statUserTime + " sys=" + statSystemTime
+ + " io=" + statIOWaitTime + " irq=" + statIrqTime
+ + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
+ mCurStepCpuUserTime += totalUTime;
+ mCurStepCpuSystemTime += totalSTime;
+ mCurStepStatUserTime += statUserTime;
+ mCurStepStatSystemTime += statSystemTime;
+ mCurStepStatIOWaitTime += statIOWaitTime;
+ mCurStepStatIrqTime += statIrqTime;
+ mCurStepStatSoftIrqTime += statSoftIrqTime;
+ mCurStepStatIdleTime += statIdleTime;
+
final int N = mPartialTimers.size();
if (perc != 0) {
int num = 0;
@@ -2874,26 +3056,24 @@ public final class BatteryStatsImpl extends BatteryStats {
if (st.mInList) {
Uid uid = st.mUid;
if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- int myUTime = utime/num;
- int mySTime = stime/num;
- utime -= myUTime;
- stime -= mySTime;
+ int myUTime = remainUTime/num;
+ int mySTime = remainSTtime/num;
+ remainUTime -= myUTime;
+ remainSTtime -= mySTime;
num--;
Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
- proc.addCpuTimeLocked(myUTime, mySTime);
- proc.addSpeedStepTimes(cpuSpeedTimes);
+ proc.addCpuTimeLocked(myUTime, mySTime, cpuSpeedTimes);
}
}
}
}
// Just in case, collect any lost CPU time.
- if (utime != 0 || stime != 0) {
+ if (remainUTime != 0 || remainSTtime != 0) {
Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
if (uid != null) {
Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
- proc.addCpuTimeLocked(utime, stime);
- proc.addSpeedStepTimes(cpuSpeedTimes);
+ proc.addCpuTimeLocked(remainUTime, remainSTtime, cpuSpeedTimes);
}
}
}
@@ -4214,6 +4394,14 @@ public final class BatteryStatsImpl extends BatteryStats {
LongSamplingCounter mMobileRadioActiveCount;
/**
+ * The CPU times we had at the last history details update.
+ */
+ long mLastStepUserTime;
+ long mLastStepSystemTime;
+ long mCurStepUserTime;
+ long mCurStepSystemTime;
+
+ /**
* The statistics we have collected for this uid's wake locks.
*/
final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
@@ -4876,6 +5064,9 @@ public final class BatteryStatsImpl extends BatteryStats {
mPackageStats.clear();
}
+ mLastStepUserTime = mLastStepSystemTime = 0;
+ mCurStepUserTime = mCurStepSystemTime = 0;
+
if (!active) {
if (mWifiRunningTimer != null) {
mWifiRunningTimer.detach();
@@ -5678,9 +5869,22 @@ public final class BatteryStatsImpl extends BatteryStats {
return BatteryStatsImpl.this;
}
- public void addCpuTimeLocked(int utime, int stime) {
+ public void addCpuTimeLocked(int utime, int stime, long[] speedStepBins) {
mUserTime += utime;
+ mCurStepUserTime += utime;
mSystemTime += stime;
+ mCurStepSystemTime += stime;
+
+ for (int i = 0; i < mSpeedBins.length && i < speedStepBins.length; i++) {
+ long amt = speedStepBins[i];
+ if (amt != 0) {
+ SamplingCounter c = mSpeedBins[i];
+ if (c == null) {
+ mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
+ }
+ c.addCountAtomic(speedStepBins[i]);
+ }
+ }
}
public void addForegroundTimeLocked(long ttime) {
@@ -5770,20 +5974,6 @@ public final class BatteryStatsImpl extends BatteryStats {
return val;
}
- /* Called by ActivityManagerService when CPU times are updated. */
- public void addSpeedStepTimes(long[] values) {
- for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
- long amt = values[i];
- if (amt != 0) {
- SamplingCounter c = mSpeedBins[i];
- if (c == null) {
- mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
- }
- c.addCountAtomic(values[i]);
- }
- }
- }
-
@Override
public long getTimeAtCpuSpeedStep(int speedStep, int which) {
if (speedStep < mSpeedBins.length) {
@@ -6756,6 +6946,18 @@ public final class BatteryStatsImpl extends BatteryStats {
mWakeupReasonStats.clear();
}
+ mLastHistoryStepDetails = null;
+ mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
+ mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
+ mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
+ mLastStepStatUserTime = mCurStepStatUserTime = 0;
+ mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
+ mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
+ mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
+
initDischarge();
clearHistoryLocked();
@@ -6872,7 +7074,7 @@ public final class BatteryStatsImpl extends BatteryStats {
reset = true;
mNumDischargeStepDurations = 0;
}
- mOnBattery = mOnBatteryInternal = onBattery;
+ mOnBattery = mOnBatteryInternal = true;
mLastDischargeStepLevel = level;
mMinDischargeStepLevel = level;
mLastDischargeStepTime = -1;
@@ -6900,7 +7102,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mDischargeAmountScreenOff = 0;
updateTimeBasesLocked(true, !screenOn, uptime, realtime);
} else {
- mOnBattery = mOnBatteryInternal = onBattery;
+ mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index b5338df..501e0ec 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -152,6 +152,7 @@ public class ProcessCpuTracker {
private int mRelIrqTime;
private int mRelSoftIrqTime;
private int mRelIdleTime;
+ private boolean mRelStatsAreGood;
private int[] mCurPids;
private int[] mCurThreadPids;
@@ -285,10 +286,9 @@ public class ProcessCpuTracker {
public void update() {
if (DEBUG) Slog.v(TAG, "Update: " + this);
- mLastSampleTime = mCurrentSampleTime;
- mCurrentSampleTime = SystemClock.uptimeMillis();
- mLastSampleRealTime = mCurrentSampleRealTime;
- mCurrentSampleRealTime = SystemClock.elapsedRealtime();
+
+ final long nowUptime = SystemClock.uptimeMillis();
+ final long nowRealtime = SystemClock.elapsedRealtime();
final long[] sysCpu = mSystemCpuData;
if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
@@ -304,30 +304,53 @@ public class ProcessCpuTracker {
final long irqtime = sysCpu[5];
final long softirqtime = sysCpu[6];
- mRelUserTime = (int)(usertime - mBaseUserTime);
- mRelSystemTime = (int)(systemtime - mBaseSystemTime);
- mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
- mRelIrqTime = (int)(irqtime - mBaseIrqTime);
- mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
- mRelIdleTime = (int)(idletime - mBaseIdleTime);
-
- if (DEBUG) {
- Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
- + " S:" + sysCpu[2] + " I:" + sysCpu[3]
- + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
- + " O:" + sysCpu[6]);
- Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
- + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
- }
+ // This code is trying to avoid issues with idle time going backwards,
+ // but currently it gets into situations where it triggers most of the time. :(
+ if (true || (usertime >= mBaseUserTime && systemtime >= mBaseSystemTime
+ && iowaittime >= mBaseIoWaitTime && irqtime >= mBaseIrqTime
+ && softirqtime >= mBaseSoftIrqTime && idletime >= mBaseIdleTime)) {
+ mRelUserTime = (int)(usertime - mBaseUserTime);
+ mRelSystemTime = (int)(systemtime - mBaseSystemTime);
+ mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
+ mRelIrqTime = (int)(irqtime - mBaseIrqTime);
+ mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
+ mRelIdleTime = (int)(idletime - mBaseIdleTime);
+ mRelStatsAreGood = true;
+
+ if (DEBUG) {
+ Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
+ + " S:" + sysCpu[2] + " I:" + sysCpu[3]
+ + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
+ + " O:" + sysCpu[6]);
+ Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
+ + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
+ }
+
+ mBaseUserTime = usertime;
+ mBaseSystemTime = systemtime;
+ mBaseIoWaitTime = iowaittime;
+ mBaseIrqTime = irqtime;
+ mBaseSoftIrqTime = softirqtime;
+ mBaseIdleTime = idletime;
- mBaseUserTime = usertime;
- mBaseSystemTime = systemtime;
- mBaseIoWaitTime = iowaittime;
- mBaseIrqTime = irqtime;
- mBaseSoftIrqTime = softirqtime;
- mBaseIdleTime = idletime;
+ } else {
+ mRelUserTime = 0;
+ mRelSystemTime = 0;
+ mRelIoWaitTime = 0;
+ mRelIrqTime = 0;
+ mRelSoftIrqTime = 0;
+ mRelIdleTime = 0;
+ mRelStatsAreGood = false;
+ Slog.w(TAG, "/proc/stats has gone backwards; skipping CPU update");
+ return;
+ }
}
+ mLastSampleTime = mCurrentSampleTime;
+ mCurrentSampleTime = nowUptime;
+ mLastSampleRealTime = mCurrentSampleRealTime;
+ mCurrentSampleRealTime = nowRealtime;
+
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
try {
mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);
@@ -647,6 +670,10 @@ public class ProcessCpuTracker {
return mRelIdleTime;
}
+ final public boolean hasGoodLastStats() {
+ return mRelStatsAreGood;
+ }
+
final public float getTotalCpuPercent() {
int denom = mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime;
if (denom <= 0) {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 912a181..b3b4651 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -626,6 +626,22 @@ public final class BatteryService extends SystemService {
pw.println(" voltage: " + mBatteryProps.batteryVoltage);
pw.println(" temperature: " + mBatteryProps.batteryTemperature);
pw.println(" technology: " + mBatteryProps.batteryTechnology);
+
+ } else if ("unplug".equals(args[0])) {
+ if (!mUpdatesStopped) {
+ mLastBatteryProps.set(mBatteryProps);
+ }
+ mBatteryProps.chargerAcOnline = false;
+ mBatteryProps.chargerUsbOnline = false;
+ mBatteryProps.chargerWirelessOnline = false;
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mUpdatesStopped = true;
+ processValuesLocked(false);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
} else if (args.length == 3 && "set".equals(args[0])) {
String key = args[1];
String value = args[2];
@@ -662,6 +678,7 @@ public final class BatteryService extends SystemService {
} catch (NumberFormatException ex) {
pw.println("Bad value: " + value);
}
+
} else if (args.length == 1 && "reset".equals(args[0])) {
long ident = Binder.clearCallingIdentity();
try {
@@ -676,6 +693,7 @@ public final class BatteryService extends SystemService {
} else {
pw.println("Dump current battery state, or:");
pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ pw.println(" unplug");
pw.println(" reset");
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 511347e..d53b61b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2255,31 +2255,33 @@ public final class ActivityManagerService extends ActivityManagerNative
if (MONITOR_CPU_USAGE &&
mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
mLastCpuTime.set(now);
- haveNewCpuStats = true;
mProcessCpuTracker.update();
- //Slog.i(TAG, mProcessCpu.printCurrentState());
- //Slog.i(TAG, "Total CPU usage: "
- // + mProcessCpu.getTotalCpuPercent() + "%");
+ if (mProcessCpuTracker.hasGoodLastStats()) {
+ haveNewCpuStats = true;
+ //Slog.i(TAG, mProcessCpu.printCurrentState());
+ //Slog.i(TAG, "Total CPU usage: "
+ // + mProcessCpu.getTotalCpuPercent() + "%");
- // Slog the cpu usage if the property is set.
- if ("true".equals(SystemProperties.get("events.cpu"))) {
- int user = mProcessCpuTracker.getLastUserTime();
- int system = mProcessCpuTracker.getLastSystemTime();
- int iowait = mProcessCpuTracker.getLastIoWaitTime();
- int irq = mProcessCpuTracker.getLastIrqTime();
- int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
- int idle = mProcessCpuTracker.getLastIdleTime();
+ // Slog the cpu usage if the property is set.
+ if ("true".equals(SystemProperties.get("events.cpu"))) {
+ int user = mProcessCpuTracker.getLastUserTime();
+ int system = mProcessCpuTracker.getLastSystemTime();
+ int iowait = mProcessCpuTracker.getLastIoWaitTime();
+ int irq = mProcessCpuTracker.getLastIrqTime();
+ int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
+ int idle = mProcessCpuTracker.getLastIdleTime();
- int total = user + system + iowait + irq + softIrq + idle;
- if (total == 0) total = 1;
+ int total = user + system + iowait + irq + softIrq + idle;
+ if (total == 0) total = 1;
- EventLog.writeEvent(EventLogTags.CPU,
- ((user+system+iowait+irq+softIrq) * 100) / total,
- (user * 100) / total,
- (system * 100) / total,
- (iowait * 100) / total,
- (irq * 100) / total,
- (softIrq * 100) / total);
+ EventLog.writeEvent(EventLogTags.CPU,
+ ((user+system+iowait+irq+softIrq) * 100) / total,
+ (user * 100) / total,
+ (system * 100) / total,
+ (iowait * 100) / total,
+ (irq * 100) / total,
+ (softIrq * 100) / total);
+ }
}
}
@@ -2288,8 +2290,10 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
- if (mOnBattery) {
- int perc = bstats.startAddingCpuLocked();
+ final int perc = bstats.startAddingCpuLocked();
+ if (perc >= 0) {
+ int remainUTime = 0;
+ int remainSTime = 0;
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessCpuTracker.countStats();
@@ -2301,17 +2305,18 @@ public final class ActivityManagerService extends ActivityManagerNative
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime*perc)/100;
int otherSTime = (st.rel_stime*perc)/100;
- totalUTime += otherUTime;
- totalSTime += otherSTime;
+ remainUTime += otherUTime;
+ remainSTime += otherSTime;
+ totalUTime += st.rel_utime;
+ totalSTime += st.rel_stime;
if (pr != null) {
BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats;
if (ps == null || !ps.isActive()) {
pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
pr.info.uid, pr.processName);
}
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
+ ps.addCpuTimeLocked(st.rel_utime - otherUTime,
+ st.rel_stime - otherSTime, cpuSpeedTimes);
pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
@@ -2319,13 +2324,19 @@ public final class ActivityManagerService extends ActivityManagerNative
st.batteryStats = ps = bstats.getProcessStatsLocked(
bstats.mapUid(st.uid), st.name);
}
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
+ ps.addCpuTimeLocked(st.rel_utime - otherUTime,
+ st.rel_stime - otherSTime, cpuSpeedTimes);
}
}
- bstats.finishAddingCpuLocked(perc, totalUTime,
- totalSTime, cpuSpeedTimes);
+ final int userTime = mProcessCpuTracker.getLastUserTime();
+ final int systemTime = mProcessCpuTracker.getLastSystemTime();
+ final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime();
+ final int irqTime = mProcessCpuTracker.getLastIrqTime();
+ final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
+ final int idleTime = mProcessCpuTracker.getLastIdleTime();
+ bstats.finishAddingCpuLocked(perc, remainUTime,
+ remainSTime, totalUTime, totalSTime, userTime, systemTime,
+ iowaitTime, irqTime, softIrqTime, idleTime, cpuSpeedTimes);
}
}
}