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

Commit 22a0c222 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge changes from topic "sep26"

* changes:
  BroadcastQueue: ignore dead registered receivers.
  BroadcastQueue: more exception details.
  BroadcastQueue: max pending, misc fixes.
  BroadcastQueue: tests for failing starts, dead.
parents 36d1a183 a4c77ee3
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -136,6 +136,14 @@ public class BroadcastConstants {
    public int MAX_RUNNING_ACTIVE_BROADCASTS = DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS;
    private static final int DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS = 16;

    /**
     * For {@link BroadcastQueueModernImpl}: Maximum number of pending
     * broadcasts to hold for a process before we ignore any delays that policy
     * might have applied to that process.
     */
    public int MAX_PENDING_BROADCASTS = DEFAULT_MAX_PENDING_BROADCASTS;
    private static final int DEFAULT_MAX_PENDING_BROADCASTS = 256;

    /**
     * For {@link BroadcastQueueModernImpl}: Default delay to apply to normal
     * broadcasts, giving a chance for debouncing of rapidly changing events.
@@ -217,6 +225,8 @@ public class BroadcastConstants {
                DEFAULT_MAX_RUNNING_PROCESS_QUEUES);
        MAX_RUNNING_ACTIVE_BROADCASTS = properties.getInt("bcast_max_running_active_broadcasts",
                DEFAULT_MAX_RUNNING_ACTIVE_BROADCASTS);
        MAX_PENDING_BROADCASTS = properties.getInt("bcast_max_pending_broadcasts",
                DEFAULT_MAX_PENDING_BROADCASTS);
        DELAY_NORMAL_MILLIS = properties.getLong("bcast_delay_normal_millis",
                DEFAULT_DELAY_NORMAL_MILLIS);
        DELAY_CACHED_MILLIS = properties.getLong("bcast_delay_cached_millis",
+20 −5
Original line number Diff line number Diff line
@@ -119,6 +119,9 @@ class BroadcastProcessQueue {

    private boolean mProcessCached;

    private String mCachedToString;
    private String mCachedToShortString;

    public BroadcastProcessQueue(@NonNull BroadcastConstants constants,
            @NonNull String processName, int uid) {
        this.constants = Objects.requireNonNull(constants);
@@ -327,7 +330,7 @@ class BroadcastProcessQueue {
    }

    public boolean isEmpty() {
        return (mActive != null) && mPending.isEmpty();
        return mPending.isEmpty();
    }

    public boolean isActive() {
@@ -385,6 +388,12 @@ class BroadcastProcessQueue {
            } else {
                mRunnableAt = runnableAt + constants.DELAY_NORMAL_MILLIS;
            }

            // If we have too many broadcasts pending, bypass any delays that
            // might have been applied above to aid draining
            if (mPending.size() >= constants.MAX_PENDING_BROADCASTS) {
                mRunnableAt = runnableAt;
            }
        } else {
            mRunnableAt = Long.MAX_VALUE;
        }
@@ -452,13 +461,19 @@ class BroadcastProcessQueue {

    @Override
    public String toString() {
        return "BroadcastProcessQueue{"
        if (mCachedToString == null) {
            mCachedToString = "BroadcastProcessQueue{"
                    + Integer.toHexString(System.identityHashCode(this))
                    + " " + processName + "/" + UserHandle.formatUid(uid) + "}";
        }
        return mCachedToString;
    }

    public String toShortString() {
        return processName + "/" + UserHandle.formatUid(uid);
        if (mCachedToShortString == null) {
            mCachedToShortString = processName + "/" + UserHandle.formatUid(uid);
        }
        return mCachedToShortString;
    }

    public void dumpLocked(@NonNull IndentingPrintWriter pw) {
+6 −3
Original line number Diff line number Diff line
@@ -114,6 +114,9 @@ public abstract class BroadcastQueue {
    /**
     * Signal from OS internals that the given process has just been actively
     * attached, and is ready to begin receiving broadcasts.
     *
     * @return if the queue performed an action on the given process, such as
     *         dispatching a pending broadcast
     */
    @GuardedBy("mService")
    public abstract boolean onApplicationAttachedLocked(@NonNull ProcessRecord app);
@@ -123,7 +126,7 @@ public abstract class BroadcastQueue {
     * an attempted start and attachment.
     */
    @GuardedBy("mService")
    public abstract boolean onApplicationTimeoutLocked(@NonNull ProcessRecord app);
    public abstract void onApplicationTimeoutLocked(@NonNull ProcessRecord app);

    /**
     * Signal from OS internals that the given process, which had already been
@@ -131,14 +134,14 @@ public abstract class BroadcastQueue {
     * not responding.
     */
    @GuardedBy("mService")
    public abstract boolean onApplicationProblemLocked(@NonNull ProcessRecord app);
    public abstract void onApplicationProblemLocked(@NonNull ProcessRecord app);

    /**
     * Signal from OS internals that the given process has been killed, and is
     * no longer actively running.
     */
    @GuardedBy("mService")
    public abstract boolean onApplicationCleanupLocked(@NonNull ProcessRecord app);
    public abstract void onApplicationCleanupLocked(@NonNull ProcessRecord app);

    /**
     * Signal from OS internals that the given package (or some subset of that
+20 −12
Original line number Diff line number Diff line
@@ -426,16 +426,16 @@ public class BroadcastQueueImpl extends BroadcastQueue {
        }
    }

    public boolean onApplicationTimeoutLocked(ProcessRecord app) {
        return skipCurrentOrPendingReceiverLocked(app);
    public void onApplicationTimeoutLocked(ProcessRecord app) {
        skipCurrentOrPendingReceiverLocked(app);
    }

    public boolean onApplicationProblemLocked(ProcessRecord app) {
        return skipCurrentOrPendingReceiverLocked(app);
    public void onApplicationProblemLocked(ProcessRecord app) {
        skipCurrentOrPendingReceiverLocked(app);
    }

    public boolean onApplicationCleanupLocked(ProcessRecord app) {
        return skipCurrentOrPendingReceiverLocked(app);
    public void onApplicationCleanupLocked(ProcessRecord app) {
        skipCurrentOrPendingReceiverLocked(app);
    }

    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
@@ -732,9 +732,10 @@ public class BroadcastQueueImpl extends BroadcastQueue {
                } catch (RemoteException ex) {
                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
                    synchronized (mService) {
                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                + " (pid " + app.getPid() + "). Crashing it.");
                        app.scheduleCrashLocked("can't deliver broadcast",
                        final String msg = "Failed to schedule " + intent + " to " + receiver
                                + " via " + app + ": " + ex;
                        Slog.w(TAG, msg);
                        app.scheduleCrashLocked(msg,
                                CannotDeliverBroadcastException.TYPE_ID, /* extras=*/ null);
                    }
                    throw ex;
@@ -814,7 +815,11 @@ public class BroadcastQueueImpl extends BroadcastQueue {
        try {
            if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                    "Delivering to " + filter + " : " + r);
            if (filter.receiverList.app != null && filter.receiverList.app.isInFullBackup()) {
            final boolean isInFullBackup = (filter.receiverList.app != null)
                    && filter.receiverList.app.isInFullBackup();
            final boolean isKilled = (filter.receiverList.app != null)
                    && filter.receiverList.app.isKilled();
            if (isInFullBackup || isKilled) {
                // Skip delivery if full backup in progress
                // If it's an ordered broadcast, we need to continue to the next receiver.
                if (ordered) {
@@ -1379,8 +1384,11 @@ public class BroadcastQueueImpl extends BroadcastQueue {
                processCurBroadcastLocked(r, app);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when sending broadcast to "
                      + r.curComponent, e);
                final String msg = "Failed to schedule " + r.intent + " to " + info
                        + " via " + app + ": " + e;
                Slog.w(TAG, msg);
                app.scheduleCrashLocked(msg,
                        CannotDeliverBroadcastException.TYPE_ID, /* extras=*/ null);
            } catch (RuntimeException e) {
                Slog.wtf(TAG, "Failed sending broadcast to "
                        + r.curComponent + " with " + r.intent, e);
+53 −24
Original line number Diff line number Diff line
@@ -290,7 +290,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        }

        // If app isn't running, and there's nothing in the queue, clean up
        if (queue.isEmpty() && !queue.isProcessWarm()) {
        if (queue.isEmpty() && !queue.isActive() && !queue.isProcessWarm()) {
            removeProcessQueue(queue.processName, queue.uid);
        }
    }
@@ -420,18 +420,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
    }

    @Override
    public boolean onApplicationTimeoutLocked(@NonNull ProcessRecord app) {
        return onApplicationCleanupLocked(app);
    public void onApplicationTimeoutLocked(@NonNull ProcessRecord app) {
        onApplicationCleanupLocked(app);
    }

    @Override
    public boolean onApplicationProblemLocked(@NonNull ProcessRecord app) {
        return onApplicationCleanupLocked(app);
    public void onApplicationProblemLocked(@NonNull ProcessRecord app) {
        onApplicationCleanupLocked(app);
    }

    @Override
    public boolean onApplicationCleanupLocked(@NonNull ProcessRecord app) {
        boolean didSomething = false;
    public void onApplicationCleanupLocked(@NonNull ProcessRecord app) {
        if ((mRunningColdStart != null) && (mRunningColdStart.app == app)) {
            // We've been waiting for this app to cold start, and it had
            // trouble; clear the slot and fail delivery below
@@ -439,7 +438,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {

            // We might be willing to kick off another cold start
            enqueueUpdateRunningList();
            didSomething = true;
        }

        final BroadcastProcessQueue queue = getProcessQueue(app);
@@ -449,16 +447,19 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            // If queue was running a broadcast, fail it
            if (queue.isActive()) {
                finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
                didSomething = true;
            }

            // Skip any pending registered receivers, since the old process
            // would never be around to receive them
            queue.removeMatchingBroadcasts((r, i) -> {
                return (r.receivers.get(i) instanceof BroadcastFilter);
            }, mBroadcastConsumerSkip);

            // If queue has nothing else pending, consider cleaning it
            if (queue.isEmpty()) {
                updateRunnableList(queue);
            }
        }

        return didSomething;
    }

    @Override
@@ -515,6 +516,13 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        final int index = queue.getActiveIndex();
        final Object receiver = r.receivers.get(index);

        // Ignore registered receivers from a previous PID
        if (receiver instanceof BroadcastFilter) {
            mRunningColdStart = null;
            finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
            return;
        }

        final ApplicationInfo info = ((ResolveInfo) receiver).activityInfo.applicationInfo;
        final ComponentName component = ((ResolveInfo) receiver).activityInfo.getComponentName();

@@ -536,6 +544,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        } else {
            mRunningColdStart = null;
            finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
            return;
        }
    }

@@ -563,7 +572,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            return;
        }

        // Consider additional cases where we'd want fo finish immediately
        // Consider additional cases where we'd want to finish immediately
        if (app.isInFullBackup()) {
            finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
            return;
@@ -578,7 +587,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            return;
        }

        if (!r.timeoutExempt) {
        // Ignore registered receivers from a previous PID
        if ((receiver instanceof BroadcastFilter)
                && ((BroadcastFilter) receiver).receiverList.pid != app.getPid()) {
            finishReceiverLocked(queue, BroadcastRecord.DELIVERY_SKIPPED);
            return;
        }

        if (mService.mProcessesReady && !r.timeoutExempt) {
            final long timeout = r.isForeground() ? mFgConstants.TIMEOUT : mBgConstants.TIMEOUT;
            mLocalHandler.sendMessageDelayed(
                    Message.obtain(mLocalHandler, MSG_DELIVERY_TIMEOUT, queue), timeout);
@@ -604,7 +620,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        }

        if (DEBUG_BROADCAST) logv("Scheduling " + r + " to warm " + app);
        setDeliveryState(queue, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED);
        setDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED);

        final IApplicationThread thread = app.getThread();
        if (thread != null) {
@@ -628,8 +644,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
                            app.mState.getReportedProcState());
                }
            } catch (RemoteException e) {
                final String msg = "Failed to schedule " + r + " to " + receiver
                        + " via " + app + ": " + e;
                Slog.w(TAG, msg);
                app.scheduleCrashLocked(msg, CannotDeliverBroadcastException.TYPE_ID, null);
                app.setKilled(true);
                finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
                app.scheduleCrashLocked(TAG, CannotDeliverBroadcastException.TYPE_ID, null);
            }
        } else {
            finishReceiverLocked(queue, BroadcastRecord.DELIVERY_FAILURE);
@@ -652,7 +672,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
                        r.resultCode, r.resultData, r.resultExtras, false, r.initialSticky,
                        r.userId, app.mState.getReportedProcState());
            } catch (RemoteException e) {
                app.scheduleCrashLocked(TAG, CannotDeliverBroadcastException.TYPE_ID, null);
                final String msg = "Failed to schedule result of " + r + " via " + app + ": " + e;
                Slog.w(TAG, msg);
                app.scheduleCrashLocked(msg, CannotDeliverBroadcastException.TYPE_ID, null);
            }
        }
    }
@@ -674,7 +696,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        // receivers as skipped
        if (r.ordered && r.resultAbort) {
            for (int i = r.finishedCount + 1; i < r.receivers.size(); i++) {
                setDeliveryState(null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED);
                setDeliveryState(null, null, r, i, r.receivers.get(i),
                        BroadcastRecord.DELIVERY_SKIPPED);
            }
        }

@@ -690,9 +713,10 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        final int index = queue.getActiveIndex();
        final Object receiver = r.receivers.get(index);

        setDeliveryState(queue, r, index, receiver, deliveryState);
        setDeliveryState(queue, app, r, index, receiver, deliveryState);

        if (deliveryState == BroadcastRecord.DELIVERY_TIMEOUT) {
            r.anrCount++;
            if (app != null && !app.isDebugging()) {
                mService.appNotResponding(queue.app, TimeoutRecord
                        .forBroadcastReceiver("Broadcast of " + r.toShortString()));
@@ -704,7 +728,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        // Even if we have more broadcasts, if we've made reasonable progress
        // and someone else is waiting, retire ourselves to avoid starvation
        final boolean shouldRetire = (mRunnableHead != null)
                && (queue.getActiveCountSinceIdle() > mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);
                && (queue.getActiveCountSinceIdle() >= mConstants.MAX_RUNNING_ACTIVE_BROADCASTS);

        if (queue.isRunnable() && queue.isProcessWarm() && !shouldRetire) {
            // We're on a roll; move onto the next broadcast for this process
@@ -733,17 +757,22 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
     * bookkeeping related to ordered broadcasts.
     */
    private void setDeliveryState(@Nullable BroadcastProcessQueue queue,
            @NonNull BroadcastRecord r, int index, @NonNull Object receiver,
            @DeliveryState int newDeliveryState) {
            @Nullable ProcessRecord app, @NonNull BroadcastRecord r, int index,
            @NonNull Object receiver, @DeliveryState int newDeliveryState) {
        final int oldDeliveryState = getDeliveryState(r, index);

        if (newDeliveryState != BroadcastRecord.DELIVERY_DELIVERED) {
            Slog.w(TAG, "Delivery state of " + r + " to " + receiver + " changed from "
            Slog.w(TAG, "Delivery state of " + r + " to " + receiver
                    + " via " + app + " changed from "
                    + deliveryStateToString(oldDeliveryState) + " to "
                    + deliveryStateToString(newDeliveryState));
        }

        // 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);
        }

        // Emit any relevant tracing results when we're changing the delivery
        // state as part of running from a queue
@@ -837,7 +866,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
     * of it matching a predicate.
     */
    private final BroadcastConsumer mBroadcastConsumerSkip = (r, i) -> {
        setDeliveryState(null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED);
        setDeliveryState(null, null, r, i, r.receivers.get(i), BroadcastRecord.DELIVERY_SKIPPED);
    };

    private boolean skipMatchingBroadcasts(
Loading