diff options
| author | 2020-12-13 14:59:22 +0000 | |
|---|---|---|
| committer | 2020-12-13 15:17:11 +0000 | |
| commit | 2f37c38f335c896c999a60073209bae4ca43eae0 (patch) | |
| tree | b9109d6994b5b9840d5cfe9af7604e29216e34e3 /libs | |
| parent | f2f545d7a0b260073a9da88da8bb641d2fe6f776 (diff) | |
Clean up LetterboxTaskListerner and all related logic.
This is the first step towards moving letterbox gravity logic from WM Shell to WM Core. It's important to do this even before the new implementation in WM Core is ready because surface repositioning in WM Shell causes visible flickering on rotation for all apps on devices with cutout.
Fix: 174632285
Bug: 175212232
Fix: 173440321
Test: atest WMShellUnitTests
Change-Id: I2b3706a1a46bb2c7ee4bb3789fb09b216e32f290
Diffstat (limited to 'libs')
10 files changed, 38 insertions, 1072 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/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/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; - } -} |