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

Commit 1b72ca3a authored by Christopher Tate's avatar Christopher Tate
Browse files

Exempt PRE_BOOT_COMPLETED from timeout & deferral policy

PRE_BOOT_COMPLETED broadcast receivers are expected to possibly take a
long time to peform their work; they're doing significant work in
standing up the system itself.  Do not time out the broadcasts
themselves, and do not apply future broadcast deferral policy on the
basis of how long its receivers take to finish running.

Change-Id: I26469576d50400f3266cf6a5b09aa645fa83213a
Fixes: 117567005
Test: manual
parent 6e6b31ad
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -14090,7 +14090,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                    BroadcastQueue queue = broadcastQueueForIntent(intent);
                    BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                            null, -1, -1, false, null, null, OP_NONE, null, receivers,
                            null, 0, null, null, false, true, true, -1, false);
                            null, 0, null, null, false, true, true, -1, false,
                            false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
                    queue.enqueueParallelBroadcastLocked(r);
                    queue.scheduleBroadcastsLocked();
                }
@@ -14475,6 +14476,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        boolean timeoutExempt = false;
        if (action != null) {
            if (getBackgroundLaunchBroadcasts().contains(action)) {
                if (DEBUG_BACKGROUND_CHECK) {
@@ -14700,6 +14703,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                    Log.w(TAG, "Broadcast " + action
                            + " no longer supported. It will not be delivered.");
                    return ActivityManager.BROADCAST_SUCCESS;
                case Intent.ACTION_PRE_BOOT_COMPLETED:
                    timeoutExempt = true;
                    break;
            }
            if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
@@ -14842,7 +14848,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts);
                    allowBackgroundActivityStarts, timeoutExempt);
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
            final boolean replaced = replacePending
                    && (queue.replaceParallelBroadcastLocked(r) != null);
@@ -14939,7 +14945,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId,
                    allowBackgroundActivityStarts);
                    allowBackgroundActivityStarts, timeoutExempt);
            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
+29 −15
Original line number Diff line number Diff line
@@ -461,6 +461,7 @@ public final class BroadcastQueue {

        // if this receiver was slow, impose deferral policy on the app.  This will kick in
        // when processNextBroadcastLocked() next finds this uid as a receiver identity.
        if (!r.timeoutExempt) {
            if (mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) {
                if (DEBUG_BROADCAST_DEFERRAL) {
                    Slog.i(TAG, "Broadcast receiver was slow: " + receiver + " br=" + r);
@@ -471,6 +472,12 @@ public final class BroadcastQueue {
                    Slog.d(TAG, "finish receiver curApp is null? " + r);
                }
            }
        } else {
            if (DEBUG_BROADCAST_DEFERRAL) {
                Slog.i(TAG_BROADCAST, "Finished broadcast " + r.intent.getAction()
                        + " is exempt from deferral policy");
            }
        }

        r.receiver = null;
        r.intent.setComponent(null);
@@ -1008,12 +1015,11 @@ public final class BroadcastQueue {
            // detection, we catch "hung" broadcasts here, discard them,
            // and continue to make progress.
            //
            // This is only done if the system is ready so that PRE_BOOT_COMPLETED
            // receivers don't get executed with timeouts. They're intended for
            // one time heavy lifting after system upgrades and can take
            // significant amounts of time.
            // This is only done if the system is ready so that early-stage receivers
            // don't get executed with timeouts; and of course other timeout-
            // exempt broadcasts are ignored.
            int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
            if (mService.mProcessesReady && r.dispatchTime > 0) {
            if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
                if ((numReceivers > 0) &&
                        (now > r.dispatchTime + (2 * mConstants.TIMEOUT * numReceivers))) {
                    Slog.w(TAG, "Hung broadcast ["
@@ -1619,9 +1625,17 @@ public final class BroadcastQueue {
        BroadcastRecord r = mDispatcher.getActiveBroadcastLocked();
        if (fromMsg) {
            if (!mService.mProcessesReady) {
                // Only process broadcast timeouts if the system is ready. That way
                // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
                // to do heavy lifting for system up.
                // Only process broadcast timeouts if the system is ready; some early
                // broadcasts do heavy work setting up system facilities
                return;
            }

            // If the broadcast is generally exempt from timeout tracking, we're done
            if (r.timeoutExempt) {
                if (DEBUG_BROADCAST) {
                    Slog.i(TAG_BROADCAST, "Broadcast timeout but it's exempt: "
                            + r.intent.getAction());
                }
                return;
            }

+5 −2
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ final class BroadcastRecord extends Binder {
    long dispatchClockTime; // the clock time the dispatch started
    long receiverTime;      // when current receiver started for timeouts.
    long finishTime;        // when we finished the broadcast.
    boolean timeoutExempt;  // true if this broadcast is not subject to receiver timeouts
    int resultCode;         // current result code value.
    String resultData;      // current result data value.
    Bundle resultExtras;    // current result extra data values.
@@ -236,7 +237,7 @@ final class BroadcastRecord extends Binder {
            String[] _requiredPermissions, int _appOp, BroadcastOptions _options, List _receivers,
            IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras,
            boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId,
            boolean _allowBackgroundActivityStarts) {
            boolean _allowBackgroundActivityStarts, boolean _timeoutExempt) {
        if (_intent == null) {
            throw new NullPointerException("Can't construct with a null intent");
        }
@@ -266,6 +267,7 @@ final class BroadcastRecord extends Binder {
        nextReceiver = 0;
        state = IDLE;
        allowBackgroundActivityStarts = _allowBackgroundActivityStarts;
        timeoutExempt = _timeoutExempt;
    }

    /**
@@ -310,6 +312,7 @@ final class BroadcastRecord extends Binder {
        manifestSkipCount = from.manifestSkipCount;
        queue = from.queue;
        allowBackgroundActivityStarts = from.allowBackgroundActivityStarts;
        timeoutExempt = from.timeoutExempt;
    }

    /**
@@ -345,7 +348,7 @@ final class BroadcastRecord extends Binder {
                callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                requiredPermissions, appOp, options, splitReceivers, resultTo, resultCode,
                resultData, resultExtras, ordered, sticky, initialSticky, userId,
                allowBackgroundActivityStarts);
                allowBackgroundActivityStarts, timeoutExempt);

        return split;
    }
+2 −1
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@ public class BroadcastRecordTest {
                false /* sticky */,
                false /* initialSticky */,
                userId,
                false /* allowBackgroundActivityStarts */);
                false, /* allowBackgroundActivityStarts */
                false /* timeoutExempt */ );
    }
}