Merge "Fix crash in getParentContainerBounds" into tm-dev
This commit is contained in:
@@ -40,6 +40,7 @@ import android.os.Handler;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.window.TaskFragmentInfo;
|
import android.window.TaskFragmentInfo;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
@@ -59,6 +60,7 @@ import java.util.function.Consumer;
|
|||||||
*/
|
*/
|
||||||
public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
|
public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
|
||||||
ActivityEmbeddingComponent {
|
ActivityEmbeddingComponent {
|
||||||
|
private static final String TAG = "SplitController";
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final SplitPresenter mPresenter;
|
final SplitPresenter mPresenter;
|
||||||
@@ -229,8 +231,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
}
|
}
|
||||||
if (taskContainer.isEmpty()) {
|
if (taskContainer.isEmpty()) {
|
||||||
// Cleanup the TaskContainer if it becomes empty.
|
// Cleanup the TaskContainer if it becomes empty.
|
||||||
mPresenter.stopOverrideSplitAnimation(taskContainer.mTaskId);
|
mPresenter.stopOverrideSplitAnimation(taskContainer.getTaskId());
|
||||||
mTaskContainers.remove(taskContainer.mTaskId);
|
mTaskContainers.remove(taskContainer.getTaskId());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -241,13 +243,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
if (taskContainer == null) {
|
if (taskContainer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean wasInPip = isInPictureInPicture(taskContainer.mConfiguration);
|
final boolean wasInPip = isInPictureInPicture(taskContainer.getConfiguration());
|
||||||
final boolean isInPIp = isInPictureInPicture(config);
|
final boolean isInPIp = isInPictureInPicture(config);
|
||||||
taskContainer.mConfiguration = config;
|
taskContainer.setConfiguration(config);
|
||||||
|
|
||||||
// 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;
|
||||||
if (onTaskBoundsMayChange(taskContainer, config.windowConfiguration.getBounds())
|
if (taskContainer.setTaskBounds(config.windowConfiguration.getBounds())
|
||||||
&& !isInPIp) {
|
&& !isInPIp) {
|
||||||
// We don't care the bounds change when it has already entered PIP.
|
// We don't care the bounds change when it has already entered PIP.
|
||||||
shouldUpdateAnimationOverride = true;
|
shouldUpdateAnimationOverride = true;
|
||||||
@@ -257,16 +259,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns {@code true} if the bounds is changed. */
|
|
||||||
private boolean onTaskBoundsMayChange(@NonNull TaskContainer taskContainer,
|
|
||||||
@NonNull Rect taskBounds) {
|
|
||||||
if (!taskBounds.isEmpty() && !taskContainer.mTaskBounds.equals(taskBounds)) {
|
|
||||||
taskContainer.mTaskBounds.set(taskBounds);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates if we should override transition animation. We only want to override if the Task
|
* Updates if we should override transition animation. We only want to override if the Task
|
||||||
* bounds is large enough for at least one split rule.
|
* bounds is large enough for at least one split rule.
|
||||||
@@ -279,15 +271,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
|
|
||||||
// We only want to override if it supports split.
|
// We only want to override if it supports split.
|
||||||
if (supportSplit(taskContainer)) {
|
if (supportSplit(taskContainer)) {
|
||||||
mPresenter.startOverrideSplitAnimation(taskContainer.mTaskId);
|
mPresenter.startOverrideSplitAnimation(taskContainer.getTaskId());
|
||||||
} else {
|
} else {
|
||||||
mPresenter.stopOverrideSplitAnimation(taskContainer.mTaskId);
|
mPresenter.stopOverrideSplitAnimation(taskContainer.getTaskId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean supportSplit(@NonNull TaskContainer taskContainer) {
|
private boolean supportSplit(@NonNull TaskContainer taskContainer) {
|
||||||
// No split inside PIP.
|
// No split inside PIP.
|
||||||
if (isInPictureInPicture(taskContainer.mConfiguration)) {
|
if (isInPictureInPicture(taskContainer.getConfiguration())) {
|
||||||
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.
|
||||||
@@ -295,7 +287,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
if (!(rule instanceof SplitRule)) {
|
if (!(rule instanceof SplitRule)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mPresenter.shouldShowSideBySide(taskContainer.mTaskBounds, (SplitRule) rule)) {
|
if (mPresenter.shouldShowSideBySide(taskContainer.getTaskBounds(), (SplitRule) rule)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,21 +417,36 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TaskFragmentContainer newContainer(@NonNull Activity activity, int taskId) {
|
||||||
|
return newContainer(activity, activity, taskId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and registers a new organized container with an optional activity that will be
|
* Creates and registers a new organized container with an optional activity that will be
|
||||||
* re-parented to it in a WCT.
|
* re-parented to it in a WCT.
|
||||||
|
*
|
||||||
|
* @param activity the activity that will be reparented to 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.
|
||||||
*/
|
*/
|
||||||
TaskFragmentContainer newContainer(@Nullable Activity activity, int taskId) {
|
TaskFragmentContainer newContainer(@Nullable Activity activity,
|
||||||
|
@NonNull Activity activityInTask, int taskId) {
|
||||||
|
if (activityInTask == null) {
|
||||||
|
throw new IllegalArgumentException("activityInTask must not be null,");
|
||||||
|
}
|
||||||
final TaskFragmentContainer container = new TaskFragmentContainer(activity, taskId);
|
final TaskFragmentContainer container = new TaskFragmentContainer(activity, taskId);
|
||||||
if (!mTaskContainers.contains(taskId)) {
|
if (!mTaskContainers.contains(taskId)) {
|
||||||
mTaskContainers.put(taskId, new TaskContainer(taskId));
|
mTaskContainers.put(taskId, new TaskContainer(taskId));
|
||||||
}
|
}
|
||||||
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
final TaskContainer taskContainer = mTaskContainers.get(taskId);
|
||||||
taskContainer.mContainers.add(container);
|
taskContainer.mContainers.add(container);
|
||||||
if (activity != null && !taskContainer.isTaskBoundsInitialized()
|
if (!taskContainer.isTaskBoundsInitialized()) {
|
||||||
&& onTaskBoundsMayChange(taskContainer,
|
// Get the initial bounds before the TaskFragment has appeared.
|
||||||
SplitPresenter.getTaskBoundsFromActivity(activity))) {
|
final Rect taskBounds = SplitPresenter.getTaskBoundsFromActivity(activityInTask);
|
||||||
// Initial check before any TaskFragment has appeared.
|
if (!taskContainer.setTaskBounds(taskBounds)) {
|
||||||
|
Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
|
||||||
|
}
|
||||||
updateAnimationOverride(taskContainer);
|
updateAnimationOverride(taskContainer);
|
||||||
}
|
}
|
||||||
return container;
|
return container;
|
||||||
@@ -887,6 +894,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
TaskContainer getTaskContainer(int taskId) {
|
||||||
|
return mTaskContainers.get(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if an Activity with the provided component name should always be
|
* Returns {@code true} if an Activity with the provided component name should always be
|
||||||
* expanded to occupy full task bounds. Such activity must not be put in a split.
|
* expanded to occupy full task bounds. Such activity must not be put in a split.
|
||||||
@@ -1211,37 +1223,4 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
|||||||
return configuration != null
|
return configuration != null
|
||||||
&& configuration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED;
|
&& configuration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents TaskFragments and split pairs below a Task. */
|
|
||||||
@VisibleForTesting
|
|
||||||
static class TaskContainer {
|
|
||||||
/** The unique task id. */
|
|
||||||
final int mTaskId;
|
|
||||||
/** Active TaskFragments in this Task. */
|
|
||||||
final List<TaskFragmentContainer> mContainers = new ArrayList<>();
|
|
||||||
/** Active split pairs in this Task. */
|
|
||||||
final List<SplitContainer> mSplitContainers = new ArrayList<>();
|
|
||||||
/**
|
|
||||||
* TaskFragments that the organizer has requested to be closed. They should be removed when
|
|
||||||
* the organizer receives {@link #onTaskFragmentVanished(TaskFragmentInfo)} event for them.
|
|
||||||
*/
|
|
||||||
final Set<IBinder> mFinishedContainer = new ArraySet<>();
|
|
||||||
/** Available window bounds of this Task. */
|
|
||||||
final Rect mTaskBounds = new Rect();
|
|
||||||
/** Configuration of the Task. */
|
|
||||||
@Nullable
|
|
||||||
Configuration mConfiguration;
|
|
||||||
|
|
||||||
TaskContainer(int taskId) {
|
|
||||||
mTaskId = taskId;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isEmpty() {
|
|
||||||
return mContainers.isEmpty() && mFinishedContainer.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isTaskBoundsInitialized() {
|
|
||||||
return !mTaskBounds.isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ package androidx.window.extensions.embedding;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.WindowConfiguration;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -111,8 +111,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
primaryActivity, primaryRectBounds, null);
|
primaryActivity, primaryRectBounds, null);
|
||||||
|
|
||||||
// Create new empty task fragment
|
// Create new empty task fragment
|
||||||
final TaskFragmentContainer secondaryContainer = mController.newContainer(null,
|
final TaskFragmentContainer secondaryContainer = mController.newContainer(
|
||||||
primaryContainer.getTaskId());
|
null /* activity */, primaryActivity, primaryContainer.getTaskId());
|
||||||
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
|
final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
|
||||||
rule, isLtr(primaryActivity, rule));
|
rule, isLtr(primaryActivity, rule));
|
||||||
createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
|
createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
|
||||||
@@ -168,8 +168,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
* Creates a new expanded container.
|
* Creates a new expanded container.
|
||||||
*/
|
*/
|
||||||
TaskFragmentContainer createNewExpandedContainer(@NonNull Activity launchingActivity) {
|
TaskFragmentContainer createNewExpandedContainer(@NonNull Activity launchingActivity) {
|
||||||
final TaskFragmentContainer newContainer = mController.newContainer(null,
|
final TaskFragmentContainer newContainer = mController.newContainer(null /* activity */,
|
||||||
launchingActivity.getTaskId());
|
launchingActivity, launchingActivity.getTaskId());
|
||||||
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
createTaskFragment(wct, newContainer.getTaskFragmentToken(),
|
createTaskFragment(wct, newContainer.getTaskFragmentToken(),
|
||||||
@@ -236,8 +236,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
launchingActivity.getTaskId());
|
launchingActivity.getTaskId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskFragmentContainer secondaryContainer = mController.newContainer(null,
|
TaskFragmentContainer secondaryContainer = mController.newContainer(null /* activity */,
|
||||||
primaryContainer.getTaskId());
|
launchingActivity, primaryContainer.getTaskId());
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
|
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
|
||||||
rule);
|
rule);
|
||||||
@@ -398,20 +398,12 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
|
Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
|
||||||
final Configuration parentConfig = mFragmentParentConfigs.get(
|
final int taskId = container.getTaskId();
|
||||||
container.getTaskFragmentToken());
|
final TaskContainer taskContainer = mController.getTaskContainer(taskId);
|
||||||
if (parentConfig != null) {
|
if (taskContainer == null) {
|
||||||
return parentConfig.windowConfiguration.getBounds();
|
throw new IllegalStateException("Can't find TaskContainer taskId=" + taskId);
|
||||||
}
|
}
|
||||||
|
return taskContainer.getTaskBounds();
|
||||||
// If there is no parent yet - then assuming that activities are running in full task bounds
|
|
||||||
final Activity topActivity = container.getTopNonFinishingActivity();
|
|
||||||
final Rect bounds = topActivity != null ? getParentContainerBounds(topActivity) : null;
|
|
||||||
|
|
||||||
if (bounds == null) {
|
|
||||||
throw new IllegalStateException("Unknown parent bounds");
|
|
||||||
}
|
|
||||||
return bounds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -419,22 +411,19 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
|||||||
final TaskFragmentContainer container = mController.getContainerWithActivity(
|
final TaskFragmentContainer container = mController.getContainerWithActivity(
|
||||||
activity.getActivityToken());
|
activity.getActivityToken());
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
final Configuration parentConfig = mFragmentParentConfigs.get(
|
return getParentContainerBounds(container);
|
||||||
container.getTaskFragmentToken());
|
|
||||||
if (parentConfig != null) {
|
|
||||||
return parentConfig.windowConfiguration.getBounds();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getTaskBoundsFromActivity(activity);
|
return getTaskBoundsFromActivity(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
static Rect getTaskBoundsFromActivity(@NonNull Activity activity) {
|
static Rect getTaskBoundsFromActivity(@NonNull Activity activity) {
|
||||||
|
final WindowConfiguration windowConfiguration =
|
||||||
|
activity.getResources().getConfiguration().windowConfiguration;
|
||||||
if (!activity.isInMultiWindowMode()) {
|
if (!activity.isInMultiWindowMode()) {
|
||||||
// In fullscreen mode the max bounds should correspond to the task bounds.
|
// In fullscreen mode the max bounds should correspond to the task bounds.
|
||||||
return activity.getResources().getConfiguration().windowConfiguration.getMaxBounds();
|
return windowConfiguration.getMaxBounds();
|
||||||
}
|
}
|
||||||
return activity.getResources().getConfiguration().windowConfiguration.getBounds();
|
return windowConfiguration.getBounds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package androidx.window.extensions.embedding;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.window.TaskFragmentInfo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/** Represents TaskFragments and split pairs below a Task. */
|
||||||
|
class TaskContainer {
|
||||||
|
|
||||||
|
/** The unique task id. */
|
||||||
|
private final int mTaskId;
|
||||||
|
|
||||||
|
/** Available window bounds of this Task. */
|
||||||
|
private final Rect mTaskBounds = new Rect();
|
||||||
|
|
||||||
|
/** Configuration of the Task. */
|
||||||
|
@Nullable
|
||||||
|
private Configuration mConfiguration;
|
||||||
|
|
||||||
|
/** Active TaskFragments in this Task. */
|
||||||
|
final List<TaskFragmentContainer> mContainers = new ArrayList<>();
|
||||||
|
|
||||||
|
/** Active split pairs in this Task. */
|
||||||
|
final List<SplitContainer> mSplitContainers = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TaskFragments that the organizer has requested to be closed. They should be removed when
|
||||||
|
* the organizer receives {@link SplitController#onTaskFragmentVanished(TaskFragmentInfo)} event
|
||||||
|
* for them.
|
||||||
|
*/
|
||||||
|
final Set<IBinder> mFinishedContainer = new ArraySet<>();
|
||||||
|
|
||||||
|
TaskContainer(int taskId) {
|
||||||
|
mTaskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getTaskId() {
|
||||||
|
return mTaskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
Rect getTaskBounds() {
|
||||||
|
return mTaskBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns {@code true} if the bounds is changed. */
|
||||||
|
boolean setTaskBounds(@NonNull Rect taskBounds) {
|
||||||
|
if (!taskBounds.isEmpty() && !mTaskBounds.equals(taskBounds)) {
|
||||||
|
mTaskBounds.set(taskBounds);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether the Task bounds has been initialized. */
|
||||||
|
boolean isTaskBoundsInitialized() {
|
||||||
|
return !mTaskBounds.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Configuration getConfiguration() {
|
||||||
|
return mConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setConfiguration(@Nullable Configuration configuration) {
|
||||||
|
mConfiguration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether there is any {@link TaskFragmentContainer} below this Task. */
|
||||||
|
boolean isEmpty() {
|
||||||
|
return mContainers.isEmpty() && mFinishedContainer.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -29,12 +32,12 @@ import static org.mockito.Mockito.never;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.window.TaskFragmentInfo;
|
import android.window.TaskFragmentInfo;
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.window.extensions.embedding.SplitController.TaskContainer;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -53,6 +56,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class SplitControllerTest {
|
public class SplitControllerTest {
|
||||||
private static final int TASK_ID = 10;
|
private static final int TASK_ID = 10;
|
||||||
|
private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Activity mActivity;
|
private Activity mActivity;
|
||||||
@@ -70,8 +74,11 @@ public class SplitControllerTest {
|
|||||||
mSplitPresenter = mSplitController.mPresenter;
|
mSplitPresenter = mSplitController.mPresenter;
|
||||||
spyOn(mSplitController);
|
spyOn(mSplitController);
|
||||||
spyOn(mSplitPresenter);
|
spyOn(mSplitPresenter);
|
||||||
|
final Configuration activityConfig = new Configuration();
|
||||||
|
activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
|
||||||
|
activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
|
||||||
doReturn(mActivityResources).when(mActivity).getResources();
|
doReturn(mActivityResources).when(mActivity).getResources();
|
||||||
doReturn(new Configuration()).when(mActivityResources).getConfiguration();
|
doReturn(activityConfig).when(mActivityResources).getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -117,4 +124,20 @@ public class SplitControllerTest {
|
|||||||
verify(mSplitController).removeContainer(tf);
|
verify(mSplitController).removeContainer(tf);
|
||||||
verify(mActivity, never()).finish();
|
verify(mActivity, never()).finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNewContainer() {
|
||||||
|
// Must pass in a valid activity.
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
mSplitController.newContainer(null /* activity */, TASK_ID));
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
mSplitController.newContainer(mActivity, null /* launchingActivity */, TASK_ID));
|
||||||
|
|
||||||
|
final TaskFragmentContainer tf = mSplitController.newContainer(null, mActivity, TASK_ID);
|
||||||
|
final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
|
||||||
|
|
||||||
|
assertNotNull(tf);
|
||||||
|
assertNotNull(taskContainer);
|
||||||
|
assertEquals(TASK_BOUNDS, taskContainer.getTaskBounds());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package androidx.window.extensions.embedding;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for {@link TaskContainer}.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WMJetpackUnitTests:TaskContainerTest
|
||||||
|
*/
|
||||||
|
@Presubmit
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class TaskContainerTest {
|
||||||
|
private static final int TASK_ID = 10;
|
||||||
|
private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsTaskBoundsInitialized() {
|
||||||
|
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
|
||||||
|
|
||||||
|
assertFalse(taskContainer.isTaskBoundsInitialized());
|
||||||
|
|
||||||
|
taskContainer.setTaskBounds(TASK_BOUNDS);
|
||||||
|
|
||||||
|
assertTrue(taskContainer.isTaskBoundsInitialized());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetTaskBounds() {
|
||||||
|
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
|
||||||
|
|
||||||
|
assertFalse(taskContainer.setTaskBounds(new Rect()));
|
||||||
|
|
||||||
|
assertTrue(taskContainer.setTaskBounds(TASK_BOUNDS));
|
||||||
|
|
||||||
|
assertFalse(taskContainer.setTaskBounds(TASK_BOUNDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsEmpty() {
|
||||||
|
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
|
||||||
|
|
||||||
|
assertTrue(taskContainer.isEmpty());
|
||||||
|
|
||||||
|
final TaskFragmentContainer tf = new TaskFragmentContainer(null, TASK_ID);
|
||||||
|
taskContainer.mContainers.add(tf);
|
||||||
|
|
||||||
|
assertFalse(taskContainer.isEmpty());
|
||||||
|
|
||||||
|
taskContainer.mFinishedContainer.add(tf.getTaskFragmentToken());
|
||||||
|
taskContainer.mContainers.clear();
|
||||||
|
|
||||||
|
assertFalse(taskContainer.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user