Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +25 −20 Original line number Diff line number Diff line Loading @@ -354,18 +354,27 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @GuardedBy("mLock") void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct, 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); if (taskContainer == null || taskContainer.isEmpty()) { Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId); 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 // removed on updating. final List<TaskFragmentContainer> containers = Loading Loading @@ -490,6 +499,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** Called on receiving {@link #onTaskFragmentVanished} for cleanup. */ @GuardedBy("mLock") private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) { for (int i = mTaskContainers.size() - 1; i >= 0; i--) { final TaskContainer taskContainer = mTaskContainers.valueAt(i); Loading @@ -505,14 +515,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } private void onTaskConfigurationChanged(int taskId, @NonNull Configuration config) { final TaskContainer taskContainer = mTaskContainers.get(taskId); if (taskContainer == null) { return; } @GuardedBy("mLock") private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer, @NonNull Configuration config) { final boolean wasInPip = taskContainer.isInPictureInPicture(); 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. boolean shouldUpdateAnimationOverride = wasInPip != isInPIp; Loading @@ -536,8 +543,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // Animation will be handled by WM Shell with Shell transition enabled. return; } if (!taskContainer.isTaskBoundsInitialized() || !taskContainer.isWindowingModeInitialized()) { if (!taskContainer.isTaskBoundsInitialized()) { // We don't know about the Task bounds/windowingMode yet. return; } Loading Loading @@ -1024,6 +1030,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** * Returns an empty expanded {@link TaskFragmentContainer} that we can launch an activity into. */ @GuardedBy("mLock") @Nullable private TaskFragmentContainer createEmptyExpandedContainer( @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId, Loading Loading @@ -1105,12 +1112,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return newContainer(pendingAppearedActivity, pendingAppearedActivity, taskId); } @GuardedBy("mLock") TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity, @NonNull Activity activityInTask, int taskId) { return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */, activityInTask, taskId); } @GuardedBy("mLock") TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId) { return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent, Loading @@ -1134,7 +1143,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen throw new IllegalArgumentException("activityInTask must not be null,"); } if (!mTaskContainers.contains(taskId)) { mTaskContainers.put(taskId, new TaskContainer(taskId)); mTaskContainers.put(taskId, new TaskContainer(taskId, activityInTask)); } final TaskContainer taskContainer = mTaskContainers.get(taskId); final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity, Loading @@ -1146,10 +1155,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen Log.w(TAG, "Can't find bounds from activity=" + activityInTask); } } if (!taskContainer.isWindowingModeInitialized()) { taskContainer.setWindowingMode(activityInTask.getResources().getConfiguration() .windowConfiguration.getWindowingMode()); } updateAnimationOverride(taskContainer); return container; } Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +58 −16 Original line number Diff line number Diff line Loading @@ -24,10 +24,13 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import android.app.Activity; import android.app.WindowConfiguration; import android.app.WindowConfiguration.WindowingMode; import android.content.res.Configuration; import android.graphics.Rect; import android.os.IBinder; import android.util.ArraySet; import android.window.TaskFragmentInfo; import android.window.TaskFragmentParentInfo; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading @@ -42,13 +45,10 @@ class TaskContainer { /** The unique task id. */ private final int mTaskId; // TODO(b/240219484): consolidate to mConfiguration /** Available window bounds of this Task. */ private final Rect mTaskBounds = new Rect(); /** Windowing mode of this Task. */ @WindowingMode private int mWindowingMode = WINDOWING_MODE_UNDEFINED; /** Active TaskFragments in this Task. */ @NonNull final List<TaskFragmentContainer> mContainers = new ArrayList<>(); Loading @@ -57,24 +57,56 @@ class TaskContainer { @NonNull 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 * the organizer receives {@link SplitController#onTaskFragmentVanished(TaskFragmentInfo)} event * for them. * the organizer receives * {@link SplitController#onTaskFragmentVanished(WindowContainerTransaction, TaskFragmentInfo)} * event for them. */ 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) { throw new IllegalArgumentException("Invalid Task id"); } 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() { return mTaskId; } int getDisplayId() { return mDisplayId; } boolean isVisible() { return mIsVisible; } @NonNull Rect getTaskBounds() { return mTaskBounds; Loading @@ -94,13 +126,16 @@ class TaskContainer { return !mTaskBounds.isEmpty(); } void setWindowingMode(int windowingMode) { mWindowingMode = windowingMode; @NonNull Configuration getConfiguration() { // Make a copy in case the config is updated unexpectedly. return new Configuration(mConfiguration); } /** Whether the Task windowing mode has been initialized. */ boolean isWindowingModeInitialized() { return mWindowingMode != WINDOWING_MODE_UNDEFINED; void updateTaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.getDisplayId(); mIsVisible = info.isVisibleRequested(); } /** Loading @@ -123,13 +158,20 @@ class TaskContainer { // 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. // TODO we won't need this anymore after we migrate Freeform caption to WM Shell. return WindowConfiguration.inMultiWindowMode(mWindowingMode) ? mWindowingMode : WINDOWING_MODE_MULTI_WINDOW; return isInMultiWindow() ? getWindowingMode() : WINDOWING_MODE_MULTI_WINDOW; } 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. */ Loading libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java +14 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ 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_NEVER; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import android.annotation.NonNull; Loading @@ -26,6 +29,7 @@ import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.util.Pair; Loading Loading @@ -130,4 +134,14 @@ public class EmbeddingTestUtils { primaryBounds.width() + 1, primaryBounds.height() + 1); 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); } } libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java +8 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package androidx.window.extensions.embedding; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 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.verify; Loading @@ -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.assertNull; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Point; import android.os.Handler; import android.platform.test.annotations.Presubmit; import android.window.TaskFragmentInfo; import android.window.TaskFragmentTransaction; Loading Loading @@ -65,7 +68,10 @@ public class JetpackTaskFragmentOrganizerTest { private WindowContainerTransaction mTransaction; @Mock private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback; @Mock private SplitController mSplitController; @Mock private Handler mHandler; private JetpackTaskFragmentOrganizer mOrganizer; @Before Loading @@ -73,9 +79,8 @@ public class JetpackTaskFragmentOrganizerTest { MockitoAnnotations.initMocks(this); mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback); mOrganizer.registerOrganizer(); mSplitController = new SplitController(); spyOn(mOrganizer); spyOn(mSplitController); doReturn(mHandler).when(mSplitController).getHandler(); } @Test Loading Loading @@ -113,7 +118,7 @@ public class JetpackTaskFragmentOrganizerTest { @Test public void testExpandTaskFragment() { final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = createTestTaskContainer(); final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */, new Intent(), taskContainer, mSplitController); final TaskFragmentInfo info = createMockInfo(container); Loading libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +5 −2 Original line number Diff line number Diff line Loading @@ -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.createMockTaskFragmentInfo; 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.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.verify; Loading Loading @@ -140,7 +142,7 @@ public class SplitControllerTest { @Test public void testGetTopActiveContainer() { final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = createTestTaskContainer(); // tf1 has no running activity so is not active. final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */, new Intent(), taskContainer, mSplitController); Loading Loading @@ -200,6 +202,7 @@ public class SplitControllerTest { @Test public void testOnTaskFragmentAppearEmptyTimeout() { final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID); doCallRealMethod().when(mSplitController).onTaskFragmentAppearEmptyTimeout(any(), any()); mSplitController.onTaskFragmentAppearEmptyTimeout(mTransaction, tf); verify(mSplitPresenter).cleanupContainer(mTransaction, tf, Loading Loading @@ -310,7 +313,7 @@ public class SplitControllerTest { @Test public void testOnStartActivityResultError() { final Intent intent = new Intent(); final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = createTestTaskContainer(); final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */, intent, taskContainer, mSplitController); final SplitController.ActivityStartMonitor monitor = Loading Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +25 −20 Original line number Diff line number Diff line Loading @@ -354,18 +354,27 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @GuardedBy("mLock") void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct, 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); if (taskContainer == null || taskContainer.isEmpty()) { Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId); 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 // removed on updating. final List<TaskFragmentContainer> containers = Loading Loading @@ -490,6 +499,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** Called on receiving {@link #onTaskFragmentVanished} for cleanup. */ @GuardedBy("mLock") private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) { for (int i = mTaskContainers.size() - 1; i >= 0; i--) { final TaskContainer taskContainer = mTaskContainers.valueAt(i); Loading @@ -505,14 +515,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } private void onTaskConfigurationChanged(int taskId, @NonNull Configuration config) { final TaskContainer taskContainer = mTaskContainers.get(taskId); if (taskContainer == null) { return; } @GuardedBy("mLock") private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer, @NonNull Configuration config) { final boolean wasInPip = taskContainer.isInPictureInPicture(); 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. boolean shouldUpdateAnimationOverride = wasInPip != isInPIp; Loading @@ -536,8 +543,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // Animation will be handled by WM Shell with Shell transition enabled. return; } if (!taskContainer.isTaskBoundsInitialized() || !taskContainer.isWindowingModeInitialized()) { if (!taskContainer.isTaskBoundsInitialized()) { // We don't know about the Task bounds/windowingMode yet. return; } Loading Loading @@ -1024,6 +1030,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** * Returns an empty expanded {@link TaskFragmentContainer} that we can launch an activity into. */ @GuardedBy("mLock") @Nullable private TaskFragmentContainer createEmptyExpandedContainer( @NonNull WindowContainerTransaction wct, @NonNull Intent intent, int taskId, Loading Loading @@ -1105,12 +1112,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return newContainer(pendingAppearedActivity, pendingAppearedActivity, taskId); } @GuardedBy("mLock") TaskFragmentContainer newContainer(@NonNull Activity pendingAppearedActivity, @NonNull Activity activityInTask, int taskId) { return newContainer(pendingAppearedActivity, null /* pendingAppearedIntent */, activityInTask, taskId); } @GuardedBy("mLock") TaskFragmentContainer newContainer(@NonNull Intent pendingAppearedIntent, @NonNull Activity activityInTask, int taskId) { return newContainer(null /* pendingAppearedActivity */, pendingAppearedIntent, Loading @@ -1134,7 +1143,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen throw new IllegalArgumentException("activityInTask must not be null,"); } if (!mTaskContainers.contains(taskId)) { mTaskContainers.put(taskId, new TaskContainer(taskId)); mTaskContainers.put(taskId, new TaskContainer(taskId, activityInTask)); } final TaskContainer taskContainer = mTaskContainers.get(taskId); final TaskFragmentContainer container = new TaskFragmentContainer(pendingAppearedActivity, Loading @@ -1146,10 +1155,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen Log.w(TAG, "Can't find bounds from activity=" + activityInTask); } } if (!taskContainer.isWindowingModeInitialized()) { taskContainer.setWindowingMode(activityInTask.getResources().getConfiguration() .windowConfiguration.getWindowingMode()); } updateAnimationOverride(taskContainer); return container; } Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +58 −16 Original line number Diff line number Diff line Loading @@ -24,10 +24,13 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import android.app.Activity; import android.app.WindowConfiguration; import android.app.WindowConfiguration.WindowingMode; import android.content.res.Configuration; import android.graphics.Rect; import android.os.IBinder; import android.util.ArraySet; import android.window.TaskFragmentInfo; import android.window.TaskFragmentParentInfo; import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; import androidx.annotation.Nullable; Loading @@ -42,13 +45,10 @@ class TaskContainer { /** The unique task id. */ private final int mTaskId; // TODO(b/240219484): consolidate to mConfiguration /** Available window bounds of this Task. */ private final Rect mTaskBounds = new Rect(); /** Windowing mode of this Task. */ @WindowingMode private int mWindowingMode = WINDOWING_MODE_UNDEFINED; /** Active TaskFragments in this Task. */ @NonNull final List<TaskFragmentContainer> mContainers = new ArrayList<>(); Loading @@ -57,24 +57,56 @@ class TaskContainer { @NonNull 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 * the organizer receives {@link SplitController#onTaskFragmentVanished(TaskFragmentInfo)} event * for them. * the organizer receives * {@link SplitController#onTaskFragmentVanished(WindowContainerTransaction, TaskFragmentInfo)} * event for them. */ 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) { throw new IllegalArgumentException("Invalid Task id"); } 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() { return mTaskId; } int getDisplayId() { return mDisplayId; } boolean isVisible() { return mIsVisible; } @NonNull Rect getTaskBounds() { return mTaskBounds; Loading @@ -94,13 +126,16 @@ class TaskContainer { return !mTaskBounds.isEmpty(); } void setWindowingMode(int windowingMode) { mWindowingMode = windowingMode; @NonNull Configuration getConfiguration() { // Make a copy in case the config is updated unexpectedly. return new Configuration(mConfiguration); } /** Whether the Task windowing mode has been initialized. */ boolean isWindowingModeInitialized() { return mWindowingMode != WINDOWING_MODE_UNDEFINED; void updateTaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.getDisplayId(); mIsVisible = info.isVisibleRequested(); } /** Loading @@ -123,13 +158,20 @@ class TaskContainer { // 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. // TODO we won't need this anymore after we migrate Freeform caption to WM Shell. return WindowConfiguration.inMultiWindowMode(mWindowingMode) ? mWindowingMode : WINDOWING_MODE_MULTI_WINDOW; return isInMultiWindow() ? getWindowingMode() : WINDOWING_MODE_MULTI_WINDOW; } 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. */ Loading
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/EmbeddingTestUtils.java +14 −0 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ 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_NEVER; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import android.annotation.NonNull; Loading @@ -26,6 +29,7 @@ import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.util.Pair; Loading Loading @@ -130,4 +134,14 @@ public class EmbeddingTestUtils { primaryBounds.width() + 1, primaryBounds.height() + 1); 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); } }
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java +8 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package androidx.window.extensions.embedding; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 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.verify; Loading @@ -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.assertNull; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Point; import android.os.Handler; import android.platform.test.annotations.Presubmit; import android.window.TaskFragmentInfo; import android.window.TaskFragmentTransaction; Loading Loading @@ -65,7 +68,10 @@ public class JetpackTaskFragmentOrganizerTest { private WindowContainerTransaction mTransaction; @Mock private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback; @Mock private SplitController mSplitController; @Mock private Handler mHandler; private JetpackTaskFragmentOrganizer mOrganizer; @Before Loading @@ -73,9 +79,8 @@ public class JetpackTaskFragmentOrganizerTest { MockitoAnnotations.initMocks(this); mOrganizer = new JetpackTaskFragmentOrganizer(Runnable::run, mCallback); mOrganizer.registerOrganizer(); mSplitController = new SplitController(); spyOn(mOrganizer); spyOn(mSplitController); doReturn(mHandler).when(mSplitController).getHandler(); } @Test Loading Loading @@ -113,7 +118,7 @@ public class JetpackTaskFragmentOrganizerTest { @Test public void testExpandTaskFragment() { final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = createTestTaskContainer(); final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */, new Intent(), taskContainer, mSplitController); final TaskFragmentInfo info = createMockInfo(container); Loading
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +5 −2 Original line number Diff line number Diff line Loading @@ -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.createMockTaskFragmentInfo; 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.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.verify; Loading Loading @@ -140,7 +142,7 @@ public class SplitControllerTest { @Test public void testGetTopActiveContainer() { final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = createTestTaskContainer(); // tf1 has no running activity so is not active. final TaskFragmentContainer tf1 = new TaskFragmentContainer(null /* activity */, new Intent(), taskContainer, mSplitController); Loading Loading @@ -200,6 +202,7 @@ public class SplitControllerTest { @Test public void testOnTaskFragmentAppearEmptyTimeout() { final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID); doCallRealMethod().when(mSplitController).onTaskFragmentAppearEmptyTimeout(any(), any()); mSplitController.onTaskFragmentAppearEmptyTimeout(mTransaction, tf); verify(mSplitPresenter).cleanupContainer(mTransaction, tf, Loading Loading @@ -310,7 +313,7 @@ public class SplitControllerTest { @Test public void testOnStartActivityResultError() { final Intent intent = new Intent(); final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = createTestTaskContainer(); final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */, intent, taskContainer, mSplitController); final SplitController.ActivityStartMonitor monitor = Loading