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

Commit 0060bd42 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

BroadcastQueue: limit runnable to avoid starvation.

When a process has a large number of pending broadcasts, they could
end up starving other runnable processes.  This change retires a
running queue if we've made reasonable progress and someone else is
waiting.

Bug: 245771249
Test: atest FrameworksMockingServicesTests:BroadcastQueueTest
Change-Id: Ie60625d8fba577ccf1cb8d1cee212fffabb68ef7
parent 527e10cc
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -95,6 +95,15 @@ class BroadcastProcessQueue {
     */
    private int mActiveIndex;

    /**
     * Count of {@link #mActive} broadcasts that have been dispatched since this
     * queue was last idle.
     */
    private int mActiveCountSinceIdle;

    /**
     * Count of {@link #mPending} broadcasts of these various flavors.
     */
    private int mCountForeground;
    private int mCountOrdered;
    private int mCountAlarm;
@@ -170,6 +179,14 @@ class BroadcastProcessQueue {
        }
    }

    /**
     * Count of {@link #mActive} broadcasts that have been dispatched since this
     * queue was last idle.
     */
    public int getActiveCountSinceIdle() {
        return mActiveCountSinceIdle;
    }

    /**
     * Set the currently active broadcast to the next pending broadcast.
     */
@@ -179,6 +196,7 @@ class BroadcastProcessQueue {
        final SomeArgs next = mPending.removeFirst();
        mActive = (BroadcastRecord) next.arg1;
        mActiveIndex = next.argi1;
        mActiveCountSinceIdle++;
        next.recycle();
        if (mActive.isForeground()) {
            mCountForeground--;
@@ -198,6 +216,7 @@ class BroadcastProcessQueue {
    public void makeActiveIdle() {
        mActive = null;
        mActiveIndex = 0;
        mActiveCountSinceIdle = 0;
    }

    public void setActiveDeliveryState(int deliveryState) {
+14 −2
Original line number Diff line number Diff line
@@ -101,6 +101,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
    // TODO: shift hard-coded defaults to BroadcastConstants
    private static final int MAX_RUNNING_PROCESS_QUEUES = 4;

    /**
     * Maximum number of active broadcasts to dispatch to a "running" process
     * queue before we retire them back to being "runnable" to give other
     * processes a chance to run.
     */
    // TODO: shift hard-coded defaults to BroadcastConstants
    private static final int MAX_RUNNING_ACTIVE_BROADCASTS = 16;

    /**
     * Map from UID to per-process broadcast queues. If a UID hosts more than
     * one process, each additional process is stored as a linked list using
@@ -475,10 +483,14 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        queue.setActiveDeliveryState(deliveryState);

        // TODO: cancel any outstanding ANR timeout
        // TODO: limit number of broadcasts in a row to avoid starvation
        // TODO: if we're the last receiver of this broadcast, record to history

        if (queue.isRunnable() && queue.isProcessWarm()) {
        // 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() > MAX_RUNNING_ACTIVE_BROADCASTS);

        if (queue.isRunnable() && queue.isProcessWarm() && !shouldRetire) {
            // We're on a roll; move onto the next broadcast for this process
            queue.makeActiveNextPending();
            scheduleReceiverWarmLocked(queue);