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

Commit a13ffe82 authored by Charles Chen's avatar Charles Chen
Browse files

Track visibility in onTaskFragmentParentInfoChanged

As we add visibility info in TaskFragmentParentInfo, we can update
the parent Task visibility in onTaskFragmentParentInfoChanged.
It can be furthur used in update SplitContainers of visible containers.

Test: atest WMJetpackUnitTests
Bug: 243609832
Bug: 207494880

Change-Id: Iad4b8d46bad75c352fc6a1a732ef796cdbfad4f9
parent 3589fb90
Loading
Loading
Loading
Loading
+25 −20
Original line number Original line Diff line number Diff line
@@ -354,18 +354,27 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
    void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
            int taskId, @NonNull TaskFragmentParentInfo parentInfo) {
            int taskId, @NonNull TaskFragmentParentInfo parentInfo) {
        // TODO(b/241043111): handles displayId and visibility here.
        final Configuration parentConfig = parentInfo.getConfiguration();
        onTaskConfigurationChanged(taskId, parentConfig);
        if (isInPictureInPicture(parentConfig)) {
            // No need to update presentation in PIP until the Task exit PIP.
            return;
        }
        final TaskContainer taskContainer = getTaskContainer(taskId);
        final TaskContainer taskContainer = getTaskContainer(taskId);
        if (taskContainer == null || taskContainer.isEmpty()) {
        if (taskContainer == null || taskContainer.isEmpty()) {
            Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
            Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
            return;
            return;
        }
        }
        taskContainer.updateTaskFragmentParentInfo(parentInfo);
        if (!taskContainer.isVisible()) {
            // Don't update containers if the task is not visible. We only update containers when
            // parentInfo#isVisibleRequested is true.
            return;
        }
        onTaskContainerInfoChanged(taskContainer, parentInfo.getConfiguration());
        if (isInPictureInPicture(parentInfo.getConfiguration())) {
            // No need to update presentation in PIP until the Task exit PIP.
            return;
        }
        updateContainersInTask(wct, taskContainer);
    }

    private void updateContainersInTask(@NonNull WindowContainerTransaction wct,
            @NonNull TaskContainer taskContainer) {
        // Update all TaskFragments in the Task. Make a copy of the list since some may be
        // Update all TaskFragments in the Task. Make a copy of the list since some may be
        // removed on updating.
        // removed on updating.
        final List<TaskFragmentContainer> containers =
        final List<TaskFragmentContainer> containers =
@@ -490,6 +499,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    }
    }


    /** Called on receiving {@link #onTaskFragmentVanished} for cleanup. */
    /** Called on receiving {@link #onTaskFragmentVanished} for cleanup. */
    @GuardedBy("mLock")
    private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) {
    private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) {
        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
            final TaskContainer taskContainer = mTaskContainers.valueAt(i);
            final TaskContainer taskContainer = mTaskContainers.valueAt(i);
@@ -505,14 +515,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        }
        }
    }
    }


    private void onTaskConfigurationChanged(int taskId, @NonNull Configuration config) {
    @GuardedBy("mLock")
        final TaskContainer taskContainer = mTaskContainers.get(taskId);
    private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer,
        if (taskContainer == null) {
            @NonNull Configuration config) {
            return;
        }
        final boolean wasInPip = taskContainer.isInPictureInPicture();
        final boolean wasInPip = taskContainer.isInPictureInPicture();
        final boolean isInPIp = isInPictureInPicture(config);
        final boolean isInPIp = isInPictureInPicture(config);
        taskContainer.setWindowingMode(config.windowConfiguration.getWindowingMode());


        // We need to check the animation override when enter/exit PIP or has bounds changed.
        // We need to check the animation override when enter/exit PIP or has bounds changed.
        boolean shouldUpdateAnimationOverride = wasInPip != isInPIp;
        boolean shouldUpdateAnimationOverride = wasInPip != isInPIp;
@@ -536,8 +543,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            // Animation will be handled by WM Shell with Shell transition enabled.
            // Animation will be handled by WM Shell with Shell transition enabled.
            return;
            return;
        }
        }
        if (!taskContainer.isTaskBoundsInitialized()
        if (!taskContainer.isTaskBoundsInitialized()) {
                || !taskContainer.isWindowingModeInitialized()) {
            // We don't know about the Task bounds/windowingMode yet.
            // We don't know about the Task bounds/windowingMode yet.
            return;
            return;
        }
        }
@@ -1024,6 +1030,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    /**
    /**
     * Returns an empty expanded {@link TaskFragmentContainer} that we can launch an activity into.
     * Returns an empty expanded {@link TaskFragmentContainer} that we can launch an activity into.
     */
     */
    @GuardedBy("mLock")
    @Nullable
    @Nullable
    private TaskFragmentContainer createEmptyExpandedContainer(
    private TaskFragmentContainer createEmptyExpandedContainer(
            @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
            @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId,
@@ -1105,12 +1112,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        return newContainer(pendingAppearedActivity, pendingAppearedActivity, taskId);
        return newContainer(pendingAppearedActivity, pendingAppearedActivity, taskId);
    }
    }


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


    @GuardedBy("mLock")
    TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
    TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent,
            @NonNull Activity activityInTask, int taskId) {
            @NonNull Activity activityInTask, int taskId) {
        return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
        return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent,
@@ -1134,7 +1143,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            throw new IllegalArgumentException("activityInTask must not be null,");
            throw new IllegalArgumentException("activityInTask must not be null,");
        }
        }
        if (!mTaskContainers.contains(taskId)) {
        if (!mTaskContainers.contains(taskId)) {
            mTaskContainers.put(taskId, new TaskContainer(taskId));
            mTaskContainers.put(taskId, new TaskContainer(taskId, activityInTask));
        }
        }
        final TaskContainer taskContainer = mTaskContainers.get(taskId);
        final TaskContainer taskContainer = mTaskContainers.get(taskId);
        final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
        final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity,
@@ -1146,10 +1155,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
                Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
            }
            }
        }
        }
        if (!taskContainer.isWindowingModeInitialized()) {
            taskContainer.setWindowingMode(activityInTask.getResources().getConfiguration()
                    .windowConfiguration.getWindowingMode());
        }
        updateAnimationOverride(taskContainer);
        updateAnimationOverride(taskContainer);
        return container;
        return container;
    }
    }
+58 −16
Original line number Original line Diff line number Diff line
@@ -24,10 +24,13 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.app.Activity;
import android.app.Activity;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.app.WindowConfiguration.WindowingMode;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.IBinder;
import android.util.ArraySet;
import android.util.ArraySet;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentParentInfo;
import android.window.WindowContainerTransaction;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
@@ -42,13 +45,10 @@ class TaskContainer {
    /** The unique task id. */
    /** The unique task id. */
    private final int mTaskId;
    private final int mTaskId;


    // TODO(b/240219484): consolidate to mConfiguration
    /** Available window bounds of this Task. */
    /** Available window bounds of this Task. */
    private final Rect mTaskBounds = new Rect();
    private final Rect mTaskBounds = new Rect();


    /** Windowing mode of this Task. */
    @WindowingMode
    private int mWindowingMode = WINDOWING_MODE_UNDEFINED;

    /** Active TaskFragments in this Task. */
    /** Active TaskFragments in this Task. */
    @NonNull
    @NonNull
    final List<TaskFragmentContainer> mContainers = new ArrayList<>();
    final List<TaskFragmentContainer> mContainers = new ArrayList<>();
@@ -57,24 +57,56 @@ class TaskContainer {
    @NonNull
    @NonNull
    final List<SplitContainer> mSplitContainers = new ArrayList<>();
    final List<SplitContainer> mSplitContainers = new ArrayList<>();


    @NonNull
    private final Configuration mConfiguration;

    private int mDisplayId;

    private boolean mIsVisible;

    /**
    /**
     * TaskFragments that the organizer has requested to be closed. They should be removed when
     * TaskFragments that the organizer has requested to be closed. They should be removed when
     * the organizer receives {@link SplitController#onTaskFragmentVanished(TaskFragmentInfo)} event
     * the organizer receives
     * for them.
     * {@link SplitController#onTaskFragmentVanished(WindowContainerTransaction, TaskFragmentInfo)}
     * event for them.
     */
     */
    final Set<IBinder> mFinishedContainer = new ArraySet<>();
    final Set<IBinder> mFinishedContainer = new ArraySet<>();


    TaskContainer(int taskId) {
    /**
     * The {@link TaskContainer} constructor
     *
     * @param taskId The ID of the Task, which must match {@link Activity#getTaskId()} with
     *               {@code activityInTask}.
     * @param activityInTask The {@link Activity} in the Task with {@code taskId}. It is used to
     *                       initialize the {@link TaskContainer} properties.
     *
     */
    TaskContainer(int taskId, @NonNull Activity activityInTask) {
        if (taskId == INVALID_TASK_ID) {
        if (taskId == INVALID_TASK_ID) {
            throw new IllegalArgumentException("Invalid Task id");
            throw new IllegalArgumentException("Invalid Task id");
        }
        }
        mTaskId = taskId;
        mTaskId = taskId;
        // Make a copy in case the activity's config is updated, and updates the TaskContainer's
        // config unexpectedly.
        mConfiguration = new Configuration(activityInTask.getResources().getConfiguration());
        mDisplayId = activityInTask.getDisplayId();
        // Note that it is always called when there's a new Activity is started, which implies
        // the host task is visible.
        mIsVisible = true;
    }
    }


    int getTaskId() {
    int getTaskId() {
        return mTaskId;
        return mTaskId;
    }
    }


    int getDisplayId() {
        return mDisplayId;
    }

    boolean isVisible() {
        return mIsVisible;
    }

    @NonNull
    @NonNull
    Rect getTaskBounds() {
    Rect getTaskBounds() {
        return mTaskBounds;
        return mTaskBounds;
@@ -94,13 +126,16 @@ class TaskContainer {
        return !mTaskBounds.isEmpty();
        return !mTaskBounds.isEmpty();
    }
    }


    void setWindowingMode(int windowingMode) {
    @NonNull
        mWindowingMode = windowingMode;
    Configuration getConfiguration() {
        // Make a copy in case the config is updated unexpectedly.
        return new Configuration(mConfiguration);
    }
    }


    /** Whether the Task windowing mode has been initialized. */
    void updateTaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) {
    boolean isWindowingModeInitialized() {
        mConfiguration.setTo(info.getConfiguration());
        return mWindowingMode != WINDOWING_MODE_UNDEFINED;
        mDisplayId = info.getDisplayId();
        mIsVisible = info.isVisibleRequested();
    }
    }


    /**
    /**
@@ -123,13 +158,20 @@ class TaskContainer {
        // DecorCaptionView won't work correctly. As a result, have the TaskFragment to be in the
        // DecorCaptionView won't work correctly. As a result, have the TaskFragment to be in the
        // Task windowing mode if the Task is in multi window.
        // Task windowing mode if the Task is in multi window.
        // TODO we won't need this anymore after we migrate Freeform caption to WM Shell.
        // TODO we won't need this anymore after we migrate Freeform caption to WM Shell.
        return WindowConfiguration.inMultiWindowMode(mWindowingMode)
        return isInMultiWindow() ? getWindowingMode() : WINDOWING_MODE_MULTI_WINDOW;
                ? mWindowingMode
                : WINDOWING_MODE_MULTI_WINDOW;
    }
    }


    boolean isInPictureInPicture() {
    boolean isInPictureInPicture() {
        return mWindowingMode == WINDOWING_MODE_PINNED;
        return getWindowingMode() == WINDOWING_MODE_PINNED;
    }

    boolean isInMultiWindow() {
        return WindowConfiguration.inMultiWindowMode(getWindowingMode());
    }

    @WindowingMode
    private int getWindowingMode() {
        return getConfiguration().windowConfiguration.getWindowingMode();
    }
    }


    /** Whether there is any {@link TaskFragmentContainer} below this Task. */
    /** Whether there is any {@link TaskFragmentContainer} below this Task. */
+14 −0
Original line number Original line Diff line number Diff line
@@ -16,9 +16,12 @@


package androidx.window.extensions.embedding;
package androidx.window.extensions.embedding;


import static android.view.Display.DEFAULT_DISPLAY;

import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;


import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;


import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -26,6 +29,7 @@ import android.app.Activity;
import android.content.Intent;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Rect;
import android.util.Pair;
import android.util.Pair;
@@ -130,4 +134,14 @@ public class EmbeddingTestUtils {
                primaryBounds.width() + 1, primaryBounds.height() + 1);
                primaryBounds.width() + 1, primaryBounds.height() + 1);
        return aInfo;
        return aInfo;
    }
    }

    static TaskContainer createTestTaskContainer() {
        Resources resources = mock(Resources.class);
        doReturn(new Configuration()).when(resources).getConfiguration();
        Activity activity = mock(Activity.class);
        doReturn(resources).when(activity).getResources();
        doReturn(DEFAULT_DISPLAY).when(activity).getDisplayId();

        return new TaskContainer(TASK_ID, activity);
    }
}
}
+8 −3
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;


import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -26,12 +27,14 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.never;


import android.content.Intent;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Point;
import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentInfo;
import android.window.TaskFragmentTransaction;
import android.window.TaskFragmentTransaction;
@@ -65,7 +68,10 @@ public class JetpackTaskFragmentOrganizerTest {
    private WindowContainerTransaction mTransaction;
    private WindowContainerTransaction mTransaction;
    @Mock
    @Mock
    private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback;
    private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback;
    @Mock
    private SplitController mSplitController;
    private SplitController mSplitController;
    @Mock
    private Handler mHandler;
    private JetpackTaskFragmentOrganizer mOrganizer;
    private JetpackTaskFragmentOrganizer mOrganizer;


    @Before
    @Before
@@ -73,9 +79,8 @@ public class JetpackTaskFragmentOrganizerTest {
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
        mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback);
        mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback);
        mOrganizer.registerOrganizer();
        mOrganizer.registerOrganizer();
        mSplitController = new SplitController();
        spyOn(mOrganizer);
        spyOn(mOrganizer);
        spyOn(mSplitController);
        doReturn(mHandler).when(mSplitController).getHandler();
    }
    }


    @Test
    @Test
@@ -113,7 +118,7 @@ public class JetpackTaskFragmentOrganizerTest {


    @Test
    @Test
    public void testExpandTaskFragment() {
    public void testExpandTaskFragment() {
        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
        final TaskContainer taskContainer = createTestTaskContainer();
        final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
        final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
                new Intent(), taskContainer, mSplitController);
                new Intent(), taskContainer, mSplitController);
        final TaskFragmentInfo info = createMockInfo(container);
        final TaskFragmentInfo info = createMockInfo(container);
+5 −2
Original line number Original line Diff line number Diff line
@@ -34,9 +34,11 @@ import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createActivityInfoWithMinDimensions;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.getSplitBounds;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;


import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;


@@ -140,7 +142,7 @@ public class SplitControllerTest {


    @Test
    @Test
    public void testGetTopActiveContainer() {
    public void testGetTopActiveContainer() {
        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
        final TaskContainer taskContainer = createTestTaskContainer();
        // tf1 has no running activity so is not active.
        // tf1 has no running activity so is not active.
        final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
        final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */,
                new Intent(), taskContainer, mSplitController);
                new Intent(), taskContainer, mSplitController);
@@ -200,6 +202,7 @@ public class SplitControllerTest {
    @Test
    @Test
    public void testOnTaskFragmentAppearEmptyTimeout() {
    public void testOnTaskFragmentAppearEmptyTimeout() {
        final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
        final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
        doCallRealMethod().when(mSplitController).onTaskFragmentAppearEmptyTimeout(any(), any());
        mSplitController.onTaskFragmentAppearEmptyTimeout(mTransaction, tf);
        mSplitController.onTaskFragmentAppearEmptyTimeout(mTransaction, tf);


        verify(mSplitPresenter).cleanupContainer(mTransaction, tf,
        verify(mSplitPresenter).cleanupContainer(mTransaction, tf,
@@ -310,7 +313,7 @@ public class SplitControllerTest {
    @Test
    @Test
    public void testOnStartActivityResultError() {
    public void testOnStartActivityResultError() {
        final Intent intent = new Intent();
        final Intent intent = new Intent();
        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
        final TaskContainer taskContainer = createTestTaskContainer();
        final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
        final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
                intent, taskContainer, mSplitController);
                intent, taskContainer, mSplitController);
        final SplitController.ActivityStartMonitor monitor =
        final SplitController.ActivityStartMonitor monitor =
Loading