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

Commit bfb6b866 authored by Chris Li's avatar Chris Li
Browse files

Keep track of pending appeared Intent on empty TaskFragment

When the previous pending appeared Intent was cleanup because of launch
failure, we may reuse the same TaskFragment for the next activity start
if the TaskFragment info is not yet received.

In this case, add the new Intent as pending.

Bug: 440507153
Test: atest WMJetpackUnitTests:SplitControllerTest
Flag: EXEMPT small bug fix
Change-Id: Id7240204aad860a04354b841f0ad0c5c7955f813
parent 4d932b19
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -1121,8 +1121,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                }

                // Update the latest taskFragmentInfo and perform necessary clean-up
                container.setInfo(wct, taskFragmentInfo);
                // Clear pending first, so that the #setInfo will evaluate for clean-up
                container.clearPendingAppearedActivities();
                container.setInfo(wct, taskFragmentInfo);
                if (container.isEmpty()) {
                    mTransactionManager.getCurrentTransactionRecord()
                            .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE);
@@ -3206,6 +3207,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                        // If the TF is an existing one, this Intent will not be kept as a pending
                        // appeared Intent.
                        mCurrentPendingAppearedIntent = intent;
                    } else if (launchedInTaskFragment.isEmpty()
                            && launchedInTaskFragment.getPendingAppearedIntent() == null) {
                        // When this Intent is added to an empty TaskFragment, make sure to wait for
                        // this Intent launch before consider cleanup.
                        launchedInTaskFragment.setPendingAppearedIntent(intent);
                        mCurrentPendingAppearedIntent = intent;
                    }
                } else {
                    transactionRecord.abort();
+8 −0
Original line number Diff line number Diff line
@@ -499,6 +499,10 @@ class TaskFragmentContainer {
            return;
        }
        mPendingAppearedIntent = null;
        if (mPendingAppearedActivities.isEmpty() && mAppearEmptyTimeout != null) {
            // Nothing to wait. Can be cleanup now.
            mAppearEmptyTimeout.run();
        }
    }

    boolean hasActivity(@NonNull IBinder activityToken) {
@@ -548,6 +552,10 @@ class TaskFragmentContainer {
            if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) {
                mAppearEmptyTimeout = () -> {
                    synchronized (mController.mLock) {
                        if (mAppearEmptyTimeout == null) {
                            // The timeout has already been executed.
                            return;
                        }
                        Log.w(SplitController.TAG,
                                "Fail to wait for activity start in TaskFragment=" + this);
                        mAppearEmptyTimeout = null;
+34 −2
Original line number Diff line number Diff line
@@ -412,7 +412,7 @@ public class SplitControllerTest {
        assertEquals(intent, container.getPendingAppearedIntent());

        // On success, do not clear the pending Intent.
        monitor.onStartActivityResult(START_SUCCESS, new Bundle());
        monitor.onStartActivityResult(START_SUCCESS, options0);

        assertNull(monitor.mCurrentPendingAppearedIntent);
        assertEquals(intent, container.getPendingAppearedIntent());
@@ -425,11 +425,43 @@ public class SplitControllerTest {
        assertNull(monitor.mCurrentPendingAppearedIntent);

        // On failure of a non-tracking Intent, do not clear the pending Intent.
        monitor.onStartActivityResult(START_DELIVERED_TO_TOP, new Bundle());
        monitor.onStartActivityResult(START_DELIVERED_TO_TOP, options1);

        assertEquals(intent, container.getPendingAppearedIntent());
    }

    @Test
    public void testOnStartActivity_emptyExistingTaskFragment_setPendingAppearedIntent() {
        final SplitController.ActivityStartMonitor monitor =
                mSplitController.getActivityStartMonitor();
        final Intent intent = new Intent();
        final Bundle options0 = new Bundle();
        setupSplitRule(mActivity, intent, false /* clearTop */);

        // On creating a new split pair, keep track of the pending Intent.
        monitor.onStartActivity(mActivity, intent, options0);
        final IBinder tfToken = options0.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN);
        final TaskFragmentContainer container = mSplitController.getContainer(tfToken);

        assertEquals(intent, monitor.mCurrentPendingAppearedIntent);
        assertNotNull(container);
        assertEquals(intent, container.getPendingAppearedIntent());

        // On failure of a tracking Intent, clear the pending Intent.
        monitor.onStartActivityResult(START_DELIVERED_TO_TOP, options0);

        assertNull(container.getPendingAppearedIntent());

        // On launching another activity into the existing empty container, keep track of the
        // pending Intent.
        final Bundle option1 = new Bundle();
        monitor.onStartActivity(mActivity, intent, option1);

        assertEquals(tfToken, option1.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN));
        assertEquals(intent, monitor.mCurrentPendingAppearedIntent);
        assertEquals(intent, container.getPendingAppearedIntent());
    }

    @Test
    public void testOnActivityCreated() {
        mSplitController.onActivityCreated(mTransaction, mActivity);