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

Commit d0e791fd authored by Louis Chang's avatar Louis Chang
Browse files

Adding TaskFragmentContainer.Builder

Using the builder vs. passing many parameters necessary for
creating a TaskFragment, in order to enhance code readability
and easier to add new parameters in the future.

This is just a refactor, no functional changes.

Bug: 341842558
Test: wm presubmit
Change-Id: I8b764e8bc6feda8d8aac3475df4616ce15fa3813
parent 0bd33674
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