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

Commit 0bec75ce authored by Sudheer Shanka's avatar Sudheer Shanka Committed by Android (Google) Code Review
Browse files

Merge "Fix user cleanup in modern broadcast queue."

parents 26af2c72 5cb9f358
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1341,7 +1341,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            @NonNull BroadcastPredicate broadcastPredicate,
            @NonNull BroadcastConsumer broadcastConsumer, boolean andRemove) {
        boolean didSomething = false;
        for (int i = 0; i < mProcessQueues.size(); i++) {
        for (int i = mProcessQueues.size() - 1; i >= 0; i--) {
            BroadcastProcessQueue leaf = mProcessQueues.valueAt(i);
            while (leaf != null) {
                if (queuePredicate.test(leaf)) {
@@ -1363,7 +1363,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
    private void forEachMatchingQueue(
            @NonNull Predicate<BroadcastProcessQueue> queuePredicate,
            @NonNull Consumer<BroadcastProcessQueue> queueConsumer) {
        for (int i = 0; i < mProcessQueues.size(); i++) {
        for (int i = mProcessQueues.size() - 1; i >= 0; i--) {
            BroadcastProcessQueue leaf = mProcessQueues.valueAt(i);
            while (leaf != null) {
                if (queuePredicate.test(leaf)) {
+37 −0
Original line number Diff line number Diff line
@@ -25,7 +25,10 @@ import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_PRIORI
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_RESULT_TO;
import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList;
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
import static com.android.server.am.BroadcastQueueTest.CLASS_BLUE;
import static com.android.server.am.BroadcastQueueTest.CLASS_GREEN;
import static com.android.server.am.BroadcastQueueTest.CLASS_RED;
import static com.android.server.am.BroadcastQueueTest.CLASS_YELLOW;
import static com.android.server.am.BroadcastQueueTest.PACKAGE_BLUE;
import static com.android.server.am.BroadcastQueueTest.PACKAGE_GREEN;
import static com.android.server.am.BroadcastQueueTest.PACKAGE_RED;
@@ -981,6 +984,40 @@ public class BroadcastQueueModernImplTest {
        assertTrue(queue.isEmpty());
    }

    @Test
    public void testCleanupDisabledPackageReceiversLocked() {
        final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT);
        final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);

        final BroadcastRecord record1 = makeBroadcastRecord(userPresent, List.of(
                makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
                makeManifestReceiver(PACKAGE_RED, CLASS_BLUE),
                makeManifestReceiver(PACKAGE_YELLOW, CLASS_RED),
                makeManifestReceiver(PACKAGE_BLUE, CLASS_GREEN)
        ));
        final BroadcastRecord record2 = makeBroadcastRecord(timeTick, List.of(
                makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
                makeManifestReceiver(PACKAGE_RED, CLASS_RED),
                makeManifestReceiver(PACKAGE_YELLOW, CLASS_YELLOW)
        ));

        // Halt all processing so that we get a consistent view
        mHandlerThread.getLooper().getQueue().postSyncBarrier();
        mImpl.enqueueBroadcastLocked(record1);
        mImpl.enqueueBroadcastLocked(record2);

        mImpl.cleanupDisabledPackageReceiversLocked(null, null, UserHandle.USER_SYSTEM);

        // Verify that all receivers have been marked as "skipped".
        for (BroadcastRecord record : new BroadcastRecord[] {record1, record2}) {
            for (int i = 0; i < record.receivers.size(); ++i) {
                final String errMsg = "Unexpected delivery state for record:" + record
                        + "; receiver=" + record.receivers.get(i);
                assertEquals(errMsg, BroadcastRecord.DELIVERY_SKIPPED, record.getDeliveryState(i));
            }
        }
    }

    private Intent createPackageChangedIntent(int uid, List<String> componentNameList) {
        final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
        packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);
+55 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -805,14 +806,27 @@ public class BroadcastQueueTest {
                    null, null, null, null, null, null, userId, null));
    }

    private void verifyScheduleReceiver(VerificationMode mode, ProcessRecord app,
            int userId) throws Exception {
        verify(app.getThread(), mode).scheduleReceiverList(
                manifestReceiver(null,
                        null, null, null, null, null, null, userId, null));
    }

    private void verifyScheduleRegisteredReceiver(ProcessRecord app,
            Intent intent)
            throws Exception {
            Intent intent) throws Exception {
        verify(app.getThread()).scheduleReceiverList(
            registeredReceiver(null, filterEqualsIgnoringComponent(intent),
                    null, null, null, null, null, UserHandle.USER_SYSTEM, null));
    }

    private void verifyScheduleRegisteredReceiver(VerificationMode mode, ProcessRecord app,
            int userId) throws Exception {
        verify(app.getThread(), mode).scheduleReceiverList(
                registeredReceiver(null, null,
                        null, null, null, null, null, userId, null));
    }

    static final int USER_GUEST = 11;

    static final String PACKAGE_ANDROID = "android";
@@ -1222,6 +1236,45 @@ public class BroadcastQueueTest {
                new ComponentName(PACKAGE_GREEN, CLASS_BLUE));
    }

    @Test
    public void testCleanup_userRemoved() throws Exception {
        final ProcessRecord callerApp = makeActiveProcessRecord(
                PACKAGE_RED, PACKAGE_RED, ProcessBehavior.NORMAL,
                USER_GUEST);

        final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        final Intent timeZone = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
        try (SyncBarrier b = new SyncBarrier()) {
            enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, USER_GUEST, new ArrayList<>(
                    List.of(makeRegisteredReceiver(callerApp),
                            makeManifestReceiver(PACKAGE_GREEN, CLASS_RED, USER_GUEST),
                            makeManifestReceiver(PACKAGE_BLUE, CLASS_GREEN, USER_GUEST),
                            makeManifestReceiver(PACKAGE_YELLOW, CLASS_BLUE, USER_GUEST)))));
            enqueueBroadcast(makeBroadcastRecord(timeZone, callerApp, USER_GUEST, new ArrayList<>(
                    List.of(makeRegisteredReceiver(callerApp),
                            makeManifestReceiver(PACKAGE_GREEN, CLASS_RED, USER_GUEST),
                            makeManifestReceiver(PACKAGE_BLUE, CLASS_GREEN, USER_GUEST),
                            makeManifestReceiver(PACKAGE_YELLOW, CLASS_BLUE, USER_GUEST)))));

            synchronized (mAms) {
                mQueue.cleanupDisabledPackageReceiversLocked(null, null, USER_GUEST);
            }
        }

        waitForIdle();
        // Legacy stack does not remove registered receivers as part of
        // cleanUpDisabledPackageReceiversLocked() call, so verify this only on modern queue.
        if (mImpl == Impl.MODERN) {
            verifyScheduleReceiver(never(), callerApp, USER_GUEST);
            verifyScheduleRegisteredReceiver(never(), callerApp, USER_GUEST);
        }
        for (String pkg : new String[] {
                PACKAGE_GREEN, PACKAGE_BLUE, PACKAGE_YELLOW
        }) {
            assertNull(mAms.getProcessRecordLocked(pkg, getUidForPackage(pkg, USER_GUEST)));
        }
    }

    /**
     * Verify that killing a running process skips registered receivers.
     */