Retain milestone timestamps of historical broadcast activity

Also use a ring buffer now instead of using arraycopy() every time
we send a broadcast.

Bug 20297662
Bug 20426398

Change-Id: I682461f358e5bc6ebc63bbeb87d0ad07d85fe4b6
This commit is contained in:
Christopher Tate
2015-04-22 13:12:01 -07:00
parent f7de58130a
commit f278f12fae

View File

@@ -18,7 +18,9 @@ package com.android.server.am;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import android.app.ActivityManager;
import android.app.AppGlobals;
@@ -95,14 +97,27 @@ public final class BroadcastQueue {
final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();
/**
* Historical data of past broadcasts, for debugging.
* Historical data of past broadcasts, for debugging. This is a ring buffer
* whose last element is at mHistoryNext.
*/
final BroadcastRecord[] mBroadcastHistory = new BroadcastRecord[MAX_BROADCAST_HISTORY];
int mHistoryNext = 0;
/**
* Summary of historical data of past broadcasts, for debugging.
* Summary of historical data of past broadcasts, for debugging. This is a
* ring buffer whose last element is at mSummaryHistoryNext.
*/
final Intent[] mBroadcastSummaryHistory = new Intent[MAX_BROADCAST_SUMMARY_HISTORY];
int mSummaryHistoryNext = 0;
/**
* Various milestone timestamps of entries in the mBroadcastSummaryHistory ring
* buffer, also tracked via the mSummaryHistoryNext index. These are all in wall
* clock time, not elapsed.
*/
final long[] mSummaryHistoryEnqueueTime = new long[MAX_BROADCAST_SUMMARY_HISTORY];
final long[] mSummaryHistoryDispatchTime = new long[MAX_BROADCAST_SUMMARY_HISTORY];
final long[] mSummaryHistoryFinishTime = new long[MAX_BROADCAST_SUMMARY_HISTORY];
/**
* Set when we current have a BROADCAST_INTENT_MSG in flight.
@@ -1060,18 +1075,28 @@ public final class BroadcastQueue {
}
}
private final int ringAdvance(int x, final int increment, final int ringSize) {
x += increment;
if (x < 0) return (ringSize - 1);
else if (x >= ringSize) return 0;
else return x;
}
private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
if (r.callingUid < 0) {
// This was from a registerReceiver() call; ignore it.
return;
}
System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
MAX_BROADCAST_HISTORY-1);
r.finishTime = SystemClock.uptimeMillis();
mBroadcastHistory[0] = r;
System.arraycopy(mBroadcastSummaryHistory, 0, mBroadcastSummaryHistory, 1,
MAX_BROADCAST_SUMMARY_HISTORY-1);
mBroadcastSummaryHistory[0] = r.intent;
mBroadcastHistory[mHistoryNext] = r;
mHistoryNext = ringAdvance(mHistoryNext, 1, MAX_BROADCAST_HISTORY);
mBroadcastSummaryHistory[mSummaryHistoryNext] = r.intent;
mSummaryHistoryEnqueueTime[mSummaryHistoryNext] = r.enqueueClockTime;
mSummaryHistoryDispatchTime[mSummaryHistoryNext] = r.dispatchClockTime;
mSummaryHistoryFinishTime[mSummaryHistoryNext] = System.currentTimeMillis();
mSummaryHistoryNext = ringAdvance(mSummaryHistoryNext, 1, MAX_BROADCAST_SUMMARY_HISTORY);
}
final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
@@ -1158,11 +1183,20 @@ public final class BroadcastQueue {
int i;
boolean printed = false;
for (i=0; i<MAX_BROADCAST_HISTORY; i++) {
BroadcastRecord r = mBroadcastHistory[i];
i = -1;
int lastIndex = mHistoryNext;
int ringIndex = lastIndex;
do {
// increasing index = more recent entry, and we want to print the most
// recent first and work backwards, so we roll through the ring backwards.
ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_HISTORY);
BroadcastRecord r = mBroadcastHistory[ringIndex];
if (r == null) {
break;
continue;
}
i++; // genuine record of some sort even if we're filtering it out
if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
continue;
}
@@ -1190,17 +1224,33 @@ public final class BroadcastQueue {
pw.print(" extras: "); pw.println(bundle.toString());
}
}
}
} while (ringIndex != lastIndex);
if (dumpPackage == null) {
lastIndex = ringIndex = mSummaryHistoryNext;
if (dumpAll) {
i = 0;
printed = false;
i = -1;
} else {
// roll over the 'i' full dumps that have already been issued
for (int j = i;
j > 0 && ringIndex != lastIndex;) {
ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY);
BroadcastRecord r = mBroadcastHistory[ringIndex];
if (r == null) {
continue;
}
j--;
}
}
for (; i<MAX_BROADCAST_SUMMARY_HISTORY; i++) {
Intent intent = mBroadcastSummaryHistory[i];
// done skipping; dump the remainder of the ring. 'i' is still the ordinal within
// the overall broadcast history.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
do {
ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY);
Intent intent = mBroadcastSummaryHistory[ringIndex];
if (intent == null) {
break;
continue;
}
if (!printed) {
if (needSep) {
@@ -1214,13 +1264,17 @@ public final class BroadcastQueue {
pw.println(" ...");
break;
}
i++;
pw.print(" #"); pw.print(i); pw.print(": ");
pw.println(intent.toShortString(false, true, true, false));
pw.print(" enq="); pw.print(sdf.format(new Date(mSummaryHistoryEnqueueTime[ringIndex])));
pw.print(" disp="); pw.print(sdf.format(new Date(mSummaryHistoryDispatchTime[ringIndex])));
pw.print(" fin="); pw.println(sdf.format(new Date(mSummaryHistoryFinishTime[ringIndex])));
Bundle bundle = intent.getExtras();
if (bundle != null) {
pw.print(" extras: "); pw.println(bundle.toString());
}
}
} while (ringIndex != lastIndex);
}
return needSep;