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

Commit 05d59548 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Expand checkHealth() to look for more stalls.

The initial health check was only looking for processes stuck in the
"blocked" state for more than 10 minutes; this change expands that
to look for *any* broadcasts that have been waiting more than 10
minutes to be dispatched.

Note that the first broadcast matching this state will trigger the
wtf() event, and from that point onward we stop doing health checks
until the next reboot to avoid spamming dropbox.

Bug: 272685068
Test: treehugger
Change-Id: I6d84ccfecf72131195ed96498e2538e790e2bbd2
parent a5991fc1
Loading
Loading
Loading
Loading
+22 −14
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UptimeMillisLong;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.SystemClock;
import android.os.Trace;
@@ -42,7 +43,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
@@ -125,12 +125,6 @@ class BroadcastProcessQueue {
     */
    private final ArrayDeque<SomeArgs> mPendingOffload = new ArrayDeque<>(4);

    /**
     * List of all queues holding broadcasts that are waiting to be dispatched.
     */
    private final List<ArrayDeque<SomeArgs>> mPendingQueues = List.of(
            mPendingUrgent, mPending, mPendingOffload);

    /**
     * Broadcast actively being dispatched to this process.
     */
@@ -1043,16 +1037,30 @@ class BroadcastProcessQueue {
     * that we're not wedged.
     */
    public void checkHealthLocked() {
        if (mRunnableAtReason == REASON_BLOCKED) {
            final SomeArgs next = peekNextBroadcast();
            Objects.requireNonNull(next, "peekNextBroadcast");
        checkHealthLocked(mPending);
        checkHealthLocked(mPendingUrgent);
        checkHealthLocked(mPendingOffload);
    }

            // If blocked more than 10 minutes, we're likely wedged
            final BroadcastRecord r = (BroadcastRecord) next.arg1;
            final long waitingTime = SystemClock.uptimeMillis() - r.enqueueTime;
    private void checkHealthLocked(@NonNull ArrayDeque<SomeArgs> queue) {
        if (queue.isEmpty()) return;

        final Iterator<SomeArgs> it = queue.descendingIterator();
        while (it.hasNext()) {
            final SomeArgs args = it.next();
            final BroadcastRecord record = (BroadcastRecord) args.arg1;
            final int recordIndex = args.argi1;

            if (BroadcastRecord.isDeliveryStateTerminal(record.getDeliveryState(recordIndex))
                    || record.isDeferUntilActive()) {
                continue;
            } else {
                // If waiting more than 10 minutes, we're likely wedged
                final long waitingTime = SystemClock.uptimeMillis() - record.enqueueTime;
                checkState(waitingTime < (10 * DateUtils.MINUTE_IN_MILLIS), "waitingTime");
            }
        }
    }

    /**
     * Insert the given queue into a sorted linked list of "runnable" queues.