diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-02-18 14:02:14 -0800 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2015-02-19 17:37:12 -0800 |
commit | d1eccbea388fde6a575acb4e797efdd07798344a (patch) | |
tree | b46ba39c6f578b7186fc5661a08e41249abc4d15 /core/java/com | |
parent | 8de8627657b0e5b5028c544f1e444f8b1aadfe11 (diff) | |
download | frameworks_base-d1eccbea388fde6a575acb4e797efdd07798344a.zip frameworks_base-d1eccbea388fde6a575acb4e797efdd07798344a.tar.gz frameworks_base-d1eccbea388fde6a575acb4e797efdd07798344a.tar.bz2 |
Add some detailed data as part of battery history.
Every time the battery level changes, a new extended
detailed use data structure is written to the history.
This currently only contains delta CPU use since the
last detailed entry (total CPU and to three uids), but
it gives us the infrastructure for adding more detailed
data in the future.
A detail entry for regular history looks like:
Details: cpu=15730u+2307s (u0a57=11312u+502s, 1000=2344u+701s, 0=473u+991s)
/proc/stat=15377 usr, 1797 sys, 197 io, 0 irq, 8 sirq, 23103 idle (42.9% of 6m 44s 820ms)
u is user-space cpu time, s is system/kernel time.
The equivalent check-in output is:
9,h,0,Dcpu=15730:2307/10057:11312:502/1000:2344:701/0:473:991
9,h,0,Dpst=15377,1797,197,0,8,23103
Also add a new "unplug" command to the battery service,
to easily put it into a state where it always considers
the device to be running on battery.
Change-Id: Ic76d966f11e592b9dd671879977bf999ebc11eef
Diffstat (limited to 'core/java/com')
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 268 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ProcessCpuTracker.java | 77 |
2 files changed, 287 insertions, 58 deletions
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) { |