Include more broadcasts related data in the activity service dump.

Bug: 268639079
Bug: 267503178
Test: manual
Change-Id: I80bdfea987099fa86e01bb457295e0271a8065e9
This commit is contained in:
Sudheer Shanka
2023-02-28 17:23:05 -08:00
parent 757ecb96db
commit 5dde7fffb1
6 changed files with 110 additions and 16 deletions

View File

@@ -142,6 +142,7 @@ message BroadcastQueueProto {
optional int64 finish_clock_time_ms = 4;
}
repeated BroadcastSummary historical_broadcasts_summary = 6;
repeated BroadcastRecordProto pending_broadcasts = 7;
}
message MemInfoDumpProto {

View File

@@ -17,6 +17,7 @@
package com.android.server.am;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Bundle;
import android.util.TimeUtils;
@@ -26,6 +27,7 @@ import dalvik.annotation.optimization.NeverCompile;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
/**
@@ -47,6 +49,11 @@ public class BroadcastHistory {
mSummaryHistoryFinishTime = new long[MAX_BROADCAST_SUMMARY_HISTORY];
}
/**
* List of broadcasts which are being delivered or yet to be delivered.
*/
private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();
/**
* Historical data of past broadcasts, for debugging. This is a ring buffer
* whose last element is at mHistoryNext.
@@ -70,7 +77,16 @@ public class BroadcastHistory {
final long[] mSummaryHistoryDispatchTime;
final long[] mSummaryHistoryFinishTime;
public void addBroadcastToHistoryLocked(BroadcastRecord original) {
void onBroadcastEnqueuedLocked(@NonNull BroadcastRecord r) {
mPendingBroadcasts.add(r);
}
void onBroadcastFinishedLocked(@NonNull BroadcastRecord r) {
mPendingBroadcasts.remove(r);
addBroadcastToHistoryLocked(r);
}
public void addBroadcastToHistoryLocked(@NonNull BroadcastRecord original) {
// Note sometimes (only for sticky broadcasts?) we reuse BroadcastRecords,
// So don't change the incoming record directly.
final BroadcastRecord historyRecord = original.maybeStripForHistory();
@@ -93,7 +109,12 @@ public class BroadcastHistory {
}
@NeverCompile
public void dumpDebug(ProtoOutputStream proto) {
public void dumpDebug(@NonNull ProtoOutputStream proto) {
for (int i = 0; i < mPendingBroadcasts.size(); ++i) {
final BroadcastRecord r = mPendingBroadcasts.get(i);
r.dumpDebug(proto, BroadcastQueueProto.PENDING_BROADCASTS);
}
int lastIndex = mHistoryNext;
int ringIndex = lastIndex;
do {
@@ -127,8 +148,20 @@ public class BroadcastHistory {
}
@NeverCompile
public boolean dumpLocked(PrintWriter pw, String dumpPackage, String queueName,
SimpleDateFormat sdf, boolean dumpAll, boolean needSep) {
public boolean dumpLocked(@NonNull PrintWriter pw, @Nullable String dumpPackage,
@NonNull String queueName, @NonNull SimpleDateFormat sdf,
boolean dumpAll, boolean needSep) {
pw.println(" Pending broadcasts:");
if (mPendingBroadcasts.isEmpty()) {
pw.println(" <empty>");
} else {
for (int idx = mPendingBroadcasts.size() - 1; idx >= 0; --idx) {
final BroadcastRecord r = mPendingBroadcasts.get(idx);
pw.print(" Broadcast #"); pw.print(idx); pw.println(":");
r.dump(pw, " ", sdf);
}
}
int i;
boolean printed = false;

View File

@@ -1145,8 +1145,11 @@ class BroadcastProcessQueue {
pw.print(" because ");
pw.print(reasonToString(mRunnableAtReason));
pw.println();
pw.print("mProcessCached="); pw.println(mProcessCached);
pw.increaseIndent();
dumpProcessState(pw);
dumpBroadcastCounts(pw);
if (mActive != null) {
dumpRecord("ACTIVE", now, pw, mActive, mActiveIndex);
}
@@ -1166,6 +1169,49 @@ class BroadcastProcessQueue {
pw.println();
}
@NeverCompile
private void dumpProcessState(@NonNull IndentingPrintWriter pw) {
final StringBuilder sb = new StringBuilder();
if (mProcessCached) {
sb.append("CACHED");
}
if (mProcessInstrumented) {
if (sb.length() > 0) sb.append("|");
sb.append("INSTR");
}
if (mProcessPersistent) {
if (sb.length() > 0) sb.append("|");
sb.append("PER");
}
if (sb.length() > 0) {
pw.print("state:"); pw.println(sb);
}
if (runningOomAdjusted) {
pw.print("runningOomAdjusted:"); pw.println(runningOomAdjusted);
}
}
@NeverCompile
private void dumpBroadcastCounts(@NonNull IndentingPrintWriter pw) {
pw.print("e:"); pw.print(mCountEnqueued);
pw.print(" d:"); pw.print(mCountDeferred);
pw.print(" f:"); pw.print(mCountForeground);
pw.print(" fd:"); pw.print(mCountForegroundDeferred);
pw.print(" o:"); pw.print(mCountOrdered);
pw.print(" a:"); pw.print(mCountAlarm);
pw.print(" p:"); pw.print(mCountPrioritized);
pw.print(" pd:"); pw.print(mCountPrioritizedDeferred);
pw.print(" int:"); pw.print(mCountInteractive);
pw.print(" rt:"); pw.print(mCountResultTo);
pw.print(" ins:"); pw.print(mCountInstrumented);
pw.print(" m:"); pw.print(mCountManifest);
pw.print(" csi:"); pw.print(mActiveCountSinceIdle);
pw.print(" ccu:"); pw.print(mActiveCountConsecutiveUrgent);
pw.print(" ccn:"); pw.print(mActiveCountConsecutiveNormal);
pw.println();
}
@NeverCompile
private void dumpRecord(@Nullable String flavor, @UptimeMillisLong long now,
@NonNull IndentingPrintWriter pw, @NonNull BroadcastRecord record, int recordIndex) {

View File

@@ -90,7 +90,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -614,6 +613,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
r.enqueueTime = SystemClock.uptimeMillis();
r.enqueueRealTime = SystemClock.elapsedRealtime();
r.enqueueClockTime = System.currentTimeMillis();
mHistory.onBroadcastEnqueuedLocked(r);
ArraySet<BroadcastRecord> replacedBroadcasts = mReplacedBroadcastsCache.getAndSet(null);
if (replacedBroadcasts == null) {
@@ -837,8 +837,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
if (app != null && app.isInFullBackup()) {
return "isInFullBackup";
}
if (mSkipPolicy.shouldSkip(r, receiver)) {
return "mSkipPolicy";
final String skipReason = mSkipPolicy.shouldSkipMessage(r, receiver);
if (skipReason != null) {
return skipReason;
}
final Intent receiverIntent = r.getReceiverIntent(receiver);
if (receiverIntent == null) {
@@ -1108,7 +1109,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
*/
private void setDeliveryState(@Nullable BroadcastProcessQueue queue,
@Nullable ProcessRecord app, @NonNull BroadcastRecord r, int index,
@NonNull Object receiver, @DeliveryState int newDeliveryState, String reason) {
@NonNull Object receiver, @DeliveryState int newDeliveryState,
@NonNull String reason) {
final int cookie = traceBegin("setDeliveryState");
final int oldDeliveryState = getDeliveryState(r, index);
boolean checkFinished = false;
@@ -1116,7 +1118,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// Only apply state when we haven't already reached a terminal state;
// this is how we ignore racing timeout messages
if (!isDeliveryStateTerminal(oldDeliveryState)) {
r.setDeliveryState(index, newDeliveryState);
r.setDeliveryState(index, newDeliveryState, reason);
if (oldDeliveryState == BroadcastRecord.DELIVERY_DEFERRED) {
r.deferredCount--;
} else if (newDeliveryState == BroadcastRecord.DELIVERY_DEFERRED) {
@@ -1667,7 +1669,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
mService.notifyBroadcastFinishedLocked(r);
r.finishTime = SystemClock.uptimeMillis();
r.nextReceiver = r.receivers.size();
mHistory.addBroadcastToHistoryLocked(r);
mHistory.onBroadcastFinishedLocked(r);
BroadcastQueueImpl.logBootCompletedBroadcastCompletionLatencyIfPossible(r);
@@ -1841,8 +1843,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
if (dumpConstants) {
mConstants.dump(ipw);
}
if (dumpHistory) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
needSep = mHistory.dumpLocked(ipw, dumpPackage, mQueueName, sdf, dumpAll, needSep);
}
return needSep;

View File

@@ -99,6 +99,7 @@ final class BroadcastRecord extends Binder {
final @Nullable BroadcastOptions options; // BroadcastOptions supplied by caller
final @NonNull List<Object> receivers; // contains BroadcastFilter and ResolveInfo
final @DeliveryState int[] delivery; // delivery state of each receiver
final @NonNull String[] deliveryReasons; // reasons for delivery state of each receiver
final boolean[] deferredUntilActive; // whether each receiver is infinitely deferred
final int[] blockedUntilTerminalCount; // blocked until count of each receiver
@Nullable ProcessRecord resultToApp; // who receives final result if non-null
@@ -298,7 +299,7 @@ final class BroadcastRecord extends Binder {
pw.print(" initialSticky="); pw.println(initialSticky);
}
if (nextReceiver != 0) {
pw.print(prefix); pw.print("nextReceiver="); pw.print(nextReceiver);
pw.print(prefix); pw.print("nextReceiver="); pw.println(nextReceiver);
}
if (curFilter != null) {
pw.print(prefix); pw.print("curFilter="); pw.println(curFilter);
@@ -328,6 +329,7 @@ final class BroadcastRecord extends Binder {
}
pw.print(prefix); pw.print("state="); pw.print(state); pw.println(stateStr);
}
pw.print(prefix); pw.print("terminalCount="); pw.println(terminalCount);
final int N = receivers != null ? receivers.size() : 0;
String p2 = prefix + " ";
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
@@ -346,6 +348,7 @@ final class BroadcastRecord extends Binder {
TimeUtils.formatDuration(terminalTime[i] - scheduledTime[i], pw);
pw.print(' ');
}
pw.print("("); pw.print(blockedUntilTerminalCount[i]); pw.print(") ");
pw.print("#"); pw.print(i); pw.print(": ");
if (o instanceof BroadcastFilter) {
pw.println(o);
@@ -356,6 +359,9 @@ final class BroadcastRecord extends Binder {
} else {
pw.println(o);
}
if (deliveryReasons[i] != null) {
pw.print(p2); pw.print("reason: "); pw.println(deliveryReasons[i]);
}
}
}
@@ -393,6 +399,7 @@ final class BroadcastRecord extends Binder {
options = _options;
receivers = (_receivers != null) ? _receivers : EMPTY_RECEIVERS;
delivery = new int[_receivers != null ? _receivers.size() : 0];
deliveryReasons = new String[delivery.length];
deferUntilActive = options != null ? options.isDeferUntilActive() : false;
deferredUntilActive = new boolean[deferUntilActive ? delivery.length : 0];
blockedUntilTerminalCount = calculateBlockedUntilTerminalCount(receivers, _serialized);
@@ -448,6 +455,7 @@ final class BroadcastRecord extends Binder {
options = from.options;
receivers = from.receivers;
delivery = from.delivery;
deliveryReasons = from.deliveryReasons;
deferUntilActive = from.deferUntilActive;
deferredUntilActive = from.deferredUntilActive;
blockedUntilTerminalCount = from.blockedUntilTerminalCount;
@@ -609,8 +617,10 @@ final class BroadcastRecord extends Binder {
* Update the delivery state of the given {@link #receivers} index.
* Automatically updates any time measurements related to state changes.
*/
void setDeliveryState(int index, @DeliveryState int deliveryState) {
void setDeliveryState(int index, @DeliveryState int deliveryState,
@NonNull String reason) {
delivery[index] = deliveryState;
deliveryReasons[index] = reason;
if (deferUntilActive) deferredUntilActive[index] = false;
switch (deliveryState) {
case DELIVERY_DELIVERED:
@@ -977,7 +987,8 @@ final class BroadcastRecord extends Binder {
if (label == null) {
label = intent.toString();
}
mCachedToShortString = label + "/u" + userId;
mCachedToShortString = Integer.toHexString(System.identityHashCode(this))
+ ":" + label + "/u" + userId;
}
return mCachedToShortString;
}

View File

@@ -558,7 +558,7 @@ public final class BroadcastQueueModernImplTest {
// To maximize test coverage, dump current state; we're not worried
// about the actual output, just that we don't crash
queue.getActive().setDeliveryState(0, BroadcastRecord.DELIVERY_SCHEDULED);
queue.getActive().setDeliveryState(0, BroadcastRecord.DELIVERY_SCHEDULED, "Test-driven");
queue.dumpLocked(SystemClock.uptimeMillis(),
new IndentingPrintWriter(new PrintWriter(new ByteArrayOutputStream())));