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
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4213,6 +4393,14 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
LongSamplingCounter mMobileRadioActiveTime;
|
||||
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.
|
||||
*/
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
// 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);
|
||||
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;
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
mBaseUserTime = usertime;
|
||||
mBaseSystemTime = systemtime;
|
||||
mBaseIoWaitTime = iowaittime;
|
||||
mBaseIrqTime = irqtime;
|
||||
mBaseSoftIrqTime = softirqtime;
|
||||
mBaseIdleTime = idletime;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user