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

Commit 9d4244ee authored by Chris Li's avatar Chris Li
Browse files

Do not resolve activity creation if it is in unknown TaskFragment

This can happen in two cases:
1. The activity is embedded in another app. Then the current organizer
   shouldn't control it.
2. The activity is in a TaskFragment that the organizer just request to
   remove, but hasn't reach the server side. Then the activity will soon
   be finished with the TaskFragment.

In either case, the organizer shouldn't need to resolve it. Otherwise it
may incorrectly change the state, such as entering split for a finishing
activity.

Bug: 233295443
Test: atest WMJetpackUnitTests:SplitControllerTest
Change-Id: I5d2028dd45abd8d20a8e82bc4e51c4d6dc6e26ee
parent fc974566
Loading
Loading
Loading
Loading
+27 −3
Original line number Diff line number Diff line
@@ -363,7 +363,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
     * @param activity      the activity that is newly added to the Task.
     * @param isOnReparent  whether the activity is reparented to the Task instead of new launched.
     *                      We only support to split as primary for reparented activity for now.
     * @return {@code true} if the activity was placed in TaskFragment container.
     * @return {@code true} if the activity has been handled, such as placed in a TaskFragment, or
     *         in a state that the caller shouldn't handle.
     */
    @VisibleForTesting
    boolean resolveActivityToContainer(@NonNull Activity activity, boolean isOnReparent) {
@@ -373,6 +374,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            return true;
        }

        if (!isOnReparent && getContainerWithActivity(activity) == null
                && getInitialTaskFragmentToken(activity) != null) {
            // We can't find the new launched activity in any recorded container, but it is
            // currently placed in an embedded TaskFragment. This can happen in two cases:
            // 1. the activity is embedded in another app.
            // 2. the organizer has already requested to remove the TaskFragment.
            // In either case, return true since we don't want any extra handling.
            Log.d(TAG, "Activity is in a TaskFragment that is not recorded by the organizer. r="
                    + activity);
            return true;
        }

        /*
         * We will check the following to see if there is any embedding rule matched:
         * 1. Whether the new launched activity should always expand.
@@ -1285,6 +1298,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        return ActivityThread.currentActivityThread().getActivity(activityToken);
    }

    /**
     * Gets the token of the initial TaskFragment that embedded this activity. Do not rely on it
     * after creation because the activity could be reparented.
     */
    @VisibleForTesting
    @Nullable
    IBinder getInitialTaskFragmentToken(@NonNull Activity activity) {
        final ActivityThread.ActivityClientRecord record = ActivityThread.currentActivityThread()
                .getActivityClient(activity.getActivityToken());
        return record != null ? record.mInitialTaskFragmentToken : null;
    }

    /**
     * Returns {@code true} if an Activity with the provided component name should always be
     * expanded to occupy full task bounds. Such activity must not be put in a split.
@@ -1358,8 +1383,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        @Override
        public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) {
            final IBinder activityToken = activity.getActivityToken();
            final IBinder initialTaskFragmentToken = ActivityThread.currentActivityThread()
                    .getActivityClient(activityToken).mInitialTaskFragmentToken;
            final IBinder initialTaskFragmentToken = getInitialTaskFragmentToken(activity);
            // If the activity is not embedded, then it will not have an initial task fragment token
            // so no further action is needed.
            if (initialTaskFragmentToken == null) {
+9 −0
Original line number Diff line number Diff line
@@ -733,6 +733,15 @@ public class SplitControllerTest {
        assertSplitPair(mActivity, primaryActivity);
    }

    @Test
    public void testResolveActivityToContainer_inUnknownTaskFragment() {
        doReturn(new Binder()).when(mSplitController).getInitialTaskFragmentToken(mActivity);

        // No need to handle when the new launched activity is in an unknown TaskFragment.
        assertTrue(mSplitController.resolveActivityToContainer(mActivity,
                false /* isOnReparent */));
    }

    @Test
    public void testGetPlaceholderOptions() {
        doReturn(true).when(mActivity).isResumed();