diff options
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); } } } |