Merge "Allow activity in ActivityEmbedding split to get Task windowing mode" into tm-dev am: 8358f51ed3 am: 7c9f75dba7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17905030

Change-Id: I27001f0eee7bde846140a6fa9aea48063917c06b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-04-28 08:41:56 +00:00
committed by Automerger Merge Worker
6 changed files with 196 additions and 29 deletions

View File

@@ -16,7 +16,6 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.app.Activity; import android.app.Activity;
@@ -49,7 +48,8 @@ import java.util.concurrent.Executor;
class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
/** Mapping from the client assigned unique token to the {@link TaskFragmentInfo}. */ /** Mapping from the client assigned unique token to the {@link TaskFragmentInfo}. */
private final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>(); @VisibleForTesting
final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>();
/** /**
* Mapping from the client assigned unique token to the TaskFragment parent * Mapping from the client assigned unique token to the TaskFragment parent
@@ -120,25 +120,29 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
* @param secondaryFragmentBounds the initial bounds for the secondary TaskFragment * @param secondaryFragmentBounds the initial bounds for the secondary TaskFragment
* @param activityIntent Intent to start the secondary Activity with. * @param activityIntent Intent to start the secondary Activity with.
* @param activityOptions ActivityOptions to start the secondary Activity with. * @param activityOptions ActivityOptions to start the secondary Activity with.
* @param windowingMode the windowing mode to set for the TaskFragments.
*/ */
void startActivityToSide(@NonNull WindowContainerTransaction wct, void startActivityToSide(@NonNull WindowContainerTransaction wct,
@NonNull IBinder launchingFragmentToken, @NonNull Rect launchingFragmentBounds, @NonNull IBinder launchingFragmentToken, @NonNull Rect launchingFragmentBounds,
@NonNull Activity launchingActivity, @NonNull IBinder secondaryFragmentToken, @NonNull Activity launchingActivity, @NonNull IBinder secondaryFragmentToken,
@NonNull Rect secondaryFragmentBounds, @NonNull Intent activityIntent, @NonNull Rect secondaryFragmentBounds, @NonNull Intent activityIntent,
@Nullable Bundle activityOptions, @NonNull SplitRule rule) { @Nullable Bundle activityOptions, @NonNull SplitRule rule,
@WindowingMode int windowingMode) {
final IBinder ownerToken = launchingActivity.getActivityToken(); final IBinder ownerToken = launchingActivity.getActivityToken();
// Create or resize the launching TaskFragment. // Create or resize the launching TaskFragment.
if (mFragmentInfos.containsKey(launchingFragmentToken)) { if (mFragmentInfos.containsKey(launchingFragmentToken)) {
resizeTaskFragment(wct, launchingFragmentToken, launchingFragmentBounds); resizeTaskFragment(wct, launchingFragmentToken, launchingFragmentBounds);
wct.setWindowingMode(mFragmentInfos.get(launchingFragmentToken).getToken(),
windowingMode);
} else { } else {
createTaskFragmentAndReparentActivity(wct, launchingFragmentToken, ownerToken, createTaskFragmentAndReparentActivity(wct, launchingFragmentToken, ownerToken,
launchingFragmentBounds, WINDOWING_MODE_MULTI_WINDOW, launchingActivity); launchingFragmentBounds, windowingMode, launchingActivity);
} }
// Create a TaskFragment for the secondary activity. // Create a TaskFragment for the secondary activity.
createTaskFragmentAndStartActivity(wct, secondaryFragmentToken, ownerToken, createTaskFragmentAndStartActivity(wct, secondaryFragmentToken, ownerToken,
secondaryFragmentBounds, WINDOWING_MODE_MULTI_WINDOW, activityIntent, secondaryFragmentBounds, windowingMode, activityIntent,
activityOptions); activityOptions);
// Set adjacent to each other so that the containers below will be invisible. // Set adjacent to each other so that the containers below will be invisible.
@@ -153,6 +157,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
void expandTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) { void expandTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) {
resizeTaskFragment(wct, fragmentToken, new Rect()); resizeTaskFragment(wct, fragmentToken, new Rect());
setAdjacentTaskFragments(wct, fragmentToken, null /* secondary */, null /* splitRule */); setAdjacentTaskFragments(wct, fragmentToken, null /* secondary */, null /* splitRule */);
setWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
} }
/** /**
@@ -255,6 +260,15 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
wct.setBounds(mFragmentInfos.get(fragmentToken).getToken(), bounds); wct.setBounds(mFragmentInfos.get(fragmentToken).getToken(), bounds);
} }
private void setWindowingMode(WindowContainerTransaction wct, IBinder fragmentToken,
@WindowingMode int windowingMode) {
if (!mFragmentInfos.containsKey(fragmentToken)) {
throw new IllegalArgumentException(
"Can't find an existing TaskFragment with fragmentToken=" + fragmentToken);
}
wct.setWindowingMode(mFragmentInfos.get(fragmentToken).getToken(), windowingMode);
}
void deleteTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) { void deleteTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) {
if (!mFragmentInfos.containsKey(fragmentToken)) { if (!mFragmentInfos.containsKey(fragmentToken)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(

View File

@@ -257,9 +257,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (taskContainer == null) { if (taskContainer == null) {
return; return;
} }
final boolean wasInPip = isInPictureInPicture(taskContainer.getConfiguration()); final boolean wasInPip = taskContainer.isInPictureInPicture();
final boolean isInPIp = isInPictureInPicture(config); final boolean isInPIp = isInPictureInPicture(config);
taskContainer.setConfiguration(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;
@@ -278,8 +278,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
* bounds is large enough for at least one split rule. * bounds is large enough for at least one split rule.
*/ */
private void updateAnimationOverride(@NonNull TaskContainer taskContainer) { private void updateAnimationOverride(@NonNull TaskContainer taskContainer) {
if (!taskContainer.isTaskBoundsInitialized()) { if (!taskContainer.isTaskBoundsInitialized()
// We don't know about the Task bounds yet. || !taskContainer.isWindowingModeInitialized()) {
// We don't know about the Task bounds/windowingMode yet.
return; return;
} }
@@ -293,7 +294,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
private boolean supportSplit(@NonNull TaskContainer taskContainer) { private boolean supportSplit(@NonNull TaskContainer taskContainer) {
// No split inside PIP. // No split inside PIP.
if (isInPictureInPicture(taskContainer.getConfiguration())) { if (taskContainer.isInPictureInPicture()) {
return false; return false;
} }
// Check if the parent container bounds can support any split rule. // Check if the parent container bounds can support any split rule.
@@ -461,8 +462,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (!taskContainer.setTaskBounds(taskBounds)) { if (!taskContainer.setTaskBounds(taskBounds)) {
Log.w(TAG, "Can't find bounds from activity=" + activityInTask); Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
} }
updateAnimationOverride(taskContainer);
} }
if (!taskContainer.isWindowingModeInitialized()) {
taskContainer.setWindowingMode(activityInTask.getResources().getConfiguration()
.windowConfiguration.getWindowingMode());
}
updateAnimationOverride(taskContainer);
return container; return container;
} }

View File

@@ -16,10 +16,11 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 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.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect; import android.graphics.Rect;
@@ -111,13 +112,16 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
primaryActivity, primaryRectBounds, null); primaryActivity, primaryRectBounds, null);
// Create new empty task fragment // Create new empty task fragment
final int taskId = primaryContainer.getTaskId();
final TaskFragmentContainer secondaryContainer = mController.newContainer( final TaskFragmentContainer secondaryContainer = mController.newContainer(
null /* activity */, primaryActivity, primaryContainer.getTaskId()); null /* activity */, primaryActivity, taskId);
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
rule, isLtr(primaryActivity, rule)); rule, isLtr(primaryActivity, rule));
final int windowingMode = mController.getTaskContainer(taskId)
.getWindowingModeForSplitTaskFragment(secondaryRectBounds);
createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(), createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
primaryActivity.getActivityToken(), secondaryRectBounds, primaryActivity.getActivityToken(), secondaryRectBounds,
WINDOWING_MODE_MULTI_WINDOW); windowingMode);
secondaryContainer.setLastRequestedBounds(secondaryRectBounds); secondaryContainer.setLastRequestedBounds(secondaryRectBounds);
// Set adjacent to each other so that the containers below will be invisible. // Set adjacent to each other so that the containers below will be invisible.
@@ -173,7 +177,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
createTaskFragment(wct, newContainer.getTaskFragmentToken(), createTaskFragment(wct, newContainer.getTaskFragmentToken(),
launchingActivity.getActivityToken(), new Rect(), WINDOWING_MODE_MULTI_WINDOW); launchingActivity.getActivityToken(), new Rect(), WINDOWING_MODE_UNDEFINED);
applyTransaction(wct); applyTransaction(wct);
return newContainer; return newContainer;
@@ -189,15 +193,17 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
@NonNull Rect bounds, @Nullable TaskFragmentContainer containerToAvoid) { @NonNull Rect bounds, @Nullable TaskFragmentContainer containerToAvoid) {
TaskFragmentContainer container = mController.getContainerWithActivity( TaskFragmentContainer container = mController.getContainerWithActivity(
activity.getActivityToken()); activity.getActivityToken());
final int taskId = container != null ? container.getTaskId() : activity.getTaskId();
final int windowingMode = mController.getTaskContainer(taskId)
.getWindowingModeForSplitTaskFragment(bounds);
if (container == null || container == containerToAvoid) { if (container == null || container == containerToAvoid) {
container = mController.newContainer(activity, activity.getTaskId()); container = mController.newContainer(activity, taskId);
final TaskFragmentCreationParams fragmentOptions = final TaskFragmentCreationParams fragmentOptions =
createFragmentOptions( createFragmentOptions(
container.getTaskFragmentToken(), container.getTaskFragmentToken(),
activity.getActivityToken(), activity.getActivityToken(),
bounds, bounds,
WINDOWING_MODE_MULTI_WINDOW); windowingMode);
wct.createTaskFragment(fragmentOptions); wct.createTaskFragment(fragmentOptions);
wct.reparentActivityToTaskFragment(container.getTaskFragmentToken(), wct.reparentActivityToTaskFragment(container.getTaskFragmentToken(),
@@ -206,6 +212,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
container.setLastRequestedBounds(bounds); container.setLastRequestedBounds(bounds);
} else { } else {
resizeTaskFragmentIfRegistered(wct, container, bounds); resizeTaskFragmentIfRegistered(wct, container, bounds);
updateTaskFragmentWindowingModeIfRegistered(wct, container, windowingMode);
} }
return container; return container;
@@ -237,14 +244,17 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
launchingActivity.getTaskId()); launchingActivity.getTaskId());
} }
final int taskId = primaryContainer.getTaskId();
TaskFragmentContainer secondaryContainer = mController.newContainer(null /* activity */, TaskFragmentContainer secondaryContainer = mController.newContainer(null /* activity */,
launchingActivity, primaryContainer.getTaskId()); launchingActivity, taskId);
final int windowingMode = mController.getTaskContainer(taskId)
.getWindowingModeForSplitTaskFragment(primaryRectBounds);
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer, mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
rule); rule);
startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds, startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
launchingActivity, secondaryContainer.getTaskFragmentToken(), secondaryRectBounds, launchingActivity, secondaryContainer.getTaskFragmentToken(), secondaryRectBounds,
activityIntent, activityOptions, rule); activityIntent, activityOptions, rule, windowingMode);
if (isPlaceholder) { if (isPlaceholder) {
// When placeholder is launched in split, we should keep the focus on the primary. // When placeholder is launched in split, we should keep the focus on the primary.
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken()); wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
@@ -292,6 +302,12 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
// When placeholder is shown in split, we should keep the focus on the primary. // When placeholder is shown in split, we should keep the focus on the primary.
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken()); wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
} }
final TaskContainer taskContainer = mController.getTaskContainer(
updatedContainer.getTaskId());
final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
primaryRectBounds);
updateTaskFragmentWindowingModeIfRegistered(wct, primaryContainer, windowingMode);
updateTaskFragmentWindowingModeIfRegistered(wct, secondaryContainer, windowingMode);
} }
private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct, private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@@ -323,6 +339,15 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
resizeTaskFragment(wct, container.getTaskFragmentToken(), bounds); resizeTaskFragment(wct, container.getTaskFragmentToken(), bounds);
} }
private void updateTaskFragmentWindowingModeIfRegistered(
@NonNull WindowContainerTransaction wct,
@NonNull TaskFragmentContainer container,
@WindowingMode int windowingMode) {
if (container.getInfo() != null) {
wct.setWindowingMode(container.getInfo().getToken(), windowingMode);
}
}
@Override @Override
void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken, void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
@Nullable Rect bounds) { @Nullable Rect bounds) {

View File

@@ -16,9 +16,14 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.res.Configuration; import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.IBinder; import android.os.IBinder;
import android.util.ArraySet; import android.util.ArraySet;
@@ -37,9 +42,9 @@ class TaskContainer {
/** Available window bounds of this Task. */ /** Available window bounds of this Task. */
private final Rect mTaskBounds = new Rect(); private final Rect mTaskBounds = new Rect();
/** Configuration of the Task. */ /** Windowing mode of this Task. */
@Nullable @WindowingMode
private Configuration mConfiguration; private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
/** Active TaskFragments in this Task. */ /** Active TaskFragments in this Task. */
final List<TaskFragmentContainer> mContainers = new ArrayList<>(); final List<TaskFragmentContainer> mContainers = new ArrayList<>();
@@ -81,13 +86,42 @@ class TaskContainer {
return !mTaskBounds.isEmpty(); return !mTaskBounds.isEmpty();
} }
@Nullable void setWindowingMode(int windowingMode) {
Configuration getConfiguration() { mWindowingMode = windowingMode;
return mConfiguration;
} }
void setConfiguration(@Nullable Configuration configuration) { /** Whether the Task windowing mode has been initialized. */
mConfiguration = configuration; boolean isWindowingModeInitialized() {
return mWindowingMode != WINDOWING_MODE_UNDEFINED;
}
/**
* Returns the windowing mode for the TaskFragments below this Task, which should be split with
* other TaskFragments.
*
* @param taskFragmentBounds Requested bounds for the TaskFragment. It will be empty when
* the pair of TaskFragments are stacked due to the limited space.
*/
@WindowingMode
int getWindowingModeForSplitTaskFragment(@Nullable Rect taskFragmentBounds) {
// Only set to multi-windowing mode if the pair are showing side-by-side. Otherwise, it
// will be set to UNDEFINED which will then inherit the Task windowing mode.
if (taskFragmentBounds == null || taskFragmentBounds.isEmpty()) {
return WINDOWING_MODE_UNDEFINED;
}
// We use WINDOWING_MODE_MULTI_WINDOW when the Task is fullscreen.
// However, when the Task is in other multi windowing mode, such as Freeform, we need to
// have the activity windowing mode to match the Task, otherwise things like
// 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;
}
boolean isInPictureInPicture() {
return mWindowingMode == WINDOWING_MODE_PINNED;
} }
/** Whether there is any {@link TaskFragmentContainer} below this Task. */ /** Whether there is any {@link TaskFragmentContainer} below this Task. */

View File

@@ -16,15 +16,23 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
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;
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.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import android.content.res.Configuration;
import android.graphics.Point;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import android.window.TaskFragmentInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -35,6 +43,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
/** /**
* Test class for {@link JetpackTaskFragmentOrganizer}. * Test class for {@link JetpackTaskFragmentOrganizer}.
* *
@@ -47,6 +57,8 @@ import org.mockito.MockitoAnnotations;
public class JetpackTaskFragmentOrganizerTest { public class JetpackTaskFragmentOrganizerTest {
private static final int TASK_ID = 10; private static final int TASK_ID = 10;
@Mock
private WindowContainerTransaction mTransaction;
@Mock @Mock
private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback; private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback;
private JetpackTaskFragmentOrganizer mOrganizer; private JetpackTaskFragmentOrganizer mOrganizer;
@@ -91,4 +103,24 @@ public class JetpackTaskFragmentOrganizerTest {
verify(mOrganizer).unregisterRemoteAnimations(TASK_ID); verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
} }
@Test
public void testExpandTaskFragment() {
final TaskFragmentContainer container = new TaskFragmentContainer(null, TASK_ID);
final TaskFragmentInfo info = createMockInfo(container);
mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
container.setInfo(info);
mOrganizer.expandTaskFragment(mTransaction, container.getTaskFragmentToken());
verify(mTransaction).setWindowingMode(container.getInfo().getToken(),
WINDOWING_MODE_UNDEFINED);
}
private TaskFragmentInfo createMockInfo(TaskFragmentContainer container) {
return new TaskFragmentInfo(container.getTaskFragmentToken(),
mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
false /* isVisible */, new ArrayList<>(), new Point(),
false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */);
}
} }

View File

@@ -16,6 +16,13 @@
package androidx.window.extensions.embedding; package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@@ -63,6 +70,56 @@ public class TaskContainerTest {
assertFalse(taskContainer.setTaskBounds(TASK_BOUNDS)); assertFalse(taskContainer.setTaskBounds(TASK_BOUNDS));
} }
@Test
public void testIsWindowingModeInitialized() {
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
assertFalse(taskContainer.isWindowingModeInitialized());
taskContainer.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
assertTrue(taskContainer.isWindowingModeInitialized());
}
@Test
public void testGetWindowingModeForSplitTaskFragment() {
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
final Rect splitBounds = new Rect(0, 0, 500, 1000);
assertEquals(WINDOWING_MODE_MULTI_WINDOW,
taskContainer.getWindowingModeForSplitTaskFragment(splitBounds));
taskContainer.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
assertEquals(WINDOWING_MODE_MULTI_WINDOW,
taskContainer.getWindowingModeForSplitTaskFragment(splitBounds));
taskContainer.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(WINDOWING_MODE_FREEFORM,
taskContainer.getWindowingModeForSplitTaskFragment(splitBounds));
// Empty bounds means the split pair are stacked, so it should be UNDEFINED which will then
// inherit the Task windowing mode
assertEquals(WINDOWING_MODE_UNDEFINED,
taskContainer.getWindowingModeForSplitTaskFragment(new Rect()));
}
@Test
public void testIsInPictureInPicture() {
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
assertFalse(taskContainer.isInPictureInPicture());
taskContainer.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
assertFalse(taskContainer.isInPictureInPicture());
taskContainer.setWindowingMode(WINDOWING_MODE_PINNED);
assertTrue(taskContainer.isInPictureInPicture());
}
@Test @Test
public void testIsEmpty() { public void testIsEmpty() {
final TaskContainer taskContainer = new TaskContainer(TASK_ID); final TaskContainer taskContainer = new TaskContainer(TASK_ID);