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

Commit 89bc5f99 authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "Adding TaskFragmentContainer.Builder" into main

parents ff5ab550 d0e791fd
Loading
Loading
Loading
Loading
+16 −72
Original line number Diff line number Diff line
@@ -1322,7 +1322,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            mPresenter.expandTaskFragment(wct, container);
        } else {
            // Put activity into a new expanded container.
            final TaskFragmentContainer newContainer = newContainer(activity, getTaskId(activity));
            final TaskFragmentContainer newContainer =
                    new TaskFragmentContainer.Builder(this, getTaskId(activity), activity)
                            .setPendingAppearedActivity(activity).build();
            mPresenter.expandActivity(wct, newContainer.getTaskFragmentToken(), activity);
        }
    }
@@ -1738,9 +1740,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            // Can't find any activity in the Task that we can use as the owner activity.
            return null;
        }
        final TaskFragmentContainer container = newContainer(null /* pendingAppearedActivity */,
                intent, activityInTask, taskId, null /* pairedPrimaryContainer*/, overlayTag,
                launchOptions, associateLaunchingActivity);
        final TaskFragmentContainer container =
                new TaskFragmentContainer.Builder(this, taskId, activityInTask)
                        .setPendingAppearedIntent(intent)
                        .setOverlayTag(overlayTag)
                        .setLaunchOptions(launchOptions)
                        .setAssociatedActivity(associateLaunchingActivity ? activityInTask : null)
                        .build();
        final IBinder taskFragmentToken = container.getTaskFragmentToken();
        // Note that taskContainer will not exist before calling #newContainer if the container
        // is the first embedded TF in the task.
@@ -1818,74 +1824,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        return null;
    }

    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity, int taskId) {
        return newContainer(pendingAppearedActivity, pendingAppearedActivity, taskId);
    }

    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity,
            @NonNull Activity activityInTask, int taskId) {
        return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */,
                activityInTask, taskId, null /* pairedPrimaryContainer */, null /* tag */,
                null /* launchOptions */, false /* associateLaunchingActivity */);
    }

    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
            @NonNull Activity activityInTask, int taskId) {
        return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
                activityInTask, taskId, null /* pairedPrimaryContainer */, null /* tag */,
                null /* launchOptions */, false /* associateLaunchingActivity */);
    }

    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
            @NonNull Activity activityInTask, int taskId,
            @NonNull TaskFragmentContainer pairedPrimaryContainer) {
        return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
                activityInTask, taskId, pairedPrimaryContainer, null /* tag */,
                null /* launchOptions */, false /* associateLaunchingActivity */);
    }

    /**
     * Creates and registers a new organized container with an optional activity that will be
     * re-parented to it in a WCT.
     *
     * @param pendingAppearedActivity the activity that will be reparented to the TaskFragment.
     * @param pendingAppearedIntent   the Intent that will be started in the TaskFragment.
     * @param activityInTask          activity in the same Task so that we can get the Task bounds
     *                                if needed.
     * @param taskId                  parent Task of the new TaskFragment.
     * @param pairedContainer  the paired primary {@link TaskFragmentContainer}. When it is
     *                                set, the new container will be added right above it.
     * @param overlayTag              The tag for the new created overlay container. It must be
     *                                needed if {@code isOverlay} is {@code true}. Otherwise,
     *                                it should be {@code null}.
     * @param launchOptions           The launch options bundle to create a container. Must be
     *                                specified for overlay container.
     * @param associateLaunchingActivity {@code true} to indicate this overlay container
     *                                   should associate with launching activity.
     */
    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@Nullable Activity pendingAppearedActivity,
            @Nullable Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId,
            @Nullable TaskFragmentContainer pairedContainer, @Nullable String overlayTag,
            @Nullable Bundle launchOptions, boolean associateLaunchingActivity) {
        if (activityInTask == null) {
            throw new IllegalArgumentException("activityInTask must not be null,");
        }
        if (!mTaskContainers.contains(taskId)) {
            mTaskContainers.put(taskId, new TaskContainer(taskId, activityInTask));
            mDividerPresenters.put(taskId, new DividerPresenter(taskId, this, mExecutor));
        }
        final TaskContainer taskContainer = mTaskContainers.get(taskId);
        final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
                pendingAppearedIntent, taskContainer, this, pairedContainer, overlayTag,
                launchOptions, associateLaunchingActivity ? activityInTask : null);
        return container;
    }

    /**
     * Creates and registers a new split with the provided containers and configuration. Finishes
     * existing secondary containers if found for the given primary container.
@@ -2581,6 +2519,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        return mTaskContainers.get(taskId);
    }

    @GuardedBy("mLock")
    void addTaskContainer(int taskId, TaskContainer taskContainer) {
        mTaskContainers.put(taskId, taskContainer);
        mDividerPresenters.put(taskId, new DividerPresenter(taskId, this, mExecutor));
    }

    Handler getHandler() {
        return mHandler;
    }
+15 −9
Original line number Diff line number Diff line
@@ -186,8 +186,9 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {

        // Create new empty task fragment
        final int taskId = primaryContainer.getTaskId();
        final TaskFragmentContainer secondaryContainer = mController.newContainer(
                secondaryIntent, primaryActivity, taskId);
        final TaskFragmentContainer secondaryContainer =
                new TaskFragmentContainer.Builder(mController, taskId, primaryActivity)
                        .setPendingAppearedIntent(secondaryIntent).build();
        final Rect secondaryRelBounds = getRelBoundsForPosition(POSITION_END, taskProperties,
                splitAttributes);
        final int windowingMode = mController.getTaskContainer(taskId)
@@ -261,7 +262,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        TaskFragmentContainer container = mController.getContainerWithActivity(activity);
        final int taskId = container != null ? container.getTaskId() : activity.getTaskId();
        if (container == null || container == containerToAvoid) {
            container = mController.newContainer(activity, taskId);
            container = new TaskFragmentContainer.Builder(mController, taskId, activity)
                    .setPendingAppearedActivity(activity).build();
            final int windowingMode = mController.getTaskContainer(taskId)
                    .getWindowingModeForTaskFragment(relBounds);
            final IBinder reparentActivityToken = activity.getActivityToken();
@@ -304,15 +306,19 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
                launchingActivity);
        if (primaryContainer == null) {
            primaryContainer = mController.newContainer(launchingActivity,
                    launchingActivity.getTaskId());
            primaryContainer = new TaskFragmentContainer.Builder(mController,
                    launchingActivity.getTaskId(), launchingActivity)
                    .setPendingAppearedActivity(launchingActivity).build();
        }

        final int taskId = primaryContainer.getTaskId();
        final TaskFragmentContainer secondaryContainer = mController.newContainer(activityIntent,
                launchingActivity, taskId,
                // Pass in the primary container to make sure it is added right above the primary.
                primaryContainer);
        final TaskFragmentContainer secondaryContainer =
                new TaskFragmentContainer.Builder(mController, taskId, launchingActivity)
                        .setPendingAppearedIntent(activityIntent)
                        // Pass in the primary container to make sure it is added right above the
                        // primary.
                        .setPairedPrimaryContainer(primaryContainer)
                        .build();
        final TaskContainer taskContainer = mController.getTaskContainer(taskId);
        final int windowingMode = taskContainer.getWindowingModeForTaskFragment(
                primaryRelBounds);
+112 −21
Original line number Diff line number Diff line
@@ -194,20 +194,6 @@ class TaskFragmentContainer {
     */
    private boolean mLastDimOnTask;

    /**
     * @see #TaskFragmentContainer(Activity, Intent, TaskContainer, SplitController,
     * TaskFragmentContainer, String, Bundle, Activity)
     */
    TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
                          @Nullable Intent pendingAppearedIntent,
                          @NonNull TaskContainer taskContainer,
                          @NonNull SplitController controller,
                          @Nullable TaskFragmentContainer pairedPrimaryContainer) {
        this(pendingAppearedActivity, pendingAppearedIntent, taskContainer,
                controller, pairedPrimaryContainer, null /* overlayTag */,
                null /* launchOptions */, null /* associatedActivity */);
    }

    /**
     * Creates a container with an existing activity that will be re-parented to it in a window
     * container transaction.
@@ -218,7 +204,7 @@ class TaskFragmentContainer {
     * @param associatedActivity        the associated activity of the overlay container. Must be
     *                                  {@code null} for a non-overlay container.
     */
    TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
    private TaskFragmentContainer(@Nullable Activity pendingAppearedActivity,
            @Nullable Intent pendingAppearedIntent, @NonNull TaskContainer taskContainer,
            @NonNull SplitController controller,
            @Nullable TaskFragmentContainer pairedPrimaryContainer, @Nullable String overlayTag,
@@ -232,12 +218,6 @@ class TaskFragmentContainer {
        mToken = new Binder("TaskFragmentContainer");
        mTaskContainer = taskContainer;
        mOverlayTag = overlayTag;
        if (overlayTag != null) {
            Objects.requireNonNull(launchOptions);
        } else if (associatedActivity != null) {
            throw new IllegalArgumentException("Associated activity must be null for "
                    + "non-overlay activity.");
        }
        mAssociatedActivityToken = associatedActivity != null
                ? associatedActivity.getActivityToken() : null;

@@ -1116,6 +1096,117 @@ class TaskFragmentContainer {
        return sb.append("]").toString();
    }

    static final class Builder {
        @NonNull
        private final SplitController mSplitController;

        // The parent Task id of the new TaskFragment.
        private final int mTaskId;

        // The activity in the same Task so that we can get the Task bounds if needed.
        @NonNull
        private final Activity mActivityInTask;

        // The activity that will be reparented to the TaskFragment.
        @Nullable
        private Activity mPendingAppearedActivity;

        // The Intent that will be started in the TaskFragment.
        @Nullable
        private Intent mPendingAppearedIntent;

        // The paired primary {@link TaskFragmentContainer}. When it is set, the new container
        // will be added right above it.
        @Nullable
        private TaskFragmentContainer mPairedPrimaryContainer;

        // The launch options bundle to create a container. Must be specified for overlay container.
        @Nullable
        private Bundle mLaunchOptions;

        // The tag for the new created overlay container. This is required when creating an
        // overlay container.
        @Nullable
        private String mOverlayTag;

        // The associated activity of the overlay container. Must be {@code null} for a
        // non-overlay container.
        @Nullable
        private Activity mAssociatedActivity;

        Builder(@NonNull SplitController splitController, int taskId,
                @Nullable Activity activityInTask) {
            if (taskId <= 0) {
                throw new IllegalArgumentException("taskId is invalid, " + taskId);
            }

            mSplitController = splitController;
            mTaskId = taskId;
            mActivityInTask = activityInTask;
        }

        @NonNull
        Builder setPendingAppearedActivity(@Nullable Activity pendingAppearedActivity) {
            mPendingAppearedActivity = pendingAppearedActivity;
            return this;
        }

        @NonNull
        Builder setPendingAppearedIntent(@Nullable Intent pendingAppearedIntent) {
            mPendingAppearedIntent = pendingAppearedIntent;
            return this;
        }

        @NonNull
        Builder setPairedPrimaryContainer(@Nullable TaskFragmentContainer pairedPrimaryContainer) {
            mPairedPrimaryContainer = pairedPrimaryContainer;
            return this;
        }

        @NonNull
        Builder setLaunchOptions(@Nullable Bundle launchOptions) {
            mLaunchOptions = launchOptions;
            return this;
        }

        @NonNull
        Builder setOverlayTag(@Nullable String overlayTag) {
            mOverlayTag = overlayTag;
            return this;
        }

        @NonNull
        Builder setAssociatedActivity(@Nullable Activity associatedActivity) {
            mAssociatedActivity = associatedActivity;
            return this;
        }

        @NonNull
        TaskFragmentContainer build() {
            if (mOverlayTag != null) {
                Objects.requireNonNull(mLaunchOptions);
            } else if (mAssociatedActivity != null) {
                throw new IllegalArgumentException("Associated activity must be null for "
                        + "non-overlay activity.");
            }

            TaskContainer taskContainer = mSplitController.getTaskContainer(mTaskId);
            if (taskContainer == null && mActivityInTask == null) {
                throw new IllegalArgumentException("mActivityInTask must be set.");
            }

            if (taskContainer == null) {
                // Adding a TaskContainer if no existed one.
                taskContainer = new TaskContainer(mTaskId, mActivityInTask);
                mSplitController.addTaskContainer(mTaskId, taskContainer);
            }

            return new TaskFragmentContainer(mPendingAppearedActivity, mPendingAppearedIntent,
                    taskContainer, mSplitController, mPairedPrimaryContainer, mOverlayTag,
                    mLaunchOptions, mAssociatedActivity);
        }
    }

    static class OverlayContainerRestoreParams {
        /** The token of the overlay container */
        @NonNull
+13 −0
Original line number Diff line number Diff line
@@ -248,4 +248,17 @@ public class EmbeddingTestUtils {
        return new SplitPlaceholderRule.Builder(placeholderIntent, activityPredicate,
                intentPredicate, windowMetricsPredicate);
    }

    @NonNull
    static TaskFragmentContainer createTfContainer(
            @NonNull SplitController splitController, @NonNull Activity activity) {
        return createTfContainer(splitController, TASK_ID, activity);
    }

    @NonNull
    static TaskFragmentContainer createTfContainer(
            @NonNull SplitController splitController, int taskId, @NonNull Activity activity) {
        return new TaskFragmentContainer.Builder(splitController, taskId, activity)
                .setPendingAppearedActivity(activity).build();
    }
}
+6 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

@@ -105,8 +106,11 @@ public class JetpackTaskFragmentOrganizerTest {
    @Test
    public void testExpandTaskFragment() {
        final TaskContainer taskContainer = createTestTaskContainer();
        final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
                new Intent(), taskContainer, mSplitController, null /* pairedPrimaryContainer */);
        doReturn(taskContainer).when(mSplitController).getTaskContainer(anyInt());
        final TaskFragmentContainer container =  new TaskFragmentContainer.Builder(mSplitController,
                taskContainer.getTaskId(), null /* activityInTask */)
                .setPendingAppearedIntent(new Intent())
                .build();
        final TaskFragmentInfo info = createMockInfo(container);
        mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
        container.setInfo(mTransaction, info);
Loading