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

Commit 32774bad authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

Merge "Merge "Retry manifest bcast delivery if the receiver dies as part of...

Merge "Merge "Retry manifest bcast delivery if the receiver dies as part of unfreezing." into udc-dev am: 0bd2ce4e am: fd55eff9"
parents ec2ba88f 7fbd0385
Loading
Loading
Loading
Loading
+26 −8
Original line number Original line Diff line number Diff line
@@ -458,7 +458,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            updateWarmProcess(queue);
            updateWarmProcess(queue);


            final boolean processWarm = queue.isProcessWarm();
            final boolean processWarm = queue.isProcessWarm();
            if (!processWarm) {
            if (processWarm) {
                mService.mOomAdjuster.unfreezeTemporarily(queue.app,
                        CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);
                // The process could be killed as part of unfreezing. So, check again if it
                // is still warm.
                if (!queue.isProcessWarm()) {
                    queue = nextQueue;
                    enqueueUpdateRunningList();
                    continue;
                }
            } else {
                // We only offer to run one cold-start at a time to preserve
                // We only offer to run one cold-start at a time to preserve
                // system resources; below we either claim that single slot or
                // system resources; below we either claim that single slot or
                // skip to look for another warm process
                // skip to look for another warm process
@@ -530,6 +540,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        mRunningColdStart.reEnqueueActiveBroadcast();
        mRunningColdStart.reEnqueueActiveBroadcast();
        demoteFromRunningLocked(mRunningColdStart);
        demoteFromRunningLocked(mRunningColdStart);
        clearRunningColdStart();
        clearRunningColdStart();
        enqueueUpdateRunningList();
    }
    }


    private void checkPendingColdStartValidity() {
    private void checkPendingColdStartValidity() {
@@ -564,6 +575,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
    @Override
    @Override
    public boolean onApplicationAttachedLocked(@NonNull ProcessRecord app)
    public boolean onApplicationAttachedLocked(@NonNull ProcessRecord app)
            throws BroadcastDeliveryFailedException {
            throws BroadcastDeliveryFailedException {
        if (DEBUG_BROADCAST) {
            logv("Process " + app + " is attached");
        }
        // Process records can be recycled, so always start by looking up the
        // Process records can be recycled, so always start by looking up the
        // relevant per-process queue
        // relevant per-process queue
        final BroadcastProcessQueue queue = getProcessQueue(app);
        final BroadcastProcessQueue queue = getProcessQueue(app);
@@ -613,18 +627,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {


    @Override
    @Override
    public void onApplicationCleanupLocked(@NonNull ProcessRecord app) {
    public void onApplicationCleanupLocked(@NonNull ProcessRecord app) {
        // Process records can be recycled, so always start by looking up the
        if (DEBUG_BROADCAST) {
        // relevant per-process queue
            logv("Process " + app + " is cleaned up");
        final BroadcastProcessQueue queue = getProcessQueue(app);
        if (queue != null) {
            setQueueProcess(queue, null);
        }
        }


        if ((mRunningColdStart != null) && (mRunningColdStart == queue)) {
        // This cleanup callback could be for an old process and not for the one we are waiting
        // on, so explicitly check if this for the same ProcessRecord that a queue has.
        final BroadcastProcessQueue queue = getProcessQueue(app);
        if ((mRunningColdStart != null) && (mRunningColdStart == queue)
                && mRunningColdStart.app == app) {
            clearRunningColdStart();
            clearRunningColdStart();
        }
        }


        if (queue != null) {
        if (queue != null && queue.app == app) {
            setQueueProcess(queue, null);

            // If queue was running a broadcast, fail it
            // If queue was running a broadcast, fail it
            if (queue.isActive()) {
            if (queue.isActive()) {
                finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
                finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
@@ -1073,6 +1090,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
                // If we were trying to deliver a manifest broadcast, throw the error as we need
                // If we were trying to deliver a manifest broadcast, throw the error as we need
                // to try redelivering the broadcast to this receiver.
                // to try redelivering the broadcast to this receiver.
                if (receiver instanceof ResolveInfo) {
                if (receiver instanceof ResolveInfo) {
                    mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);
                    throw new BroadcastDeliveryFailedException(e);
                    throw new BroadcastDeliveryFailedException(e);
                }
                }
                finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
                finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
+48 −0
Original line number Original line Diff line number Diff line
@@ -261,6 +261,7 @@ public class BroadcastQueueTest {
                    // Create a different process that will be linked to the
                    // Create a different process that will be linked to the
                    // returned process via a predecessor/successor relationship
                    // returned process via a predecessor/successor relationship
                    mActiveProcesses.remove(res);
                    mActiveProcesses.remove(res);
                    res.setKilled(true);
                    deliverRes = makeActiveProcessRecord(ai, processName,
                    deliverRes = makeActiveProcessRecord(ai, processName,
                          ProcessBehavior.NORMAL, UnaryOperator.identity());
                          ProcessBehavior.NORMAL, UnaryOperator.identity());
                    deliverRes.mPredecessor = res;
                    deliverRes.mPredecessor = res;
@@ -1316,6 +1317,53 @@ public class BroadcastQueueTest {
        verifyScheduleReceiver(times(1), receiverOrangeApp, timezone);
        verifyScheduleReceiver(times(1), receiverOrangeApp, timezone);
    }
    }


    /**
     * Verify that a broadcast sent to a frozen app, which gets killed as part of unfreezing
     * process due to pending sync binder transactions, is delivered as expected.
     */
    @Test
    public void testDeliveryToFrozenApp_killedWhileUnfreeze() throws Exception {
        final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
        final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);

        // Mark the app as killed while unfreezing it, which can happen either when we directly
        // try to unfreeze it or when it is done as part of OomAdjust computation.
        doAnswer(invocation -> {
            final ProcessRecord app = invocation.getArgument(0);
            if (app == receiverBlueApp) {
                app.setKilled(true);
                mActiveProcesses.remove(app);
            }
            return null;
        }).when(mAms.mOomAdjuster).unfreezeTemporarily(eq(receiverBlueApp), anyInt());
        doAnswer(invocation -> {
            final ProcessRecord app = invocation.getArgument(0);
            if (app == receiverBlueApp) {
                app.setKilled(true);
                mActiveProcesses.remove(app);
            }
            return null;
        }).when(mAms).enqueueOomAdjTargetLocked(eq(receiverBlueApp));

        final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, List.of(
                makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE))));

        waitForIdle();
        final ProcessRecord restartedReceiverBlueApp = mAms.getProcessRecordLocked(PACKAGE_BLUE,
                getUidForPackage(PACKAGE_BLUE));
        assertNotEquals(receiverBlueApp, restartedReceiverBlueApp);
        // Legacy queue will always try delivering the broadcast even if the process
        // has been killed.
        if (mImpl == Impl.MODERN) {
            verifyScheduleReceiver(never(), receiverBlueApp, airplane);
        } else {
            verifyScheduleReceiver(times(1), receiverBlueApp, airplane);
        }
        // Verify that the new process receives the broadcast.
        verifyScheduleReceiver(times(1), restartedReceiverBlueApp, airplane);
    }

    @Test
    @Test
    public void testCold_Success() throws Exception {
    public void testCold_Success() throws Exception {
        doCold(ProcessStartBehavior.SUCCESS);
        doCold(ProcessStartBehavior.SUCCESS);