summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java66
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java108
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java108
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java267
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java16
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt46
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt46
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt16
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt138
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt146
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt157
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt95
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt104
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml11
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml32
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java7
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java29
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java36
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java131
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java367
27 files changed, 645 insertions, 1323 deletions
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index f0eae97b107e..807e5afae890 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -42,16 +42,4 @@
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
when the PIP menu is shown in center. -->
<string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>
-
- <!-- Gravity of letterboxed apps in portrait screen orientation.
- Can be Gravity.TOP, Gravity.CENTER or Gravity.BOTTOM.
- Any other value will result in runtime exception for a letterboxed activity.
- Default is Gravity.TOP. -->
- <integer name="config_letterboxPortraitGravity">0x00000030</integer>
-
- <!-- Gravity of letterboxed apps in landscape screen orientation.
- Can be Gravity.LEFT, Gravity.CENTER or Gravity.RIGHT.
- Any other value will result in runtime exception for a letterboxed activity.
- Default is Gravity.CENTER. -->
- <integer name="config_letterboxLandscapeGravity">0x00000011</integer>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 4f13b83bc29d..63d31182a748 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -20,8 +20,9 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCR
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import android.app.ActivityManager;
-import android.util.ArraySet;
+import android.graphics.Point;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.SurfaceControl;
import androidx.annotation.NonNull;
@@ -40,7 +41,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
private final SyncTransactionQueue mSyncQueue;
- private final ArraySet<Integer> mTasks = new ArraySet<>();
+ private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
public FullscreenTaskListener(SyncTransactionQueue syncQueue) {
mSyncQueue = syncQueue;
@@ -48,39 +49,44 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
- synchronized (mTasks) {
- if (mTasks.contains(taskInfo.taskId)) {
- throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
- }
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
- taskInfo.taskId);
- mTasks.add(taskInfo.taskId);
- mSyncQueue.runInSync(t -> {
- // Reset several properties back to fullscreen (PiP, for example, leaves all these
- // properties in a bad state).
- t.setWindowCrop(leash, null);
- t.setPosition(leash, 0, 0);
- // TODO(shell-transitions): Eventually set everything in transition so there's no
- // SF Transaction here.
- if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
- t.setAlpha(leash, 1f);
- t.setMatrix(leash, 1, 0, 0, 1);
- t.show(leash);
- }
- });
+ if (mLeashByTaskId.get(taskInfo.taskId) != null) {
+ throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
}
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
+ taskInfo.taskId);
+ mLeashByTaskId.put(taskInfo.taskId, leash);
+ final Point positionInParent = taskInfo.positionInParent;
+ mSyncQueue.runInSync(t -> {
+ // Reset several properties back to fullscreen (PiP, for example, leaves all these
+ // properties in a bad state).
+ t.setWindowCrop(leash, null);
+ t.setPosition(leash, positionInParent.x, positionInParent.y);
+ // TODO(shell-transitions): Eventually set everything in transition so there's no
+ // SF Transaction here.
+ if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
+ t.setAlpha(leash, 1f);
+ t.setMatrix(leash, 1, 0, 0, 1);
+ t.show(leash);
+ }
+ });
+ }
+
+ @Override
+ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+ final Point positionInParent = taskInfo.positionInParent;
+ mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y));
}
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
- synchronized (mTasks) {
- if (!mTasks.remove(taskInfo.taskId)) {
- Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
- return;
- }
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
- taskInfo.taskId);
+ if (mLeashByTaskId.get(taskInfo.taskId) == null) {
+ Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ return;
}
+ mLeashByTaskId.remove(taskInfo.taskId);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
+ taskInfo.taskId);
}
@Override
@@ -88,7 +94,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
final String innerPrefix = prefix + " ";
final String childPrefix = innerPrefix + " ";
pw.println(prefix + this);
- pw.println(innerPrefix + mTasks.size() + " Tasks");
+ pw.println(innerPrefix + mLeashByTaskId.size() + " Tasks");
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
index 45948dd9e800..20850428d3bd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
@@ -16,12 +16,9 @@
package com.android.wm.shell;
-import android.view.Gravity;
-
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
-import com.android.wm.shell.letterbox.LetterboxConfigController;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
@@ -42,7 +39,6 @@ public final class ShellCommandHandler {
private final Optional<HideDisplayCutout> mHideDisplayCutout;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<AppPairs> mAppPairsOptional;
- private final LetterboxConfigController mLetterboxConfigController;
public ShellCommandHandler(
ShellTaskOrganizer shellTaskOrganizer,
@@ -50,15 +46,13 @@ public final class ShellCommandHandler {
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
- Optional<AppPairs> appPairsOptional,
- LetterboxConfigController letterboxConfigController) {
+ Optional<AppPairs> appPairsOptional) {
mShellTaskOrganizer = shellTaskOrganizer;
mSplitScreenOptional = splitScreenOptional;
mPipOptional = pipOptional;
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
mAppPairsOptional = appPairsOptional;
- mLetterboxConfigController = letterboxConfigController;
}
/** Dumps WM Shell internal state. */
@@ -85,14 +79,6 @@ public final class ShellCommandHandler {
return false;
}
switch (args[1]) {
- case "set-letterbox-portrait-gravity":
- return runSetLetterboxPortraitGravity(args, pw);
- case "get-letterbox-portrait-gravity":
- return runGetLetterboxPortraitGravity(pw);
- case "set-letterbox-landscape-gravity":
- return runSetLetterboxLandscapeGravity(args, pw);
- case "get-letterbox-landscape-gravity":
- return runGetLetterboxLandscapeGravity(pw);
case "pair":
return runPair(args, pw);
case "unpair":
@@ -104,92 +90,6 @@ public final class ShellCommandHandler {
}
}
- private boolean runSetLetterboxPortraitGravity(String[] args, PrintWriter pw) {
- if (args.length < 3) {
- // First two arguments are "WMShell" and command name.
- pw.println("Error: reset, TOP, CENTER or BOTTOM should be provided as an argument");
- return true;
- }
- switch (args[2]) {
- case "reset":
- mLetterboxConfigController.resetPortraitGravity();
- break;
- case "TOP":
- mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
- break;
- case "CENTER":
- mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
- break;
- case "BOTTOM":
- mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
- break;
- default:
- pw.println("Error: expected reset, TOP, CENTER or BOTTOM but got " + args[2]);
- }
- return true;
- }
-
- private boolean runGetLetterboxPortraitGravity(PrintWriter pw) {
- final int gravity = mLetterboxConfigController.getPortraitGravity();
- switch (gravity) {
- case Gravity.TOP:
- pw.println("TOP");
- break;
- case Gravity.CENTER:
- pw.println("CENTER");
- break;
- case Gravity.BOTTOM:
- pw.println("BOTTOM");
- break;
- default:
- throw new AssertionError("Unexpected gravity: " + gravity);
- }
- return true;
- }
-
- private boolean runSetLetterboxLandscapeGravity(String[] args, PrintWriter pw) {
- if (args.length < 3) {
- // First two arguments are "WMShell" and command name.
- pw.println("Error: reset, LEFT, CENTER or RIGHT should be provided as an argument");
- return false;
- }
- switch (args[2]) {
- case "reset":
- mLetterboxConfigController.resetLandscapeGravity();
- break;
- case "LEFT":
- mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
- break;
- case "CENTER":
- mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
- break;
- case "RIGHT":
- mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
- break;
- default:
- pw.println(
- "Error: expected reset, LEFT, CENTER or RIGHT but got " + args[2]);
- }
- return true;
- }
-
- private boolean runGetLetterboxLandscapeGravity(PrintWriter pw) {
- final int gravity = mLetterboxConfigController.getLandscapeGravity();
- switch (gravity) {
- case Gravity.LEFT:
- pw.println("LEFT");
- break;
- case Gravity.CENTER:
- pw.println("CENTER");
- break;
- case Gravity.RIGHT:
- pw.println("RIGHT");
- break;
- default:
- throw new AssertionError("Unexpected gravity: " + gravity);
- }
- return true;
- }
private boolean runPair(String[] args, PrintWriter pw) {
if (args.length < 4) {
@@ -220,12 +120,6 @@ public final class ShellCommandHandler {
pw.println(" Print this help text.");
pw.println(" <no arguments provided>");
pw.println(" Dump Window Manager Shell internal state");
- pw.println(" set-letterbox-portrait-gravity [reset|TOP|CENTER|BOTTOM]");
- pw.println(" get-letterbox-portrait-gravity");
- pw.println(" Set, reset or print letterbox gravity for portrait screen mode.");
- pw.println(" set-letterbox-landscape-gravity [reset|LEFT|CENTER|RIGHT]");
- pw.println(" get-letterbox-landscape-gravity");
- pw.println(" Set, reset or print letterbox gravity for landscape screen mode.");
pw.println(" pair <taskId1> <taskId2>");
pw.println(" unpair <taskId>");
pw.println(" Pairs/unpairs tasks with given ids.");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
index 6c08079e586e..f8956030936c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
@@ -17,13 +17,11 @@
package com.android.wm.shell;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
-import com.android.wm.shell.letterbox.LetterboxTaskListener;
import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
@@ -38,7 +36,6 @@ public class ShellInit {
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<AppPairs> mAppPairsOptional;
- private final LetterboxTaskListener mLetterboxTaskListener;
private final FullscreenTaskListener mFullscreenTaskListener;
private final Transitions mTransitions;
@@ -47,7 +44,6 @@ public class ShellInit {
ShellTaskOrganizer shellTaskOrganizer,
Optional<SplitScreen> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
- LetterboxTaskListener letterboxTaskListener,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions) {
mDisplayImeController = displayImeController;
@@ -55,7 +51,6 @@ public class ShellInit {
mShellTaskOrganizer = shellTaskOrganizer;
mSplitScreenOptional = splitScreenOptional;
mAppPairsOptional = appPairsOptional;
- mLetterboxTaskListener = letterboxTaskListener;
mFullscreenTaskListener = fullscreenTaskListener;
mTransitions = transitions;
}
@@ -66,8 +61,6 @@ public class ShellInit {
mDisplayImeController.startMonitorDisplays();
mShellTaskOrganizer.addListenerForType(
- mLetterboxTaskListener, TASK_LISTENER_TYPE_LETTERBOX);
- mShellTaskOrganizer.addListenerForType(
mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
// Register the shell organizer
mShellTaskOrganizer.registerOrganizer();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 62d265aab38f..10cec6d59cbe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -62,14 +62,12 @@ public class ShellTaskOrganizer extends TaskOrganizer {
public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
public static final int TASK_LISTENER_TYPE_PIP = -4;
- public static final int TASK_LISTENER_TYPE_LETTERBOX = -5;
@IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
TASK_LISTENER_TYPE_UNDEFINED,
TASK_LISTENER_TYPE_FULLSCREEN,
TASK_LISTENER_TYPE_MULTI_WINDOW,
TASK_LISTENER_TYPE_PIP,
- TASK_LISTENER_TYPE_LETTERBOX,
})
public @interface TaskListenerType {}
@@ -371,9 +369,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
static @TaskListenerType int taskInfoToTaskListenerType(RunningTaskInfo runningTaskInfo) {
switch (runningTaskInfo.getWindowingMode()) {
case WINDOWING_MODE_FULLSCREEN:
- return runningTaskInfo.letterboxActivityBounds != null
- ? TASK_LISTENER_TYPE_LETTERBOX
- : TASK_LISTENER_TYPE_FULLSCREEN;
+ return TASK_LISTENER_TYPE_FULLSCREEN;
case WINDOWING_MODE_MULTI_WINDOW:
return TASK_LISTENER_TYPE_MULTI_WINDOW;
case WINDOWING_MODE_PINNED:
@@ -389,8 +385,6 @@ public class ShellTaskOrganizer extends TaskOrganizer {
switch (type) {
case TASK_LISTENER_TYPE_FULLSCREEN:
return "TASK_LISTENER_TYPE_FULLSCREEN";
- case TASK_LISTENER_TYPE_LETTERBOX:
- return "TASK_LISTENER_TYPE_LETTERBOX";
case TASK_LISTENER_TYPE_MULTI_WINDOW:
return "TASK_LISTENER_TYPE_MULTI_WINDOW";
case TASK_LISTENER_TYPE_PIP:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 4c70b5d32108..e1a94b071bf4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -123,14 +123,16 @@ public class SplitLayout {
mBounds1.set(mRootBounds);
mBounds2.set(mRootBounds);
if (isLandscape(mRootBounds)) {
+ position += mRootBounds.left;
mDividerBounds.left = position - mDividerInsets;
mDividerBounds.right = mDividerBounds.left + mDividerWindowWidth;
- mBounds1.right = mBounds1.left + position;
+ mBounds1.right = position;
mBounds2.left = mBounds1.right + mDividerSize;
} else {
+ position += mRootBounds.top;
mDividerBounds.top = position - mDividerInsets;
mDividerBounds.bottom = mDividerBounds.top + mDividerWindowWidth;
- mBounds1.bottom = mBounds1.top + position;
+ mBounds1.bottom = position;
mBounds2.top = mBounds1.bottom + mDividerSize;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java
deleted file mode 100644
index 0a549c6aa7d9..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.wm.shell.letterbox;
-
-import android.content.Context;
-import android.view.Gravity;
-
-import com.android.wm.shell.R;
-
-/**
- * Controls access to and overrides of resource config values used by {@link
- * LetterboxTaskOrganizer}.
- */
-public final class LetterboxConfigController {
-
- private final Context mContext;
-
- /** {@link Gravity} of letterboxed apps in portrait screen orientation. */
- private int mLetterboxPortraitGravity;
-
- /** {@link Gravity} of letterboxed apps in landscape screen orientation. */
- private int mLetterboxLandscapeGravity;
-
- public LetterboxConfigController(Context context) {
- mContext = context;
- mLetterboxPortraitGravity =
- mContext.getResources().getInteger(R.integer.config_letterboxPortraitGravity);
- mLetterboxLandscapeGravity =
- mContext.getResources().getInteger(R.integer.config_letterboxLandscapeGravity);
- }
-
- /**
- * Overrides {@link Gravity} of letterboxed apps in portrait screen orientation.
- *
- * @throws IllegalArgumentException if gravity isn't equal to {@link Gravity#TOP}, {@link
- * Gravity#CENTER} or {@link Gravity#BOTTOM}.
- */
- public void setPortraitGravity(int gravity) {
- if (gravity != Gravity.TOP && gravity != Gravity.CENTER && gravity != Gravity.BOTTOM) {
- throw new IllegalArgumentException(
- "Expected Gravity#TOP, Gravity#CENTER or Gravity#BOTTOM but got"
- + gravity);
- }
- mLetterboxPortraitGravity = gravity;
- }
-
- /**
- * Resets {@link Gravity} of letterboxed apps in portrait screen orientation to {@link
- * R.integer.config_letterboxPortraitGravity}.
- */
- public void resetPortraitGravity() {
- mLetterboxPortraitGravity =
- mContext.getResources().getInteger(R.integer.config_letterboxPortraitGravity);
- }
-
- /**
- * Gets {@link Gravity} of letterboxed apps in portrait screen orientation.
- */
- public int getPortraitGravity() {
- return mLetterboxPortraitGravity;
- }
-
- /**
- * Overrides {@link Gravity} of letterboxed apps in landscape screen orientation.
- *
- * @throws IllegalArgumentException if gravity isn't equal to {@link Gravity#RIGHT}, {@link
- * Gravity#CENTER} or {@link Gravity#LEFT}.
- */
- public void setLandscapeGravity(int gravity) {
- if (gravity != Gravity.LEFT && gravity != Gravity.CENTER && gravity != Gravity.RIGHT) {
- throw new IllegalArgumentException(
- "Expected Gravity#LEFT, Gravity#CENTER or Gravity#RIGHT but got"
- + gravity);
- }
- mLetterboxLandscapeGravity = gravity;
- }
-
- /**
- * Resets {@link Gravity} of letterboxed apps in landscape screen orientation to {@link
- * R.integer.config_letterboxLandscapeGravity}.
- */
- public void resetLandscapeGravity() {
- mLetterboxLandscapeGravity =
- mContext.getResources().getInteger(R.integer.config_letterboxLandscapeGravity);
- }
-
- /**
- * Gets {@link Gravity} of letterboxed apps in landscape screen orientation.
- */
- public int getLandscapeGravity() {
- return mLetterboxLandscapeGravity;
- }
-
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java
deleted file mode 100644
index 490ef3296be6..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.wm.shell.letterbox;
-
-import android.app.ActivityManager;
-import android.graphics.Insets;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.Gravity;
-import android.view.SurfaceControl;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.Transitions;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.protolog.ShellProtoLogGroup;
-
-/**
- * Organizes a task in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN} when
- * it's presented in the letterbox mode either because orientations of a top activity and a device
- * don't match or because a top activity is in a size compat mode.
- */
-public class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener {
- private static final String TAG = "LetterboxTaskListener";
-
- private final SyncTransactionQueue mSyncQueue;
- private final LetterboxConfigController mLetterboxConfigController;
- private final WindowManager mWindowManager;
- private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
-
- public LetterboxTaskListener(
- SyncTransactionQueue syncQueue,
- LetterboxConfigController letterboxConfigController,
- WindowManager windowManager) {
- mSyncQueue = syncQueue;
- mLetterboxConfigController = letterboxConfigController;
- mWindowManager = windowManager;
- }
-
- @Override
- public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (mLeashByTaskId.get(taskInfo.taskId) != null) {
- throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
- }
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Appeared: #%d",
- taskInfo.taskId);
- mLeashByTaskId.put(taskInfo.taskId, leash);
- Point positionInParent = new Point();
- Rect crop = new Rect();
- resolveTaskPositionAndCrop(taskInfo, positionInParent, crop);
- mSyncQueue.runInSync(t -> {
- setPositionAndWindowCrop(t, leash, positionInParent, crop);
- if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
- t.setAlpha(leash, 1f);
- t.setMatrix(leash, 1, 0, 0, 1);
- t.show(leash);
- }
- });
- }
-
- @Override
- public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
- if (mLeashByTaskId.get(taskInfo.taskId) == null) {
- Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
- return;
- }
- mLeashByTaskId.remove(taskInfo.taskId);
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Vanished: #%d",
- taskInfo.taskId);
- }
-
- @Override
- public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Changed: #%d",
- taskInfo.taskId);
- final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
- Point positionInParent = new Point();
- Rect crop = new Rect();
- resolveTaskPositionAndCrop(taskInfo, positionInParent, crop);
- mSyncQueue.runInSync(t -> setPositionAndWindowCrop(t, leash, positionInParent, crop));
- }
-
- private static void setPositionAndWindowCrop(
- SurfaceControl.Transaction transaction,
- SurfaceControl leash,
- final Point positionInParent,
- final Rect crop) {
- transaction.setPosition(leash, positionInParent.x, positionInParent.y);
- transaction.setWindowCrop(leash, crop);
- }
-
- // TODO(b/173440321): Correct presentation of letterboxed activities in One-handed mode.
- private void resolveTaskPositionAndCrop(
- ActivityManager.RunningTaskInfo taskInfo,
- Point positionInParent,
- Rect crop) {
- // In screen coordinates
- Rect parentBounds = new Rect(taskInfo.parentBounds);
- // Intersect parent and max bounds. This is required for situations when parent bounds
- // go beyond display bounds, for example, in One-handed mode.
- final Rect maxBounds = taskInfo.getConfiguration().windowConfiguration.getMaxBounds();
- if (!parentBounds.intersect(maxBounds)) {
- Slog.w(TAG, "Task parent and max bounds don't intersect: #" + taskInfo.taskId);
- }
-
- // In screen coordinates
- final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
- final Rect activityBounds = taskInfo.letterboxActivityBounds;
-
- Insets insets = getInsets();
- Rect displayBoundsWithInsets =
- new Rect(mWindowManager.getMaximumWindowMetrics().getBounds());
- displayBoundsWithInsets.inset(insets);
-
- Rect taskBoundsWithInsets = new Rect(taskBounds);
- taskBoundsWithInsets.intersect(displayBoundsWithInsets);
-
- Rect activityBoundsWithInsets = new Rect(activityBounds);
- activityBoundsWithInsets.intersect(displayBoundsWithInsets);
-
- Rect parentBoundsWithInsets = new Rect(parentBounds);
- parentBoundsWithInsets.intersect(displayBoundsWithInsets);
-
- // Crop need to be in the task coordinates.
- crop.set(activityBoundsWithInsets);
- crop.offset(-taskBounds.left, -taskBounds.top);
-
- // Account for insets since coordinates calculations below are done with them.
- positionInParent.x = parentBoundsWithInsets.left - parentBounds.left
- - (taskBoundsWithInsets.left - taskBounds.left);
- positionInParent.y = parentBoundsWithInsets.top - parentBounds.top
- - (taskBoundsWithInsets.top - taskBounds.top);
-
- // Calculating a position of task bounds (without insets) in parent coordinates (without
- // insets) to align activity bounds (without insets) as requested in config. Activity
- // accounts for insets that overlap with its bounds (this overlap can be partial) so
- // ignoring overlap with insets when computing the position. Also, cropping unwanted insets
- // while keeping the top one if the activity is aligned at the top of the window to show
- // status bar decor view.
- if (parentBounds.height() >= parentBounds.width()) {
- final int gravity = mLetterboxConfigController.getPortraitGravity();
- // Center activity horizontally.
- positionInParent.x +=
- (parentBoundsWithInsets.width() - activityBoundsWithInsets.width()) / 2
- + taskBoundsWithInsets.left - activityBoundsWithInsets.left;
- switch (gravity) {
- case Gravity.TOP:
- positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top;
- break;
- case Gravity.CENTER:
- positionInParent.y +=
- taskBoundsWithInsets.top - activityBoundsWithInsets.top
- + (parentBoundsWithInsets.height()
- - activityBoundsWithInsets.height()) / 2;
- break;
- case Gravity.BOTTOM:
- positionInParent.y +=
- parentBoundsWithInsets.height() - activityBoundsWithInsets.bottom
- + taskBoundsWithInsets.top;
- break;
- default:
- throw new AssertionError(
- "Unexpected portrait gravity " + gravity
- + " for task: #" + taskInfo.taskId);
- }
- } else {
- final int gravity = mLetterboxConfigController.getLandscapeGravity();
- // Align activity to the top.
- positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top;
- switch (gravity) {
- case Gravity.LEFT:
- positionInParent.x += taskBoundsWithInsets.left - activityBoundsWithInsets.left;
- break;
- case Gravity.CENTER:
- positionInParent.x +=
- (parentBoundsWithInsets.width() - activityBoundsWithInsets.width()) / 2
- + taskBoundsWithInsets.left - activityBoundsWithInsets.left;
- break;
- case Gravity.RIGHT:
- positionInParent.x +=
- parentBoundsWithInsets.width()
- - activityBoundsWithInsets.right + taskBoundsWithInsets.left;
- break;
- default:
- throw new AssertionError(
- "Unexpected landscape gravity " + gravity
- + " for task: #" + taskInfo.taskId);
- }
- }
-
- // New bounds of the activity after it's repositioned with required gravity.
- Rect newActivityBounds = new Rect(activityBounds);
- // Task's surfce will be repositioned to positionInParent together with the activity
- // inside it so the new activity bounds are the original activity bounds offset by
- // the task's offset.
- newActivityBounds.offset(
- positionInParent.x - taskBounds.left, positionInParent.y - taskBounds.top);
- Rect newActivityBoundsWithInsets = new Rect(newActivityBounds);
- newActivityBoundsWithInsets.intersect(displayBoundsWithInsets);
- // Activity handles insets on its own (e.g. under status bar or navigation bar).
- // crop that is calculated above crops all insets from an activity and below insets that
- // can be shown are added back to the crop bounds (e.g. if activity is still shown at the
- // top of the display then the top inset won't be cropped).
- // After task's surface is repositioned, intersection between an activity and insets can
- // change but if it doesn't, the activity should be shown under insets to maximize visible
- // area.
- // Also, an activity can use area under insets and insets shouldn't be cropped in this case
- // regardless of a position on the screen.
- final Rect activityInsetsFromCore = taskInfo.letterboxActivityInsets;
- if (newActivityBounds.top - newActivityBoundsWithInsets.top
- == activityBounds.top - activityBoundsWithInsets.top
- // Check whether an activity is shown under inset. If it is, then the inset from
- // WM Core and the inset computed here will be different because local insets
- // doesn't take into account visibility of insets requested by the activity.
- || activityBoundsWithInsets.top - activityBounds.top
- != activityInsetsFromCore.top) {
- crop.top -= activityBoundsWithInsets.top - activityBounds.top;
- }
- if (newActivityBounds.bottom - newActivityBoundsWithInsets.bottom
- == activityBounds.bottom - activityBoundsWithInsets.bottom
- || activityBounds.bottom - activityBoundsWithInsets.bottom
- != activityInsetsFromCore.bottom) {
- crop.bottom += activityBounds.bottom - activityBoundsWithInsets.bottom;
- }
- if (newActivityBounds.left - newActivityBoundsWithInsets.left
- == activityBounds.left - activityBoundsWithInsets.left
- || activityBoundsWithInsets.left - activityBounds.left
- != activityInsetsFromCore.left) {
- crop.left -= activityBoundsWithInsets.left - activityBounds.left;
- }
- if (newActivityBounds.right - newActivityBoundsWithInsets.right
- == activityBounds.right - activityBoundsWithInsets.right
- || activityBounds.right - activityBoundsWithInsets.right
- != activityInsetsFromCore.right) {
- crop.right += activityBounds.right - activityBoundsWithInsets.right;
- }
- }
-
- private Insets getInsets() {
- return mWindowManager
- .getMaximumWindowMetrics()
- .getWindowInsets()
- .getInsets(
- WindowInsets.Type.navigationBars()
- | WindowInsets.Type.statusBars()
- | WindowInsets.Type.displayCutout());
- }
-
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
index 3b1e6cbe5ccd..951a68884e11 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java
@@ -75,6 +75,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
@Nullable
OneHandedGestureEventCallback mGestureEventCallback;
private Rect mGestureRegion = new Rect();
+ private boolean mIsStopGesture;
/**
* Constructor of OneHandedGestureHandler, we only handle the gesture of
@@ -153,20 +154,20 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
float distance = (float) Math.hypot(mLastPos.x - mDownPos.x,
mLastPos.y - mDownPos.y);
if (distance > mDragDistThreshold) {
- mGestureEventCallback.onStop();
+ mIsStopGesture = true;
}
}
break;
case MotionEvent.ACTION_UP:
if (mLastPos.y >= mDownPos.y && mPassedSlop) {
mGestureEventCallback.onStart();
+ } else if (mIsStopGesture) {
+ mGestureEventCallback.onStop();
}
- mPassedSlop = false;
- mAllowGesture = false;
+ clearState();
break;
case MotionEvent.ACTION_CANCEL:
- mPassedSlop = false;
- mAllowGesture = false;
+ clearState();
break;
default:
break;
@@ -174,6 +175,11 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
}
}
+ private void clearState() {
+ mPassedSlop = false;
+ mIsStopGesture = false;
+ }
+
private void disposeInputChannel() {
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 1638d72f9914..c5b54bc4abcb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -16,8 +16,10 @@
package com.android.wm.shell.flicker
+import android.graphics.Region
import com.android.server.wm.flicker.dsl.EventLogAssertion
import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.helpers.WindowUtils
@JvmOverloads
fun LayersAssertion.appPairsDividerIsVisible(
@@ -59,6 +61,50 @@ fun LayersAssertion.dockedStackDividerIsInvisible(
}
}
+@JvmOverloads
+fun LayersAssertion.dockedStackPrimaryBoundsIsVisible(
+ rotation: Int,
+ primaryLayerName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ end("PrimaryAppBounds", bugId, enabled) {
+ val entry = this.trace.entries.firstOrNull()
+ ?: throw IllegalStateException("Trace is empty")
+ val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER)
+ this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.dockedStackSecondaryBoundsIsVisible(
+ rotation: Int,
+ secondaryLayerName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ end("SecondaryAppBounds", bugId, enabled) {
+ val entry = this.trace.entries.firstOrNull()
+ ?: throw IllegalStateException("Trace is empty")
+ val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER)
+ this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+ }
+}
+
+fun getPrimaryRegion(dividerRegion: Region, rotation: Int): Region {
+ val displayBounds = WindowUtils.getDisplayBounds(rotation)
+ return Region(0, 0, displayBounds.getBounds().right,
+ dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset)
+}
+
+fun getSecondaryRegion(dividerRegion: Region, rotation: Int): Region {
+ val displayBounds = WindowUtils.getDisplayBounds(rotation)
+ return Region(0,
+ dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset,
+ displayBounds.getBounds().right,
+ displayBounds.getBounds().bottom - WindowUtils.navigationBarHeight)
+}
+
fun EventLogAssertion.focusChanges(
vararg windows: String,
bugId: Int = 0,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 96234fcc8570..5125a3972cf4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -37,3 +37,4 @@ const val TEST_APP_FIXED_ACTIVITY_LABEL = "FixedApp"
// Test App > SplitScreen Activity
const val TEST_APP_SPLITSCREEN_PRIMARY_LABEL = "SplitScreenPrimaryApp"
const val TEST_APP_SPLITSCREEN_SECONDARY_LABEL = "SplitScreenSecondaryApp"
+const val TEST_APP_NONRESIZEABLE_LABEL = "NonResizeableApp"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
index 0f8d30a94ec6..379ec95b6792 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
@@ -61,10 +61,9 @@ class AppPairsTest(
setup {
eachRun {
uiDevice.wakeUpAndGoToHomeScreen()
- primaryApp.open()
- uiDevice.pressHome()
- secondaryApp.open()
- uiDevice.pressHome()
+ primaryApp.launchViaIntent()
+ secondaryApp.launchViaIntent()
+ nonResizeableApp.launchViaIntent()
updateTaskId()
}
}
@@ -90,7 +89,7 @@ class AppPairsTest(
@Test
fun testAppPairs_pairPrimaryAndSecondaryApps() {
- val testTag = "testAppPaired_pairPrimaryAndSecondary"
+ val testTag = "testAppPairs_pairPrimaryAndSecondaryApps"
runWithFlicker(appPairsSetup) {
withTestName { testTag }
repeat {
@@ -176,6 +175,36 @@ class AppPairsTest(
}
}
+ @Test
+ fun testAppPairs_canNotPairNonResizeableApps() {
+ val testTag = "testAppPairs_canNotPairNonResizeableApps"
+ runWithFlicker(appPairsSetup) {
+ withTestName { testTag }
+ repeat {
+ TEST_REPETITIONS
+ }
+ transitions {
+ nonResizeableApp.launchViaIntent()
+ // TODO pair apps through normal UX flow
+ executeShellCommand(composePairsCommand(
+ primaryTaskId, nonResizeableTaskId, true /* pair */))
+ SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
+ }
+ assertions {
+ layersTrace {
+ appPairsDividerIsInvisible()
+ }
+ windowManagerTrace {
+ end {
+ showsAppWindow(nonResizeableApp.defaultWindowName)
+ .and()
+ .hidesAppWindow(primaryApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
private fun composePairsCommand(
primaryApp: String,
secondaryApp: String,
@@ -202,6 +231,7 @@ class AppPairsTest(
private fun updateTaskId() {
val primaryAppComponent = primaryApp.openAppIntent.component
val secondaryAppComponent = secondaryApp.openAppIntent.component
+ val nonResizeableAppComponent = nonResizeableApp.openAppIntent.component
if (primaryAppComponent != null) {
primaryTaskId = appPairsHelper.getTaskIdForActivity(
primaryAppComponent.packageName, primaryAppComponent.className).toString()
@@ -210,11 +240,17 @@ class AppPairsTest(
secondaryTaskId = appPairsHelper.getTaskIdForActivity(
secondaryAppComponent.packageName, secondaryAppComponent.className).toString()
}
+ if (nonResizeableAppComponent != null) {
+ nonResizeableTaskId = appPairsHelper.getTaskIdForActivity(
+ nonResizeableAppComponent.packageName,
+ nonResizeableAppComponent.className).toString()
+ }
}
companion object {
var primaryTaskId = ""
var secondaryTaskId = ""
+ var nonResizeableTaskId = ""
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt
index f32cd8842074..4d46f2856704 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt
@@ -17,6 +17,7 @@
package com.android.wm.shell.flicker.apppairs
import com.android.wm.shell.flicker.NonRotationTestBase
+import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL
import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL
import com.android.wm.shell.flicker.helpers.AppPairsHelper
@@ -36,4 +37,7 @@ abstract class AppPairsTestBase(
protected val secondaryApp = SplitScreenHelper(instrumentation,
TEST_APP_SPLITSCREEN_SECONDARY_LABEL,
Components.SplitScreenSecondaryActivity())
+ protected val nonResizeableApp = SplitScreenHelper(instrumentation,
+ TEST_APP_NONRESIZEABLE_LABEL,
+ Components.NonResizeableActivity())
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index e67fc97dad2e..fb795c72b106 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -17,9 +17,7 @@
package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
-import android.graphics.Region
import android.os.SystemClock
-import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.wm.shell.flicker.testapp.Components
class SplitScreenHelper(
@@ -43,20 +41,6 @@ class SplitScreenHelper(
SystemClock.sleep(TIMEOUT_MS)
}
- fun getPrimaryBounds(dividerBounds: Region): android.graphics.Region {
- val primaryAppBounds = Region(0, 0, dividerBounds.bounds.right,
- dividerBounds.bounds.bottom + WindowUtils.dockedStackDividerInset)
- return primaryAppBounds
- }
-
- fun getSecondaryBounds(dividerBounds: Region): android.graphics.Region {
- val displayBounds = WindowUtils.displayBounds
- val secondaryAppBounds = Region(0,
- dividerBounds.bounds.bottom - WindowUtils.dockedStackDividerInset,
- displayBounds.right, displayBounds.bottom - WindowUtils.navigationBarHeight)
- return secondaryAppBounds
- }
-
companion object {
const val TEST_REPETITIONS = 1
const val TIMEOUT_MS = 3_000L
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
index 5570a562a515..348676189524 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
@@ -21,14 +21,23 @@ import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.canSplitScreen
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickstep
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
import com.android.wm.shell.flicker.dockedStackDividerIsVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
+import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -56,14 +65,16 @@ class EnterSplitScreenTest(
setup {
eachRun {
uiDevice.wakeUpAndGoToHomeScreen()
- splitScreenApp.open()
- uiDevice.pressHome()
}
}
teardown {
eachRun {
+ if (uiDevice.isInSplitScreen()) {
+ uiDevice.exitSplitScreen()
+ }
splitScreenApp.exit()
secondaryApp.exit()
+ nonResizeableApp.exit()
}
}
assertions {
@@ -87,18 +98,14 @@ class EnterSplitScreenTest(
TEST_REPETITIONS
}
transitions {
+ splitScreenApp.launchViaIntent()
uiDevice.launchSplitScreen()
}
assertions {
layersTrace {
dockedStackDividerIsVisible()
- end("appsEndingBounds", enabled = false) {
- val entry = this.trace.entries.firstOrNull()
- ?: throw IllegalStateException("Trace is empty")
- this.hasVisibleRegion(splitScreenApp.defaultWindowName,
- splitScreenApp.getPrimaryBounds(
- entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
- }
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
}
windowManagerTrace {
end {
@@ -118,27 +125,18 @@ class EnterSplitScreenTest(
TEST_REPETITIONS
}
transitions {
- secondaryApp.open()
- uiDevice.pressHome()
- splitScreenApp.open()
- uiDevice.pressHome()
+ secondaryApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
uiDevice.launchSplitScreen()
splitScreenApp.reopenAppFromOverview()
}
assertions {
layersTrace {
dockedStackDividerIsVisible()
- end("appsEndingBounds", enabled = false) {
- val entry = this.trace.entries.firstOrNull()
- ?: throw IllegalStateException("Trace is empty")
- this.hasVisibleRegion(splitScreenApp.defaultWindowName,
- splitScreenApp.getPrimaryBounds(
- entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
- .and()
- .hasVisibleRegion(secondaryApp.defaultWindowName,
- splitScreenApp.getSecondaryBounds(
- entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
- }
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackSecondaryBoundsIsVisible(
+ rotation, secondaryApp.defaultWindowName, 169271943)
}
windowManagerTrace {
end {
@@ -150,6 +148,98 @@ class EnterSplitScreenTest(
}
}
+ @Test
+ fun testNonResizeableNotDocked() {
+ val testTag = "testNonResizeableNotDocked"
+ runWithFlicker(splitScreenSetup) {
+ withTestName { testTag }
+ repeat {
+ TEST_REPETITIONS
+ }
+ transitions {
+ nonResizeableApp.launchViaIntent()
+ uiDevice.openQuickstep()
+ if (uiDevice.canSplitScreen()) {
+ Assert.fail("Non-resizeable app should not enter split screen")
+ }
+ }
+ assertions {
+ layersTrace {
+ dockedStackDividerIsInvisible()
+ }
+ windowManagerTrace {
+ end {
+ hidesAppWindow(nonResizeableApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testNonResizeableWhenAlreadyInSplitScreenPrimary() {
+ val testTag = "testNonResizeableWhenAlreadyInSplitScreenPrimary"
+ runWithFlicker(splitScreenSetup) {
+ withTestName { testTag }
+ repeat {
+ TEST_REPETITIONS
+ }
+ transitions {
+ nonResizeableApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
+ uiDevice.launchSplitScreen()
+ nonResizeableApp.reopenAppFromOverview()
+ }
+ assertions {
+ layersTrace {
+ dockedStackDividerIsInvisible()
+ end("appsEndingBounds", enabled = false) {
+ val displayBounds = WindowUtils.getDisplayBounds(rotation)
+ this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds)
+ }
+ }
+ windowManagerTrace {
+ end {
+ showsAppWindow(nonResizeableApp.defaultWindowName)
+ hidesAppWindow(splitScreenApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testNonResizeableWhenAlreadyInSplitScreenSecondary() {
+ val testTag = "testNonResizeableWhenAlreadyInSplitScreenSecondary"
+ runWithFlicker(splitScreenSetup) {
+ withTestName { testTag }
+ repeat {
+ TEST_REPETITIONS
+ }
+ transitions {
+ splitScreenApp.launchViaIntent()
+ uiDevice.launchSplitScreen()
+ uiDevice.pressBack()
+ nonResizeableApp.launchViaIntent()
+ }
+ assertions {
+ layersTrace {
+ dockedStackDividerIsInvisible()
+ end("appsEndingBounds", enabled = false) {
+ val displayBounds = WindowUtils.getDisplayBounds(rotation)
+ this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds)
+ }
+ }
+ windowManagerTrace {
+ end {
+ showsAppWindow(nonResizeableApp.defaultWindowName)
+ hidesAppWindow(splitScreenApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt
new file mode 100644
index 000000000000..be8f9bcdedb6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2020 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 com.android.wm.shell.flicker.splitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RotateOneLaunchedAppTest(
+ rotationName: String,
+ rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+ private val splitScreenRotationSetup: FlickerBuilder
+ get() = FlickerBuilder(instrumentation).apply {
+ val testSetupRotation = "testSetupRotation"
+ withTestName {
+ testSetupRotation
+ }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ }
+ teardown {
+ eachRun {
+ if (uiDevice.isInSplitScreen()) {
+ uiDevice.exitSplitScreen()
+ }
+ setRotation(Surface.ROTATION_0)
+ splitScreenApp.exit()
+ secondaryApp.exit()
+ }
+ }
+ }
+
+ @Test
+ fun testRotateInSplitScreenMode() {
+ val testTag = "testEnterSplitScreen_launchToSide"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ splitScreenApp.launchViaIntent()
+ device.launchSplitScreen()
+ setRotation(rotation)
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testRotateAndEnterSplitScreenMode() {
+ val testTag = "testRotateAndEnterSplitScreenMode"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ splitScreenApp.launchViaIntent()
+ setRotation(rotation)
+ device.launchSplitScreen()
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt
new file mode 100644
index 000000000000..2e05c2a99273
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2020 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 com.android.wm.shell.flicker.splitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RotateTwoLaunchedAppTest(
+ rotationName: String,
+ rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+ private val splitScreenRotationSetup: FlickerBuilder
+ get() = FlickerBuilder(instrumentation).apply {
+ val testSetupRotation = "testSetupRotation"
+ withTestName {
+ testSetupRotation
+ }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ }
+ teardown {
+ eachRun {
+ if (uiDevice.isInSplitScreen()) {
+ uiDevice.exitSplitScreen()
+ }
+ setRotation(Surface.ROTATION_0)
+ splitScreenApp.exit()
+ secondaryApp.exit()
+ }
+ }
+ }
+
+ @Test
+ fun testRotateInSplitScreenMode() {
+ val testTag = "testRotateInSplitScreenMode"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ secondaryApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
+ device.launchSplitScreen()
+ splitScreenApp.reopenAppFromOverview()
+ setRotation(rotation)
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackSecondaryBoundsIsVisible(
+ rotation, secondaryApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ .and().showsAppWindow(secondaryApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testRotateAndEnterSplitScreenMode() {
+ val testTag = "testRotateAndEnterSplitScreenMode"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ secondaryApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
+ setRotation(rotation)
+ device.launchSplitScreen()
+ splitScreenApp.reopenAppFromOverview()
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackSecondaryBoundsIsVisible(
+ rotation, secondaryApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ .and().showsAppWindow(secondaryApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt
deleted file mode 100644
index d2371bd766f5..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.wm.shell.flicker.splitscreen
-
-import androidx.test.filters.FlakyTest
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenRotateOneLaunchedAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest
-class SplitScreenRotateOneLaunchedAppTest(
- testName: String,
- flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
- companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): Collection<Array<Any>> {
- val instrumentation = InstrumentationRegistry.getInstrumentation()
- val testApp = StandardAppHelper(instrumentation,
- "com.android.wm.shell.flicker.testapp", "SimpleApp")
-
- return FlickerTestRunnerFactory(instrumentation, repetitions = 3)
- .buildTest { configuration ->
- withTestName {
- buildTestTag("splitScreenRotateOneApp", testApp, configuration)
- }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- testApp.open()
- device.launchSplitScreen()
- device.waitForIdle()
- }
- eachRun {
- this.setRotation(configuration.startRotation)
- }
- }
- teardown {
- eachRun {
- setRotation(Surface.ROTATION_0)
- }
- test {
- testApp.exit()
- if (device.isInSplitScreen()) {
- device.exitSplitScreen()
- }
- }
- }
- transitions {
- this.setRotation(configuration.endRotation)
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt
deleted file mode 100644
index 67346424acd2..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.wm.shell.flicker.splitscreen
-
-import androidx.test.filters.FlakyTest
-import android.view.Surface
-import androidx.test.filters.RequiresDevice
-import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.Flicker
-import com.android.server.wm.flicker.FlickerTestRunner
-import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.helpers.StandardAppHelper
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenRotateTwoLaunchedAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest
-class SplitScreenRotateTwoLaunchedAppTest(
- testName: String,
- flickerSpec: Flicker
-) : FlickerTestRunner(testName, flickerSpec) {
- companion object {
- @Parameterized.Parameters(name = "{0}")
- @JvmStatic
- fun getParams(): Collection<Array<Any>> {
- val instrumentation = InstrumentationRegistry.getInstrumentation()
- val testApp = StandardAppHelper(instrumentation,
- "com.android.wm.shell.flicker.testapp", "SimpleApp")
- val secondaryApp = StandardAppHelper(instrumentation,
- "com.android.wm.shell.flicker.testapp",
- "SplitScreenSecondaryApp")
-
- return FlickerTestRunnerFactory(instrumentation, repetitions = 3)
- .buildTest { configuration ->
- withTestName {
- buildTestTag("splitScreenRotateTwoApps", testApp, configuration)
- }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- testApp.open()
- device.pressHome()
- secondaryApp.open()
- device.pressHome()
- device.launchSplitScreen()
- device.reopenAppFromOverview()
- device.waitForIdle()
- }
- eachRun {
- this.setRotation(configuration.startRotation)
- }
- }
- teardown {
- eachRun {
- setRotation(Surface.ROTATION_0)
- }
- test {
- testApp.exit()
- secondaryApp.exit()
- if (device.isInSplitScreen()) {
- device.exitSplitScreen()
- }
- }
- }
- transitions {
- this.setRotation(configuration.endRotation)
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
index a3440df9ddf8..42c509d6eba8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
@@ -17,6 +17,7 @@
package com.android.wm.shell.flicker.splitscreen
import com.android.wm.shell.flicker.NonRotationTestBase
+import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL
import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
@@ -32,4 +33,7 @@ abstract class SplitScreenTestBase(
protected val secondaryApp = SplitScreenHelper(instrumentation,
TEST_APP_SPLITSCREEN_SECONDARY_LABEL,
Components.SplitScreenSecondaryActivity())
+ protected val nonResizeableApp = SplitScreenHelper(instrumentation,
+ TEST_APP_NONRESIZEABLE_LABEL,
+ Components.NonResizeableActivity())
}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
index a583b725899b..28ed3431db62 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
@@ -86,6 +86,17 @@
</intent-filter>
</activity>
+ <activity android:name=".NonResizeableActivity"
+ android:resizeableActivity="false"
+ android:taskAffinity="com.android.wm.shell.flicker.testapp.NonResizeableActivity"
+ android:label="NonResizeableApp"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+
<activity android:name=".SimpleActivity"
android:taskAffinity="com.android.wm.shell.flicker.testapp.SimpleActivity"
android:label="SimpleApp"
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
new file mode 100644
index 000000000000..45d5917f86d6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@android:color/holo_orange_light">
+
+ <TextView
+ android:id="@+id/NonResizeableTest"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center_vertical|center_horizontal"
+ android:text="NonResizeableActivity"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+
+</LinearLayout>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
index 8e9b4cb2d53e..f729ea554072 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java
@@ -38,6 +38,13 @@ public class Components {
}
}
+ public static class NonResizeableActivity extends ComponentsInfo {
+ @Override
+ public String getActivityName() {
+ return NonResizeableActivity.class.getSimpleName();
+ }
+ }
+
public static class PipActivity extends ComponentsInfo {
// Intent action that this activity dynamically registers to enter picture-in-picture
public static final String ACTION_ENTER_PIP = PACKAGE_NAME + ".PipActivity.ENTER_PIP";
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java
new file mode 100644
index 000000000000..24275e002c7f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 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 com.android.wm.shell.flicker.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class NonResizeableActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.activity_non_resizeable);
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 3ff750af7ec9..862776ec7df2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -16,18 +16,14 @@
package com.android.wm.shell;
-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 com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -38,7 +34,6 @@ import static org.mockito.Mockito.verify;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.pm.ParceledListSlice;
-import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -47,7 +42,6 @@ import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.TaskAppearedInfo;
-import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -263,28 +257,6 @@ public class ShellTaskOrganizerTests {
assertTrue(mwListener.appeared.contains(task2));
}
- @Test
- public void testTaskInfoToTaskListenerType_whenLetterboxBoundsPassed_returnsLetterboxType() {
- RunningTaskInfo taskInfo = createTaskInfo(
- /* taskId */ 1,
- WINDOWING_MODE_FULLSCREEN,
- /* letterboxActivityBounds */ new Rect(1, 1, 1, 1));
-
- assertEquals(
- ShellTaskOrganizer.taskInfoToTaskListenerType(taskInfo),
- TASK_LISTENER_TYPE_LETTERBOX);
- }
-
- @Test
- public void testTaskInfoToTaskListenerType_whenLetterboxBoundsIsNull_returnsFullscreenType() {
- RunningTaskInfo taskInfo = createTaskInfo(
- /* taskId */ 1, WINDOWING_MODE_FULLSCREEN, /* letterboxActivityBounds */ null);
-
- assertEquals(
- ShellTaskOrganizer.taskInfoToTaskListenerType(taskInfo),
- TASK_LISTENER_TYPE_FULLSCREEN);
- }
-
private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
taskInfo.taskId = taskId;
@@ -292,12 +264,4 @@ public class ShellTaskOrganizerTests {
return taskInfo;
}
- private static RunningTaskInfo createTaskInfo(
- int taskId, int windowingMode, @Nullable Rect letterboxActivityBounds) {
- RunningTaskInfo taskInfo = new RunningTaskInfo();
- taskInfo.taskId = taskId;
- taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
- taskInfo.letterboxActivityBounds = Rect.copyOrNull(letterboxActivityBounds);
- return taskInfo;
- }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java
deleted file mode 100644
index 29233366d4f3..000000000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.wm.shell.letterbox;
-
-import static org.junit.Assert.assertEquals;
-
-import android.view.Gravity;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.R;
-import com.android.wm.shell.ShellTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for {@link LetterboxConfigController}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class LetterboxConfigControllerTest extends ShellTestCase {
-
- private LetterboxConfigController mLetterboxConfigController;
-
- @Before
- public void setUp() {
- mLetterboxConfigController = new LetterboxConfigController(getContext());
- }
-
- @Test
- public void testGetPortraitGravity_noOverrides_returnConfigValue() {
- assertEquals(
- mLetterboxConfigController.getPortraitGravity(),
- getContext().getResources().getInteger(R.integer.config_letterboxPortraitGravity));
- }
-
- @Test
- public void testGetLandscapeGravity_noOverrides_returnConfigValue() {
- assertEquals(
- mLetterboxConfigController.getLandscapeGravity(),
- getContext().getResources().getInteger(R.integer.config_letterboxLandscapeGravity));
- }
-
- @Test
- public void testSetPortraitGravity_validValue_savesValue() {
- mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
- assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.BOTTOM);
-
- mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
- assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.CENTER);
-
- mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
- assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.TOP);
- }
-
- @Test
- public void testSetLandscapeGravity_validValue_savesValue() {
- mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
- assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.LEFT);
-
- mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
- assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.CENTER);
-
- mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
- assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.RIGHT);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSetPortraitGravity_invalidValue_throwsException() {
- mLetterboxConfigController.setPortraitGravity(Gravity.RIGHT);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSetLandscapeGravity_invalidValue_throwsException() {
- mLetterboxConfigController.setLandscapeGravity(Gravity.TOP);
- }
-
- @Test
- public void testResetPortraitGravity() {
- int defaultGravity =
- getContext().getResources().getInteger(R.integer.config_letterboxPortraitGravity);
-
- mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
- mLetterboxConfigController.resetPortraitGravity();
- assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity);
-
- mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
- mLetterboxConfigController.resetPortraitGravity();
- assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity);
-
- mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
- mLetterboxConfigController.resetPortraitGravity();
- assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity);
- }
-
- @Test
- public void testResetLandscapeGravity() {
- int defaultGravity =
- getContext().getResources().getInteger(R.integer.config_letterboxLandscapeGravity);
-
- mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
- mLetterboxConfigController.resetLandscapeGravity();
- assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity);
-
- mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
- mLetterboxConfigController.resetLandscapeGravity();
- assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity);
-
- mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
- mLetterboxConfigController.resetLandscapeGravity();
- assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity);
- }
-
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java
deleted file mode 100644
index 5cbc7d927d61..000000000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.wm.shell.letterbox;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.graphics.Insets;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.Gravity;
-import android.view.SurfaceControl;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.WindowMetrics;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.common.TransactionPool;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link LetterboxTaskListener}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class LetterboxTaskListenerTest extends ShellTestCase {
-
- @Mock private SurfaceControl mLeash;
- @Mock private SurfaceControl.Transaction mTransaction;
- @Mock private WindowManager mWindowManager;
- @Mock private WindowMetrics mWindowMetrics;
- @Mock private WindowInsets mWindowInsets;
- private LetterboxTaskListener mLetterboxTaskListener;
- private LetterboxConfigController mLetterboxConfigController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mLetterboxConfigController = new LetterboxConfigController(getContext());
- mLetterboxTaskListener = new LetterboxTaskListener(
- new SyncTransactionQueue(
- new TransactionPool() {
- @Override
- public SurfaceControl.Transaction acquire() {
- return mTransaction;
- }
-
- @Override
- public void release(SurfaceControl.Transaction t) {
- }
- },
- new Handler(Looper.getMainLooper())),
- mLetterboxConfigController,
- mWindowManager);
-
- when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics);
- when(mWindowMetrics.getWindowInsets()).thenReturn(mWindowInsets);
- }
-
- @Test
- public void testOnTaskInfoChanged_updatesPositionAndCrop() {
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- Insets.NONE);
-
- mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 200, 100),
- /* activityBounds */ new Rect(75, 0, 125, 75),
- /* taskBounds */ new Rect(50, 0, 125, 100),
- /* activityInsets */ new Rect(0, 0, 0, 0)),
- mLeash);
-
- // Task doesn't need to repositioned
- verifySetPosition(50, 0);
- // Should return activity coordinates offset by task coordinates
- verifySetWindowCrop(new Rect(25, 0, 75, 75));
-
- mLetterboxTaskListener.onTaskInfoChanged(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 200, 100),
- // Activity is offset by 25 to the left
- /* activityBounds */ new Rect(50, 0, 100, 75),
- /* taskBounds */ new Rect(50, 0, 125, 100),
- /* activityInsets */ new Rect(0, 0, 0, 0)));
-
- // Task needs to be repositioned by 25 to the left
- verifySetPosition(75, 0);
- // Should return activity coordinates offset by task coordinates
- verifySetWindowCrop(new Rect(0, 0, 50, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_landscapeWithLeftGravity() {
- mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 200, 100),
- /* activityBounds */ new Rect(150, 0, 200, 75),
- /* taskBounds */ new Rect(125, 0, 200, 100),
- /* activityInsets */ new Rect(0, 10, 10, 0)),
- mLeash);
-
- verifySetPosition(-15, 0);
- // Should return activity coordinates offset by task coordinates minus unwanted right inset
- verifySetWindowCrop(new Rect(25, 0, 65, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_landscapeWithCenterGravity() {
- mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 200, 100),
- /* activityBounds */ new Rect(150, 0, 200, 75),
- /* taskBounds */ new Rect(125, 0, 200, 100),
- /* activityInsets */ new Rect(0, 10, 10, 0)),
- mLeash);
-
- verifySetPosition(55, 0);
- // Should return activity coordinates offset by task coordinates minus unwanted right inset
- verifySetWindowCrop(new Rect(25, 0, 65, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_landscapeWithRightGravity() {
- mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 200, 100),
- /* activityBounds */ new Rect(50, 0, 100, 75),
- /* taskBounds */ new Rect(25, 0, 100, 100),
- /* activityInsets */ new Rect(0, 10, 10, 0)),
- mLeash);
-
- verifySetPosition(115, 0);
- // Should return activity coordinates offset by task coordinates
- verifySetWindowCrop(new Rect(25, 0, 75, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_portraitWithTopGravity() {
- mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 100, 150),
- /* activityBounds */ new Rect(0, 75, 50, 125),
- /* taskBounds */ new Rect(0, 50, 100, 125),
- /* activityInsets */ new Rect(10, 0, 0, 0)),
- mLeash);
-
- verifySetPosition(20, -15);
- // Should return activity coordinates offset by task coordinates minus unwanted left inset
- verifySetWindowCrop(new Rect(10, 25, 50, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_portraitWithCenterGravity() {
- mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 100, 150),
- /* activityBounds */ new Rect(0, 75, 50, 125),
- /* taskBounds */ new Rect(0, 50, 100, 125),
- /* activityInsets */ new Rect(10, 0, 0, 0)),
- mLeash);
-
- verifySetPosition(20, 20);
- // Should return activity coordinates offset by task coordinates minus unwanted left inset
- verifySetWindowCrop(new Rect(10, 25, 50, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_portraitWithCenterGravity_visibleLeftInset() {
- mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 100, 150),
- /* activityBounds */ new Rect(0, 75, 50, 125),
- /* taskBounds */ new Rect(0, 50, 100, 125),
- // Activity is drawn under the left inset.
- /* activityInsets */ new Rect(0, 0, 0, 0)),
- mLeash);
-
- verifySetPosition(20, 20);
- // Should return activity coordinates offset by task coordinates
- verifySetWindowCrop(new Rect(0, 25, 50, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_portraitWithBottomGravity() {
- mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 100, 150),
- /* activityBounds */ new Rect(0, 75, 50, 125),
- /* taskBounds */ new Rect(0, 50, 100, 125),
- /* activityInsets */ new Rect(10, 0, 0, 0)),
- mLeash);
-
- verifySetPosition(20, 55);
- // Should return activity coordinates offset by task coordinates minus unwanted left inset
- verifySetWindowCrop(new Rect(10, 25, 50, 75));
- }
-
- @Test
- public void testOnTaskInfoAppeared_partlyOverlapsWithAllInsets() {
- mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds
- Insets.of(/* left= */ 25, /* top= */ 25, /* right= */ 35, /* bottom= */ 15));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds
- /* parentBounds */ new Rect(0, 0, 200, 125),
- /* activityBounds */ new Rect(15, 0, 175, 120),
- /* taskBounds */ new Rect(0, 0, 200, 125),
- /* activityInsets */ new Rect(10, 25, 10, 10)), // equal to parent bounds
- mLeash);
-
- // Activity fully covers parent bounds with insets so doesn't need to be moved.
- verifySetPosition(0, 0);
- // Should return activity coordinates offset by task coordinates
- verifySetWindowCrop(new Rect(15, 0, 175, 120));
- }
-
- @Test
- public void testOnTaskInfoAppeared_parentShiftedLikeInOneHandedMode() {
- mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
- setWindowBoundsAndInsets(
- /* windowBounds= */ new Rect(0, 0, 100, 150),
- Insets.of(/* left= */ 0, /* top= */ 10, /* right= */ 0, /* bottom= */ 0));
-
- mLetterboxTaskListener.onTaskAppeared(
- createTaskInfo(
- /* taskId */ 1,
- /* maxBounds= */ new Rect(0, 0, 100, 150),
- /* parentBounds */ new Rect(0, 75, 100, 225),
- /* activityBounds */ new Rect(25, 75, 75, 125),
- /* taskBounds */ new Rect(0, 75, 100, 125),
- /* activityInsets */ new Rect(10, 0, 0, 0)),
- mLeash);
-
- verifySetPosition(0, 0);
- verifySetWindowCrop(new Rect(25, 0, 75, 50));
- }
-
- @Test(expected = IllegalStateException.class)
- public void testOnTaskAppeared_calledSecondTimeWithSameTaskId_throwsException() {
- setWindowBoundsAndInsets(new Rect(), Insets.NONE);
- RunningTaskInfo taskInfo =
- createTaskInfo(/* taskId */ 1, new Rect(), new Rect(), new Rect(), new Rect(),
- new Rect());
- mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash);
- mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash);
- }
-
- private void setWindowBoundsAndInsets(Rect windowBounds, Insets insets) {
- when(mWindowMetrics.getBounds()).thenReturn(windowBounds);
- when(mWindowInsets.getInsets(anyInt())).thenReturn(insets);
- }
-
- private void verifySetPosition(int x, int y) {
- verify(mTransaction).setPosition(eq(mLeash), eq((float) x), eq((float) y));
- }
-
- private void verifySetWindowCrop(final Rect crop) {
- // Should return activty coordinates offset by task coordinates
- verify(mTransaction).setWindowCrop(eq(mLeash), eq(crop));
- }
-
- private static RunningTaskInfo createTaskInfo(
- int taskId,
- final Rect maxBounds,
- final Rect parentBounds,
- final Rect activityBounds,
- final Rect taskBounds,
- final Rect activityInsets) {
- RunningTaskInfo taskInfo = new RunningTaskInfo();
- taskInfo.taskId = taskId;
- taskInfo.configuration.windowConfiguration.setMaxBounds(maxBounds);
- taskInfo.parentBounds = parentBounds;
- taskInfo.configuration.windowConfiguration.setBounds(taskBounds);
- taskInfo.letterboxActivityBounds = Rect.copyOrNull(activityBounds);
- taskInfo.letterboxActivityInsets = Rect.copyOrNull(activityInsets);
-
- return taskInfo;
- }
-}