Fix issue #28602068: Add count to job scheduler stats
Also increase the event buffer size to 100, and implement
it as a real ring buffer. And put that implementation in
a generic class for use in other places.
Change-Id: I06936984e2c253fb5f0eb5d15faf0019ec73d4e2
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 4ba9dae..eb5edd3 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -23,6 +23,7 @@
import android.util.ArrayMap;
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.util.RingBufferIndices;
import com.android.server.job.controllers.JobStatus;
import java.io.PrintWriter;
@@ -33,26 +34,24 @@
// Number of historical data sets we keep.
static final int NUM_HISTORY = 5;
- private static final int EVENT_BUFFER_SIZE = 50;
+ private static final int EVENT_BUFFER_SIZE = 100;
public static final int EVENT_NULL = 0;
public static final int EVENT_START_JOB = 1;
public static final int EVENT_STOP_JOB = 2;
- private int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
- private long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
- private int[] mEventUids = new int[EVENT_BUFFER_SIZE];
- private String[] mEventTags = new String[EVENT_BUFFER_SIZE];
+ private final RingBufferIndices mEventIndices = new RingBufferIndices(EVENT_BUFFER_SIZE);
+ private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
+ private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
+ private final int[] mEventUids = new int[EVENT_BUFFER_SIZE];
+ private final String[] mEventTags = new String[EVENT_BUFFER_SIZE];
public void addEvent(int cmd, int uid, String tag) {
- System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
- System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
- System.arraycopy(mEventUids, 0, mEventUids, 1, EVENT_BUFFER_SIZE - 1);
- System.arraycopy(mEventTags, 0, mEventTags, 1, EVENT_BUFFER_SIZE - 1);
- mEventCmds[0] = cmd;
- mEventTimes[0] = SystemClock.elapsedRealtime();
- mEventUids[0] = uid;
- mEventTags[0] = tag;
+ int index = mEventIndices.add();
+ mEventCmds[index] = cmd;
+ mEventTimes[index] = SystemClock.elapsedRealtime();
+ mEventUids[index] = uid;
+ mEventTags[index] = tag;
}
DataSet mCurDataSet = new DataSet();
@@ -61,20 +60,23 @@
final static class PackageEntry {
long pastActiveTime;
long activeStartTime;
+ int activeNesting;
int activeCount;
boolean hadActive;
long pastActiveTopTime;
long activeTopStartTime;
+ int activeTopNesting;
int activeTopCount;
boolean hadActiveTop;
long pastPendingTime;
long pendingStartTime;
+ int pendingNesting;
int pendingCount;
boolean hadPending;
public long getActiveTime(long now) {
long time = pastActiveTime;
- if (activeCount > 0) {
+ if (activeNesting > 0) {
time += now - activeStartTime;
}
return time;
@@ -82,7 +84,7 @@
public long getActiveTopTime(long now) {
long time = pastActiveTopTime;
- if (activeTopCount > 0) {
+ if (activeTopNesting > 0) {
time += now - activeTopStartTime;
}
return time;
@@ -90,7 +92,7 @@
public long getPendingTime(long now) {
long time = pastPendingTime;
- if (pendingCount > 0) {
+ if (pendingNesting > 0) {
time += now - pendingStartTime;
}
return time;
@@ -147,50 +149,53 @@
void incPending(int uid, String pkg, long now) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
- if (pe.pendingCount == 0) {
+ if (pe.pendingNesting == 0) {
pe.pendingStartTime = now;
+ pe.pendingCount++;
}
- pe.pendingCount++;
+ pe.pendingNesting++;
}
void decPending(int uid, String pkg, long now) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
- if (pe.pendingCount == 1) {
+ if (pe.pendingNesting == 1) {
pe.pastPendingTime += now - pe.pendingStartTime;
}
- pe.pendingCount--;
+ pe.pendingNesting--;
}
void incActive(int uid, String pkg, long now) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
- if (pe.activeCount == 0) {
+ if (pe.activeNesting == 0) {
pe.activeStartTime = now;
+ pe.activeCount++;
}
- pe.activeCount++;
+ pe.activeNesting++;
}
void decActive(int uid, String pkg, long now) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
- if (pe.activeCount == 1) {
+ if (pe.activeNesting == 1) {
pe.pastActiveTime += now - pe.activeStartTime;
}
- pe.activeCount--;
+ pe.activeNesting--;
}
void incActiveTop(int uid, String pkg, long now) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
- if (pe.activeTopCount == 0) {
+ if (pe.activeTopNesting == 0) {
pe.activeTopStartTime = now;
+ pe.activeTopCount++;
}
- pe.activeTopCount++;
+ pe.activeTopNesting++;
}
void decActiveTop(int uid, String pkg, long now) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
- if (pe.activeTopCount == 1) {
+ if (pe.activeTopNesting == 1) {
pe.pastActiveTopTime += now - pe.activeTopStartTime;
}
- pe.activeTopCount--;
+ pe.activeTopNesting--;
}
void finish(DataSet next, long now) {
@@ -198,27 +203,27 @@
ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
for (int j = uidMap.size() - 1; j >= 0; j--) {
PackageEntry pe = uidMap.valueAt(j);
- if (pe.activeCount > 0 || pe.activeTopCount > 0 || pe.pendingCount > 0) {
+ if (pe.activeNesting > 0 || pe.activeTopNesting > 0 || pe.pendingNesting > 0) {
// Propagate existing activity in to next data set.
PackageEntry nextPe = next.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
nextPe.activeStartTime = now;
- nextPe.activeCount = pe.activeCount;
+ nextPe.activeNesting = pe.activeNesting;
nextPe.activeTopStartTime = now;
- nextPe.activeTopCount = pe.activeTopCount;
+ nextPe.activeTopNesting = pe.activeTopNesting;
nextPe.pendingStartTime = now;
- nextPe.pendingCount = pe.pendingCount;
+ nextPe.pendingNesting = pe.pendingNesting;
// Finish it off.
- if (pe.activeCount > 0) {
+ if (pe.activeNesting > 0) {
pe.pastActiveTime += now - pe.activeStartTime;
- pe.activeCount = 0;
+ pe.activeNesting = 0;
}
- if (pe.activeTopCount > 0) {
+ if (pe.activeTopNesting > 0) {
pe.pastActiveTopTime += now - pe.activeTopStartTime;
- pe.activeTopCount = 0;
+ pe.activeTopNesting = 0;
}
- if (pe.pendingCount > 0) {
+ if (pe.pendingNesting > 0) {
pe.pastPendingTime += now - pe.pendingStartTime;
- pe.pendingCount = 0;
+ pe.pendingNesting = 0;
}
}
}
@@ -233,17 +238,20 @@
PackageEntry pe = uidMap.valueAt(j);
PackageEntry outPe = out.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
outPe.pastActiveTime += pe.pastActiveTime;
+ outPe.activeCount += pe.activeCount;
outPe.pastActiveTopTime += pe.pastActiveTopTime;
+ outPe.activeTopCount += pe.activeTopCount;
outPe.pastPendingTime += pe.pastPendingTime;
- if (pe.activeCount > 0) {
+ outPe.pendingCount += pe.pendingCount;
+ if (pe.activeNesting > 0) {
outPe.pastActiveTime += now - pe.activeStartTime;
outPe.hadActive = true;
}
- if (pe.activeTopCount > 0) {
+ if (pe.activeTopNesting > 0) {
outPe.pastActiveTopTime += now - pe.activeTopStartTime;
outPe.hadActiveTop = true;
}
- if (pe.pendingCount > 0) {
+ if (pe.pendingNesting > 0) {
outPe.pastPendingTime += now - pe.pendingStartTime;
outPe.hadPending = true;
}
@@ -251,13 +259,20 @@
}
}
- void printDuration(PrintWriter pw, long period, long duration, String suffix) {
+ void printDuration(PrintWriter pw, long period, long duration, int count, String suffix) {
float fraction = duration / (float) period;
int percent = (int) ((fraction * 100) + .5f);
if (percent > 0) {
pw.print(" ");
pw.print(percent);
pw.print("% ");
+ pw.print(count);
+ pw.print("x ");
+ pw.print(suffix);
+ } else if (count > 0) {
+ pw.print(" ");
+ pw.print(count);
+ pw.print("x ");
pw.print(suffix);
}
}
@@ -286,16 +301,17 @@
UserHandle.formatUid(pw, uid);
pw.print(" / "); pw.print(uidMap.keyAt(j));
pw.print(":");
- printDuration(pw, period, pe.getPendingTime(now), "pending");
- printDuration(pw, period, pe.getActiveTime(now), "active");
- printDuration(pw, period, pe.getActiveTopTime(now), "active-top");
- if (pe.pendingCount > 0 || pe.hadPending) {
+ printDuration(pw, period, pe.getPendingTime(now), pe.pendingCount, "pending");
+ printDuration(pw, period, pe.getActiveTime(now), pe.activeCount, "active");
+ printDuration(pw, period, pe.getActiveTopTime(now), pe.activeTopCount,
+ "active-top");
+ if (pe.pendingNesting > 0 || pe.hadPending) {
pw.print(" (pending)");
}
- if (pe.activeCount > 0 || pe.hadActive) {
+ if (pe.activeNesting > 0 || pe.hadActive) {
pw.print(" (active)");
}
- if (pe.activeTopCount > 0 || pe.hadActiveTop) {
+ if (pe.activeTopNesting > 0 || pe.hadActiveTop) {
pw.print(" (active-top)");
}
pw.println();
@@ -389,34 +405,36 @@
}
public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
- if (mEventCmds[0] == EVENT_NULL) {
+ final int size = mEventIndices.size();
+ if (size <= 0) {
return false;
}
pw.println(" Job history:");
- long now = SystemClock.elapsedRealtime();
- for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
- int uid = mEventUids[i];
+ final long now = SystemClock.elapsedRealtime();
+ for (int i=0; i<size; i++) {
+ final int index = mEventIndices.indexOf(i);
+ final int uid = mEventUids[index];
if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) {
continue;
}
- int cmd = mEventCmds[i];
+ final int cmd = mEventCmds[index];
if (cmd == EVENT_NULL) {
continue;
}
- String label;
- switch (mEventCmds[i]) {
+ final String label;
+ switch (mEventCmds[index]) {
case EVENT_START_JOB: label = "START"; break;
case EVENT_STOP_JOB: label = " STOP"; break;
default: label = " ??"; break;
}
pw.print(prefix);
- TimeUtils.formatDuration(mEventTimes[i]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+ TimeUtils.formatDuration(mEventTimes[index]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
pw.print(" ");
pw.print(label);
pw.print(": ");
UserHandle.formatUid(pw, uid);
pw.print(" ");
- pw.println(mEventTags[i]);
+ pw.println(mEventTags[index]);
}
return true;
}