Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8c29399 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Fix missing broadcast ANR culprit information.

All TimeoutRecord have unfortunately been marked as "unknown culprit"
due to the Intent not having a ComponentName filled in.  We fix this
by passing the relevant package and class name through the record,
and we expand it to identify runtime registered receiver classes to
aid faster bug triage.

For now, we're abusing the class name transported via "receiverId"
to avoid the churn of adding yet another method argument late in the
release cycle.

Bug: 266169149
Test: atest InternalTests:TimeoutRecordTest
Test: atest FrameworksMockingServicesTests:BroadcastQueueTest
Test: atest FrameworksMockingServicesTests:BroadcastQueueModernImplTest
Test: atest FrameworksMockingServicesTests:BroadcastRecordTest
Change-Id: I67b6f672c24627b7281de3b218e1114ab8a48f74
parent 3f88c155
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -11356,12 +11356,15 @@ public class Intent implements Parcelable, Cloneable {
    @Override
    public String toString() {
        StringBuilder b = new StringBuilder(128);
        toString(b);
        return b.toString();
    }
    /** @hide */
    public void toString(@NonNull StringBuilder b) {
        b.append("Intent { ");
        toShortString(b, true, true, true, false);
        b.append(" }");
        return b.toString();
    }
    /** @hide */
+30 −5
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.internal.os;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Intent;
import android.os.SystemClock;

@@ -96,20 +98,43 @@ public class TimeoutRecord {
        return new TimeoutRecord(kind, reason, endUptimeMillis, /* endTakenBeforeLocks */ false);
    }

    /** Record for a broadcast receiver timeout. */
    @NonNull
    public static TimeoutRecord forBroadcastReceiver(@NonNull Intent intent,
            @Nullable String packageName, @Nullable String className) {
        final Intent logIntent;
        if (packageName != null) {
            if (className != null) {
                logIntent = new Intent(intent);
                logIntent.setComponent(new ComponentName(packageName, className));
            } else {
                logIntent = new Intent(intent);
                logIntent.setPackage(packageName);
            }
        } else {
            logIntent = intent;
        }
        return forBroadcastReceiver(logIntent);
    }

    /** Record for a broadcast receiver timeout. */
    @NonNull
    public static TimeoutRecord forBroadcastReceiver(@NonNull Intent intent) {
        String reason = "Broadcast of " + intent.toString();
        return TimeoutRecord.endingNow(TimeoutKind.BROADCAST_RECEIVER, reason);
        final StringBuilder reason = new StringBuilder("Broadcast of ");
        intent.toString(reason);
        return TimeoutRecord.endingNow(TimeoutKind.BROADCAST_RECEIVER, reason.toString());
    }

    /** Record for a broadcast receiver timeout. */
    @NonNull
    public static TimeoutRecord forBroadcastReceiver(@NonNull Intent intent,
            long timeoutDurationMs) {
        String reason = "Broadcast of " + intent.toString() + ", waited " + timeoutDurationMs
                + "ms";
        return TimeoutRecord.endingNow(TimeoutKind.BROADCAST_RECEIVER, reason);
        final StringBuilder reason = new StringBuilder("Broadcast of ");
        intent.toString(reason);
        reason.append(", waited ");
        reason.append(timeoutDurationMs);
        reason.append("ms");
        return TimeoutRecord.endingNow(TimeoutKind.BROADCAST_RECEIVER, reason.toString());
    }

    /** Record for an input dispatch no focused window timeout */
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.am;

import android.annotation.Nullable;
import android.content.IntentFilter;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -55,6 +56,16 @@ final class BroadcastFilter extends IntentFilter {
        exported = _exported;
    }

    public @Nullable String getReceiverClassName() {
        if (receiverId != null) {
            final int index = receiverId.lastIndexOf('@');
            if (index > 0) {
                return receiverId.substring(0, index);
            }
        }
        return null;
    }

    @NeverCompile
    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        long token = proto.start(fieldId);
+5 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList
import static com.android.server.am.BroadcastProcessQueue.reasonToString;
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
import static com.android.server.am.BroadcastRecord.deliveryStateToString;
import static com.android.server.am.BroadcastRecord.getReceiverClassName;
import static com.android.server.am.BroadcastRecord.getReceiverPackageName;
import static com.android.server.am.BroadcastRecord.getReceiverProcessName;
import static com.android.server.am.BroadcastRecord.getReceiverUid;
@@ -1040,7 +1041,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        if (deliveryState == BroadcastRecord.DELIVERY_TIMEOUT) {
            r.anrCount++;
            if (app != null && !app.isDebugging()) {
                mService.appNotResponding(queue.app, TimeoutRecord.forBroadcastReceiver(r.intent));
                final String packageName = getReceiverPackageName(receiver);
                final String className = getReceiverClassName(receiver);
                mService.appNotResponding(queue.app,
                        TimeoutRecord.forBroadcastReceiver(r.intent, packageName, className));
            }
        } else {
            mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);
+8 −0
Original line number Diff line number Diff line
@@ -832,6 +832,14 @@ final class BroadcastRecord extends Binder {
        }
    }

    static @Nullable String getReceiverClassName(@NonNull Object receiver) {
        if (receiver instanceof BroadcastFilter) {
            return ((BroadcastFilter) receiver).getReceiverClassName();
        } else /* if (receiver instanceof ResolveInfo) */ {
            return ((ResolveInfo) receiver).activityInfo.name;
        }
    }

    static int getReceiverPriority(@NonNull Object receiver) {
        if (receiver instanceof BroadcastFilter) {
            return ((BroadcastFilter) receiver).getPriority();
Loading