summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-11-09 05:09:21 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-09 05:09:21 +0000
commit31a500258294c0ffe310ff099d3ec97948752a0d (patch)
treea10f037cbab95893d30bdd050d7db1af14e0a8e1
parentff515c54dd84a824d308afee15266255d34ff162 (diff)
parent5bf63371a180a15d3bcb48947d7aefb55b864519 (diff)
Merge "Replace custom header spy window with custom touchable regions" into main
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java53
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java47
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java112
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt13
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt68
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java180
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java28
9 files changed, 426 insertions, 114 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 7265fb8f8027..c9f2d2e8c0e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -26,6 +26,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
+import android.annotation.NonNull;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ContentResolver;
import android.content.Context;
@@ -110,6 +111,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
}
mMainExecutor.execute(() -> {
mExclusionRegion.set(systemGestureExclusion);
+ onExclusionRegionChanged(displayId, mExclusionRegion);
});
}
};
@@ -163,7 +165,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
boolean isFocusedGlobally) {
final WindowDecoration decor = mWindowDecorByTaskId.get(taskId);
if (decor != null) {
- decor.relayout(decor.mTaskInfo, isFocusedGlobally);
+ decor.relayout(decor.mTaskInfo, isFocusedGlobally, decor.mExclusionRegion);
}
}
@@ -199,9 +201,9 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
if (enableDisplayFocusInShellTransitions()) {
// Pass the current global focus status to avoid updates outside of a ShellTransition.
- decoration.relayout(taskInfo, decoration.mHasGlobalFocus);
+ decoration.relayout(taskInfo, decoration.mHasGlobalFocus, decoration.mExclusionRegion);
} else {
- decoration.relayout(taskInfo, taskInfo.isFocused);
+ decoration.relayout(taskInfo, taskInfo.isFocused, decoration.mExclusionRegion);
}
}
@@ -240,7 +242,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
} else {
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
false /* setTaskCropAndPosition */,
- mFocusTransitionObserver.hasGlobalFocus(taskInfo));
+ mFocusTransitionObserver.hasGlobalFocus(taskInfo), mExclusionRegion);
}
}
@@ -254,7 +256,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
false /* setTaskCropAndPosition */,
- mFocusTransitionObserver.hasGlobalFocus(taskInfo));
+ mFocusTransitionObserver.hasGlobalFocus(taskInfo), mExclusionRegion);
}
@Override
@@ -266,6 +268,15 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
decoration.close();
}
+ private void onExclusionRegionChanged(int displayId, @NonNull Region exclusionRegion) {
+ final int decorCount = mWindowDecorByTaskId.size();
+ for (int i = 0; i < decorCount; i++) {
+ final CaptionWindowDecoration decoration = mWindowDecorByTaskId.valueAt(i);
+ if (decoration.mTaskInfo.displayId != displayId) continue;
+ decoration.onExclusionRegionChanged(exclusionRegion);
+ }
+ }
+
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
return true;
@@ -333,7 +344,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT
windowDecoration.setTaskDragResizer(taskPositioner);
windowDecoration.relayout(taskInfo, startT, finishT,
false /* applyStartTransactionOnDraw */, false /* setTaskCropAndPosition */,
- mFocusTransitionObserver.hasGlobalFocus(taskInfo));
+ mFocusTransitionObserver.hasGlobalFocus(taskInfo), mExclusionRegion);
}
private class CaptionTouchEventListener implements
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index c9546731a193..982fda0ddf36 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -36,6 +36,7 @@ import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.Region;
import android.graphics.drawable.GradientDrawable;
import android.os.Handler;
import android.util.Size;
@@ -174,7 +175,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
}
@Override
- void relayout(RunningTaskInfo taskInfo, boolean hasGlobalFocus) {
+ void relayout(RunningTaskInfo taskInfo, boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
// The crop and position of the task should only be set when a task is fluid resizing. In
// all other cases, it is expected that the transition handler positions and crops the task
@@ -186,7 +188,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
// synced with the buffer transaction (that draws the View). Both will be shown on screen
// at the same, whereas applying them independently causes flickering. See b/270202228.
relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */,
- shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus);
+ shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
}
@VisibleForTesting
@@ -198,7 +200,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
boolean isStatusBarVisible,
boolean isKeyguardVisibleAndOccluded,
InsetsState displayInsetsState,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus,
+ @NonNull Region globalExclusionRegion) {
relayoutParams.reset();
relayoutParams.mRunningTaskInfo = taskInfo;
relayoutParams.mLayoutResId = R.layout.caption_window_decor;
@@ -210,6 +213,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
relayoutParams.mSetTaskVisibilityPositionAndCrop = shouldSetTaskVisibilityPositionAndCrop;
relayoutParams.mIsCaptionVisible = taskInfo.isFreeform()
|| (isStatusBarVisible && !isKeyguardVisibleAndOccluded);
+ relayoutParams.mDisplayExclusionRegion.set(globalExclusionRegion);
if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
// If the app is requesting to customize the caption bar, allow input to fall
@@ -236,7 +240,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
void relayout(RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus,
+ @NonNull Region globalExclusionRegion) {
final boolean isFreeform =
taskInfo.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FREEFORM;
final boolean isDragResizeable = ENABLE_WINDOWING_SCALED_RESIZING.isTrue()
@@ -249,7 +254,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
updateRelayoutParams(mRelayoutParams, taskInfo, applyStartTransactionOnDraw,
shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible,
mIsKeyguardVisibleAndOccluded,
- mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus);
+ mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus,
+ globalExclusionRegion);
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 5e3026a73971..a2d81a0ed90a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -220,6 +220,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
}
mMainExecutor.execute(() -> {
mExclusionRegion.set(systemGestureExclusion);
+ onExclusionRegionChanged(displayId, mExclusionRegion);
});
}
};
@@ -432,7 +433,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
boolean isFocusedGlobally) {
final WindowDecoration decor = mWindowDecorByTaskId.get(taskId);
if (decor != null) {
- decor.relayout(decor.mTaskInfo, isFocusedGlobally);
+ decor.relayout(decor.mTaskInfo, isFocusedGlobally, decor.mExclusionRegion);
}
}
@@ -471,9 +472,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
}
if (enableDisplayFocusInShellTransitions()) {
// Pass the current global focus status to avoid updates outside of a ShellTransition.
- decoration.relayout(taskInfo, decoration.mHasGlobalFocus);
+ decoration.relayout(taskInfo, decoration.mHasGlobalFocus, decoration.mExclusionRegion);
} else {
- decoration.relayout(taskInfo, taskInfo.isFocused);
+ decoration.relayout(taskInfo, taskInfo.isFocused, decoration.mExclusionRegion);
}
mActivityOrientationChangeHandler.ifPresent(handler ->
handler.handleActivityOrientationChange(oldTaskInfo, taskInfo));
@@ -514,7 +515,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
} else {
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
false /* shouldSetTaskPositionAndCrop */,
- mFocusTransitionObserver.hasGlobalFocus(taskInfo));
+ mFocusTransitionObserver.hasGlobalFocus(taskInfo),
+ mExclusionRegion);
}
}
@@ -528,7 +530,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */,
false /* shouldSetTaskPositionAndCrop */,
- mFocusTransitionObserver.hasGlobalFocus(taskInfo));
+ mFocusTransitionObserver.hasGlobalFocus(taskInfo),
+ mExclusionRegion);
}
@Override
@@ -548,6 +551,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mWindowDecorByTaskId.remove(taskInfo.taskId);
}
+ private void onExclusionRegionChanged(int displayId, @NonNull Region exclusionRegion) {
+ final int decorCount = mWindowDecorByTaskId.size();
+ for (int i = 0; i < decorCount; i++) {
+ final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.valueAt(i);
+ if (decoration.mTaskInfo.displayId != displayId) continue;
+ decoration.onExclusionRegionChanged(exclusionRegion);
+ }
+ }
+
private void openHandleMenu(int taskId) {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
decoration.createHandleMenu(checkNumberOfOtherInstances(decoration.mTaskInfo)
@@ -750,10 +762,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
/**
* Whether to pilfer the next motion event to send cancellations to the windows below.
- * Useful when the caption window is spy and the gesture should be handle by the system
+ * Useful when the caption window is spy and the gesture should be handled by the system
* instead of by the app for their custom header content.
+ * Should not have any effect when {@link Flags#enableAccessibleCustomHeaders()}, because
+ * a spy window is not used then.
*/
- private boolean mShouldPilferCaptionEvents;
+ private boolean mIsCustomHeaderGesture;
+ private boolean mIsResizeGesture;
private boolean mIsDragging;
private boolean mTouchscreenInUse;
private boolean mHasLongClicked;
@@ -867,7 +882,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
// to offset position relative to caption as a whole.
int[] viewLocation = new int[2];
v.getLocationInWindow(viewLocation);
- final boolean isResizeEvent = decoration.shouldResizeListenerHandleEvent(e,
+ mIsResizeGesture = decoration.shouldResizeListenerHandleEvent(e,
new Point(viewLocation[0], viewLocation[1]));
// The caption window may be a spy window when the caption background is
// transparent, which means events will fall through to the app window. Make
@@ -875,21 +890,23 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
// customizable region and what the app reported as exclusion areas, because
// the drag-move or other caption gestures should take priority outside those
// regions.
- mShouldPilferCaptionEvents = !(downInCustomizableCaptionRegion
- && downInExclusionRegion && isTransparentCaption) && !isResizeEvent;
+ mIsCustomHeaderGesture = downInCustomizableCaptionRegion
+ && downInExclusionRegion && isTransparentCaption;
}
- if (!mShouldPilferCaptionEvents) {
- // The event will be handled by a window below or pilfered by resize handler.
+ if (mIsCustomHeaderGesture || mIsResizeGesture) {
+ // The event will be handled by the custom window below or pilfered by resize
+ // handler.
return false;
}
- // Otherwise pilfer so that windows below receive cancellations for this gesture, and
- // continue normal handling as a caption gesture.
- if (mInputManager != null) {
+ if (mInputManager != null
+ && !Flags.enableAccessibleCustomHeaders()) {
+ // Pilfer so that windows below receive cancellations for this gesture.
mInputManager.pilferPointers(v.getViewRootImpl().getInputToken());
}
if (isUpOrCancel) {
// Gesture is finished, reset state.
- mShouldPilferCaptionEvents = false;
+ mIsCustomHeaderGesture = false;
+ mIsResizeGesture = false;
}
if (isAppHandle) {
return mHandleDragDetector.onMotionEvent(v, e);
@@ -1592,7 +1609,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
windowDecoration.setDragPositioningCallback(taskPositioner);
windowDecoration.relayout(taskInfo, startT, finishT,
false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */,
- mFocusTransitionObserver.hasGlobalFocus(taskInfo));
+ mFocusTransitionObserver.hasGlobalFocus(taskInfo),
+ mExclusionRegion);
if (!DesktopModeFlags.ENABLE_HANDLE_INPUT_FIX.isTrue()) {
incrementEventReceiverTasks(taskInfo.displayId);
}
@@ -1618,6 +1636,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
pw.println(innerPrefix + "mTransitionDragActive=" + mTransitionDragActive);
pw.println(innerPrefix + "mEventReceiversByDisplay=" + mEventReceiversByDisplay);
pw.println(innerPrefix + "mWindowDecorByTaskId=" + mWindowDecorByTaskId);
+ pw.println(innerPrefix + "mExclusionRegion=" + mExclusionRegion);
}
private class DesktopModeOnTaskRepositionAnimationListener
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index d065ac33a958..cdcf14e0cbf3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -394,7 +394,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
}
@Override
- void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus) {
+ void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion) {
final SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
// The visibility, crop and position of the task should only be set when a task is
// fluid resizing. In all other cases, it is expected that the transition handler sets
@@ -415,7 +416,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
// causes flickering. See b/270202228.
final boolean applyTransactionOnDraw = taskInfo.isFreeform();
relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop,
- hasGlobalFocus);
+ hasGlobalFocus, displayExclusionRegion);
if (!applyTransactionOnDraw) {
t.apply();
}
@@ -442,18 +443,18 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
void relayout(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) {
Trace.beginSection("DesktopModeWindowDecoration#relayout");
if (taskInfo.isFreeform()) {
// The Task is in Freeform mode -> show its header in sync since it's an integral part
// of the window itself - a delayed header might cause bad UX.
relayoutInSync(taskInfo, startT, finishT, applyStartTransactionOnDraw,
- shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus);
+ shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
} else {
// The Task is outside Freeform mode -> allow the handle view to be delayed since the
// handle is just a small addition to the window.
relayoutWithDelayedViewHost(taskInfo, startT, finishT, applyStartTransactionOnDraw,
- shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus);
+ shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
}
Trace.endSection();
}
@@ -462,11 +463,11 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private void relayoutInSync(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) {
// Clear the current ViewHost runnable as we will update the ViewHost here
clearCurrentViewHostRunnable();
updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT, applyStartTransactionOnDraw,
- shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus);
+ shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus, displayExclusionRegion);
if (mResult.mRootView != null) {
updateViewHost(mRelayoutParams, startT, mResult);
}
@@ -489,7 +490,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private void relayoutWithDelayedViewHost(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion) {
if (applyStartTransactionOnDraw) {
throw new IllegalArgumentException(
"We cannot both sync viewhost ondraw and delay viewhost creation.");
@@ -498,7 +500,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
clearCurrentViewHostRunnable();
updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT,
false /* applyStartTransactionOnDraw */, shouldSetTaskVisibilityPositionAndCrop,
- hasGlobalFocus);
+ hasGlobalFocus, displayExclusionRegion);
if (mResult.mRootView == null) {
// This means something blocks the window decor from showing, e.g. the task is hidden.
// Nothing is set up in this case including the decoration surface.
@@ -513,7 +515,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private void updateRelayoutParamsAndSurfaces(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) {
Trace.beginSection("DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces");
if (Flags.enableDesktopWindowingAppToWeb()) {
setCapturedLink(taskInfo.capturedLink, taskInfo.capturedLinkTimestamp);
@@ -538,7 +540,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw,
shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible,
mIsKeyguardVisibleAndOccluded, inFullImmersive,
- mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus);
+ mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus,
+ displayExclusionRegion);
final WindowDecorLinearLayout oldRootView = mResult.mRootView;
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
@@ -879,7 +882,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
boolean isKeyguardVisibleAndOccluded,
boolean inFullImmersiveMode,
@NonNull InsetsState displayInsetsState,
- boolean hasGlobalFocus) {
+ boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion) {
final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode());
final boolean isAppHeader =
captionLayoutId == R.layout.desktop_mode_app_header;
@@ -890,6 +894,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode());
relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
relayoutParams.mHasGlobalFocus = hasGlobalFocus;
+ relayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
final boolean showCaption;
if (Flags.enableFullyImmersiveInDesktop()) {
@@ -915,10 +920,20 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
relayoutParams.mIsInsetSource = isAppHeader && !inFullImmersiveMode;
if (isAppHeader) {
if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
- // If the app is requesting to customize the caption bar, allow input to fall
- // through to the windows below so that the app can respond to input events on
- // their custom content.
- relayoutParams.mInputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
+ // The app is requesting to customize the caption bar, which means input on
+ // customizable/exclusion regions must go to the app instead of to the system.
+ // This may be accomplished with spy windows or custom touchable regions:
+ if (Flags.enableAccessibleCustomHeaders()) {
+ // Set the touchable region of the caption to only the areas where input should
+ // be handled by the system (i.e. non custom-excluded areas). The region will
+ // be calculated based on occluding caption elements and exclusion areas
+ // reported by the app.
+ relayoutParams.mLimitTouchRegionToSystemAreas = true;
+ } else {
+ // Allow input to fall through to the windows below so that the app can respond
+ // to input events on their custom content.
+ relayoutParams.mInputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
+ }
} else {
if (ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue()) {
// Force-consume the caption bar insets when the app tries to hide the caption.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index b016c755e323..a3c75bf33cde 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -127,7 +127,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
}
mDisplayController.removeDisplayWindowListener(this);
- relayout(mTaskInfo, mHasGlobalFocus);
+ relayout(mTaskInfo, mHasGlobalFocus, mExclusionRegion);
}
};
@@ -143,7 +143,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
SurfaceControl mDecorationContainerSurface;
SurfaceControl mCaptionContainerSurface;
- private WindowlessWindowManager mCaptionWindowManager;
+ private CaptionWindowlessWindowManager mCaptionWindowManager;
private SurfaceControlViewHost mViewHost;
private Configuration mWindowDecorConfig;
TaskDragResizer mTaskDragResizer;
@@ -152,6 +152,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
boolean mIsStatusBarVisible;
boolean mIsKeyguardVisibleAndOccluded;
boolean mHasGlobalFocus;
+ final Region mExclusionRegion = Region.obtain();
/** The most recent set of insets applied to this window decoration. */
private WindowDecorationInsets mWindowDecorationInsets;
@@ -218,7 +219,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
* constructor.
* @param hasGlobalFocus Whether the task is focused
*/
- abstract void relayout(RunningTaskInfo taskInfo, boolean hasGlobalFocus);
+ abstract void relayout(RunningTaskInfo taskInfo, boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion);
/**
* Used by the {@link DragPositioningCallback} associated with the implementing class to
@@ -244,6 +246,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mTaskInfo = params.mRunningTaskInfo;
}
mHasGlobalFocus = params.mHasGlobalFocus;
+ mExclusionRegion.set(params.mDisplayExclusionRegion);
final int oldLayoutResId = mLayoutResId;
mLayoutResId = params.mLayoutResId;
@@ -402,7 +405,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
final int elementWidthPx =
resources.getDimensionPixelSize(element.mWidthResId);
boundingRects[i] =
- calculateBoundingRect(element, elementWidthPx, captionInsetsRect);
+ calculateBoundingRectLocal(element, elementWidthPx, captionInsetsRect);
// Subtract the regions used by the caption elements, the rest is
// customizable.
if (params.hasInputFeatureSpy()) {
@@ -477,9 +480,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
if (mCaptionWindowManager == null) {
// Put caption under a container surface because ViewRootImpl sets the destination frame
// of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
- mCaptionWindowManager = new WindowlessWindowManager(
- mTaskInfo.getConfiguration(), mCaptionContainerSurface,
- null /* hostInputToken */);
+ mCaptionWindowManager = new CaptionWindowlessWindowManager(
+ mTaskInfo.getConfiguration(), mCaptionContainerSurface);
}
mCaptionWindowManager.setConfiguration(mTaskInfo.getConfiguration());
final WindowManager.LayoutParams lp =
@@ -492,6 +494,14 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
lp.setTrustedOverlay();
lp.inputFeatures = params.mInputFeatures;
+ final Rect localCaptionBounds = new Rect(
+ outResult.mCaptionX,
+ outResult.mCaptionY,
+ outResult.mCaptionX + outResult.mCaptionWidth,
+ outResult.mCaptionY + outResult.mCaptionHeight);
+ final Region touchableRegion = params.mLimitTouchRegionToSystemAreas
+ ? calculateLimitedTouchableRegion(params, localCaptionBounds)
+ : null;
if (mViewHost == null) {
Trace.beginSection("CaptionViewHostLayout-new");
mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
@@ -503,6 +513,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(onDrawTransaction);
}
outResult.mRootView.setPadding(0, params.mCaptionTopPadding, 0, 0);
+ if (params.mLimitTouchRegionToSystemAreas) {
+ mCaptionWindowManager.setTouchRegion(mViewHost, touchableRegion);
+ }
mViewHost.setView(outResult.mRootView, lp);
Trace.endSection();
} else {
@@ -514,13 +527,71 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mViewHost.getRootSurfaceControl().applyTransactionOnDraw(onDrawTransaction);
}
outResult.mRootView.setPadding(0, params.mCaptionTopPadding, 0, 0);
+ if (params.mLimitTouchRegionToSystemAreas) {
+ mCaptionWindowManager.setTouchRegion(mViewHost, touchableRegion);
+ }
mViewHost.relayout(lp);
Trace.endSection();
}
+ if (touchableRegion != null) {
+ touchableRegion.recycle();
+ }
Trace.endSection(); // CaptionViewHostLayout
}
- private Rect calculateBoundingRect(@NonNull OccludingCaptionElement element,
+ @NonNull
+ private Region calculateLimitedTouchableRegion(
+ RelayoutParams params,
+ @NonNull Rect localCaptionBounds) {
+ // Make caption bounds relative to display to align with exclusion region.
+ final Point positionInParent = params.mRunningTaskInfo.positionInParent;
+ final Rect captionBoundsInDisplay = new Rect(localCaptionBounds);
+ captionBoundsInDisplay.offsetTo(positionInParent.x, positionInParent.y);
+
+ final Region boundingRects = calculateBoundingRectsRegion(params, captionBoundsInDisplay);
+
+ final Region customizedRegion = Region.obtain();
+ customizedRegion.set(captionBoundsInDisplay);
+ customizedRegion.op(boundingRects, Region.Op.DIFFERENCE);
+ customizedRegion.op(params.mDisplayExclusionRegion, Region.Op.INTERSECT);
+
+ final Region touchableRegion = Region.obtain();
+ touchableRegion.set(captionBoundsInDisplay);
+ touchableRegion.op(customizedRegion, Region.Op.DIFFERENCE);
+ // Return resulting region back to window coordinates.
+ touchableRegion.translate(-positionInParent.x, -positionInParent.y);
+
+ boundingRects.recycle();
+ customizedRegion.recycle();
+ return touchableRegion;
+ }
+
+ @NonNull
+ private Region calculateBoundingRectsRegion(
+ @NonNull RelayoutParams params,
+ @NonNull Rect captionBoundsInDisplay) {
+ final int numOfElements = params.mOccludingCaptionElements.size();
+ final Region region = Region.obtain();
+ if (numOfElements == 0) {
+ // The entire caption is a bounding rect.
+ region.set(captionBoundsInDisplay);
+ return region;
+ }
+ final Resources resources = mDecorWindowContext.getResources();
+ for (int i = 0; i < numOfElements; i++) {
+ final OccludingCaptionElement element = params.mOccludingCaptionElements.get(i);
+ final int elementWidthPx = resources.getDimensionPixelSize(element.mWidthResId);
+ final Rect boundingRect = calculateBoundingRectLocal(element, elementWidthPx,
+ captionBoundsInDisplay);
+ // Bounding rect is initially calculated relative to the caption, so offset it to make
+ // it relative to the display.
+ boundingRect.offset(captionBoundsInDisplay.left, captionBoundsInDisplay.top);
+ region.union(boundingRect);
+ }
+ return region;
+ }
+
+ private Rect calculateBoundingRectLocal(@NonNull OccludingCaptionElement element,
int elementWidthPx, @NonNull Rect captionRect) {
switch (element.mAlignment) {
case START -> {
@@ -539,7 +610,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mIsKeyguardVisibleAndOccluded = visible && occluded;
final boolean changed = prevVisAndOccluded != mIsKeyguardVisibleAndOccluded;
if (changed) {
- relayout(mTaskInfo, mHasGlobalFocus);
+ relayout(mTaskInfo, mHasGlobalFocus, mExclusionRegion);
}
}
@@ -549,10 +620,14 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
final boolean changed = prevStatusBarVisibility != mIsStatusBarVisible;
if (changed) {
- relayout(mTaskInfo, mHasGlobalFocus);
+ relayout(mTaskInfo, mHasGlobalFocus, mExclusionRegion);
}
}
+ void onExclusionRegionChanged(@NonNull Region exclusionRegion) {
+ relayout(mTaskInfo, mHasGlobalFocus, exclusionRegion);
+ }
+
/**
* Update caption visibility state and views.
*/
@@ -751,9 +826,11 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
int mCaptionHeightId;
int mCaptionWidthId;
final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
+ boolean mLimitTouchRegionToSystemAreas;
int mInputFeatures;
boolean mIsInsetSource = true;
@InsetsSource.Flags int mInsetSourceFlags;
+ final Region mDisplayExclusionRegion = Region.obtain();
int mShadowRadiusId;
int mCornerRadius;
@@ -772,9 +849,11 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionHeightId = Resources.ID_NULL;
mCaptionWidthId = Resources.ID_NULL;
mOccludingCaptionElements.clear();
+ mLimitTouchRegionToSystemAreas = false;
mInputFeatures = 0;
mIsInsetSource = true;
mInsetSourceFlags = 0;
+ mDisplayExclusionRegion.setEmpty();
mShadowRadiusId = Resources.ID_NULL;
mCornerRadius = 0;
@@ -830,6 +909,19 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
}
}
+ private static class CaptionWindowlessWindowManager extends WindowlessWindowManager {
+ CaptionWindowlessWindowManager(
+ @NonNull Configuration configuration,
+ @NonNull SurfaceControl rootSurface) {
+ super(configuration, rootSurface, /* hostInputToken= */ null);
+ }
+
+ /** Set the view host's touchable region. */
+ void setTouchRegion(@NonNull SurfaceControlViewHost viewHost, @NonNull Region region) {
+ setTouchRegion(viewHost.getWindowToken().asBinder(), region);
+ }
+ }
+
@VisibleForTesting
public interface SurfaceControlViewHostFactory {
default SurfaceControlViewHost create(Context c, Display d, WindowlessWindowManager wmm) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt
index 5ebf5170bf86..59141ca39487 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorationTests.kt
@@ -19,6 +19,7 @@ package com.android.wm.shell.windowdecor
import android.app.ActivityManager
import android.app.WindowConfiguration
import android.content.ComponentName
+import android.graphics.Region
import android.testing.AndroidTestingRunner
import android.view.Display
import android.view.InsetsState
@@ -33,6 +34,9 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidTestingRunner::class)
class CaptionWindowDecorationTests : ShellTestCase() {
+
+ private val exclusionRegion = Region.obtain()
+
@Test
fun updateRelayoutParams_freeformAndTransparentAppearance_allowsInputFallthrough() {
val taskInfo = createTaskInfo()
@@ -50,7 +54,8 @@ class CaptionWindowDecorationTests : ShellTestCase() {
true /* isStatusBarVisible */,
false /* isKeyguardVisibleAndOccluded */,
InsetsState(),
- true /* hasGlobalFocus */
+ true /* hasGlobalFocus */,
+ exclusionRegion
)
Truth.assertThat(relayoutParams.hasInputFeatureSpy()).isTrue()
@@ -72,7 +77,8 @@ class CaptionWindowDecorationTests : ShellTestCase() {
true /* isStatusBarVisible */,
false /* isKeyguardVisibleAndOccluded */,
InsetsState(),
- true /* hasGlobalFocus */
+ true /* hasGlobalFocus */,
+ exclusionRegion
)
Truth.assertThat(relayoutParams.hasInputFeatureSpy()).isFalse()
@@ -90,7 +96,8 @@ class CaptionWindowDecorationTests : ShellTestCase() {
true /* isStatusBarVisible */,
false /* isKeyguardVisibleAndOccluded */,
InsetsState(),
- true /* hasGlobalFocus */
+ true /* hasGlobalFocus */,
+ exclusionRegion
)
Truth.assertThat(relayoutParams.mOccludingCaptionElements.size).isEqualTo(2)
Truth.assertThat(relayoutParams.mOccludingCaptionElements[0].mAlignment).isEqualTo(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 956100d9bc03..be664f86e9f5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -30,6 +30,7 @@ import android.content.Intent
import android.content.Intent.ACTION_MAIN
import android.content.pm.ActivityInfo
import android.graphics.Rect
+import android.graphics.Region
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.hardware.input.InputManager
@@ -48,6 +49,7 @@ import android.testing.TestableLooper.RunWithLooper
import android.util.SparseArray
import android.view.Choreographer
import android.view.Display.DEFAULT_DISPLAY
+import android.view.ISystemGestureExclusionListener
import android.view.IWindowManager
import android.view.InputChannel
import android.view.InputMonitor
@@ -84,7 +86,6 @@ import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayInsetsController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.MultiInstanceHelper
-import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler
import com.android.wm.shell.desktopmode.DesktopModeEventLogger
@@ -131,6 +132,7 @@ import org.mockito.Mockito.times
import org.mockito.kotlin.KArgumentCaptor
import org.mockito.kotlin.verify
import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.argThat
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doNothing
@@ -175,7 +177,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
@Mock private lateinit var mockInputMonitorFactory:
DesktopModeWindowDecorViewModel.InputMonitorFactory
@Mock private lateinit var mockShellController: ShellController
- @Mock private lateinit var mockShellExecutor: ShellExecutor
+ private val testShellExecutor = TestShellExecutor()
@Mock private lateinit var mockAppHeaderViewHolderFactory: AppHeaderViewHolder.Factory
@Mock private lateinit var mockRootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer
@Mock private lateinit var mockShellCommandHandler: ShellCommandHandler
@@ -230,13 +232,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
spyContext = spy(mContext)
doNothing().`when`(spyContext).startActivity(any())
- shellInit = ShellInit(mockShellExecutor)
+ shellInit = ShellInit(testShellExecutor)
windowDecorByTaskIdSpy.clear()
spyContext.addMockSystemService(InputManager::class.java, mockInputManager)
desktopModeEventLogger = mock<DesktopModeEventLogger>()
desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel(
spyContext,
- mockShellExecutor,
+ testShellExecutor,
mockMainHandler,
mockMainChoreographer,
bgExecutor,
@@ -1321,11 +1323,11 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
decoration.mHasGlobalFocus = true
desktopModeWindowDecorViewModel.onTaskInfoChanged(task)
- verify(decoration).relayout(task, true)
+ verify(decoration).relayout(eq(task), eq(true), anyOrNull())
decoration.mHasGlobalFocus = false
desktopModeWindowDecorViewModel.onTaskInfoChanged(task)
- verify(decoration).relayout(task, false)
+ verify(decoration).relayout(eq(task), eq(false), anyOrNull())
}
@Test
@@ -1342,17 +1344,66 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
task.isFocused = true
desktopModeWindowDecorViewModel.onTaskInfoChanged(task)
- verify(decoration).relayout(task, true)
+ verify(decoration).relayout(eq(task), eq(true), anyOrNull())
task.isFocused = false
desktopModeWindowDecorViewModel.onTaskInfoChanged(task)
- verify(decoration).relayout(task, false)
+ verify(decoration).relayout(eq(task), eq(false), anyOrNull())
+ }
+
+ @Test
+ fun testGestureExclusionChanged_updatesDecorations() {
+ val captor = argumentCaptor<ISystemGestureExclusionListener>()
+ verify(mockWindowManager)
+ .registerSystemGestureExclusionListener(captor.capture(), eq(DEFAULT_DISPLAY))
+ val task = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ displayId = DEFAULT_DISPLAY
+ )
+ val task2 = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ displayId = DEFAULT_DISPLAY
+ )
+ val newRegion = Region.obtain().apply {
+ set(Rect(0, 0, 1600, 80))
+ }
+
+ captor.firstValue.onSystemGestureExclusionChanged(DEFAULT_DISPLAY, newRegion, newRegion)
+ testShellExecutor.flushAll()
+
+ verify(task).onExclusionRegionChanged(newRegion)
+ verify(task2).onExclusionRegionChanged(newRegion)
+ }
+
+ @Test
+ fun testGestureExclusionChanged_otherDisplay_skipsDecorationUpdate() {
+ val captor = argumentCaptor<ISystemGestureExclusionListener>()
+ verify(mockWindowManager)
+ .registerSystemGestureExclusionListener(captor.capture(), eq(DEFAULT_DISPLAY))
+ val task = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ displayId = DEFAULT_DISPLAY
+ )
+ val task2 = createOpenTaskDecoration(
+ windowingMode = WINDOWING_MODE_FREEFORM,
+ displayId = 2
+ )
+ val newRegion = Region.obtain().apply {
+ set(Rect(0, 0, 1600, 80))
+ }
+
+ captor.firstValue.onSystemGestureExclusionChanged(DEFAULT_DISPLAY, newRegion, newRegion)
+ testShellExecutor.flushAll()
+
+ verify(task).onExclusionRegionChanged(newRegion)
+ verify(task2, never()).onExclusionRegionChanged(newRegion)
}
private fun createOpenTaskDecoration(
@WindowingMode windowingMode: Int,
taskSurface: SurfaceControl = SurfaceControl(),
requestingImmersive: Boolean = false,
+ displayId: Int = DEFAULT_DISPLAY,
onMaxOrRestoreListenerCaptor: ArgumentCaptor<Function0<Unit>> =
forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
onImmersiveOrRestoreListenerCaptor: KArgumentCaptor<() -> Unit> =
@@ -1376,6 +1427,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
): DesktopModeWindowDecoration {
val decor = setUpMockDecorationForTask(createTask(
windowingMode = windowingMode,
+ displayId = displayId,
requestingImmersive = requestingImmersive
))
onTaskOpening(decor.mTaskInfo, taskSurface)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 884ad5c13f6a..1d2d0f078817 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -64,6 +64,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.Region;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
@@ -224,6 +225,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
private TestableContext mTestableContext;
private final ShellExecutor mBgExecutor = new TestShellExecutor();
private final AssistContent mAssistContent = new AssistContent();
+ private final Region mExclusionRegion = Region.obtain();
/** Set up run before test class. */
@BeforeClass
@@ -283,7 +285,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final DesktopModeWindowDecoration spyWindowDecor =
spy(createWindowDecoration(taskInfo));
- spyWindowDecor.relayout(taskInfo, false /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, false /* hasGlobalFocus */, mExclusionRegion);
// Menus should close if open before the task being invisible causes relayout to return.
verify(spyWindowDecor).closeHandleMenu();
@@ -303,7 +305,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mShadowRadiusId).isNotEqualTo(Resources.ID_NULL);
}
@@ -324,7 +327,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mCornerRadius).isGreaterThan(0);
}
@@ -350,7 +354,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(customTaskDensity);
}
@@ -377,12 +382,14 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(systemDensity);
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_ACCESSIBLE_CUSTOM_HEADERS)
public void updateRelayoutParams_freeformAndTransparentAppearance_allowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -400,12 +407,39 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.hasInputFeatureSpy()).isTrue();
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_ACCESSIBLE_CUSTOM_HEADERS)
+ public void updateRelayoutParams_freeformAndTransparentAppearance_limitedTouchRegion() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ taskInfo.taskDescription.setTopOpaqueSystemBarsAppearance(
+ APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false,
+ /* isStatusBarVisible */ true,
+ /* isKeyguardVisibleAndOccluded */ false,
+ /* inFullImmersiveMode */ false,
+ new InsetsState(),
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
+
+ assertThat(relayoutParams.mLimitTouchRegionToSystemAreas).isTrue();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_ACCESSIBLE_CUSTOM_HEADERS)
public void updateRelayoutParams_freeformButOpaqueAppearance_disallowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -422,12 +456,38 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_ACCESSIBLE_CUSTOM_HEADERS)
+ public void updateRelayoutParams_freeformButOpaqueAppearance_unlimitedTouchRegion() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ taskInfo.taskDescription.setTopOpaqueSystemBarsAppearance(0);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false,
+ /* isStatusBarVisible */ true,
+ /* isKeyguardVisibleAndOccluded */ false,
+ /* inFullImmersiveMode */ false,
+ new InsetsState(),
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
+
+ assertThat(relayoutParams.mLimitTouchRegionToSystemAreas).isFalse();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_ACCESSIBLE_CUSTOM_HEADERS)
public void updateRelayoutParams_fullscreen_disallowsInputFallthrough() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -443,12 +503,36 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_ACCESSIBLE_CUSTOM_HEADERS)
+ public void updateRelayoutParams_fullscreen_unlimitedTouchRegion() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ final RelayoutParams relayoutParams = new RelayoutParams();
+
+ DesktopModeWindowDecoration.updateRelayoutParams(
+ relayoutParams,
+ mTestableContext,
+ taskInfo,
+ /* applyStartTransactionOnDraw= */ true,
+ /* shouldSetTaskPositionAndCrop */ false,
+ /* isStatusBarVisible */ true,
+ /* isKeyguardVisibleAndOccluded */ false,
+ /* inFullImmersiveMode */ false,
+ new InsetsState(),
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
+
+ assertThat(relayoutParams.mLimitTouchRegionToSystemAreas).isFalse();
+ }
+
+ @Test
public void updateRelayoutParams_freeform_inputChannelNeeded() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
@@ -464,7 +548,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(hasNoInputChannelFeature(relayoutParams)).isFalse();
}
@@ -486,7 +571,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
}
@@ -508,7 +594,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
}
@@ -531,7 +618,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat((relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING) != 0).isTrue();
}
@@ -555,7 +643,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat((relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING) == 0).isTrue();
}
@@ -577,7 +666,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(
(relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0)
@@ -601,7 +691,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(
(relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) == 0)
@@ -631,7 +722,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ true,
insetsState,
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
// Takes status bar inset as padding, ignores caption bar inset.
assertThat(relayoutParams.mCaptionTopPadding).isEqualTo(50);
@@ -654,7 +746,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ true,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsInsetSource).isFalse();
}
@@ -676,7 +769,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
// Header is always shown because it's assumed the status bar is always visible.
assertThat(relayoutParams.mIsCaptionVisible).isTrue();
@@ -698,7 +792,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsCaptionVisible).isTrue();
}
@@ -719,7 +814,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsCaptionVisible).isFalse();
}
@@ -740,7 +836,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ true,
/* inFullImmersiveMode */ false,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsCaptionVisible).isFalse();
}
@@ -762,7 +859,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ true,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsCaptionVisible).isTrue();
@@ -776,7 +874,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ false,
/* inFullImmersiveMode */ true,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsCaptionVisible).isFalse();
}
@@ -798,7 +897,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
/* isKeyguardVisibleAndOccluded */ true,
/* inFullImmersiveMode */ true,
new InsetsState(),
- /* hasGlobalFocus= */ true);
+ /* hasGlobalFocus= */ true,
+ mExclusionRegion);
assertThat(relayoutParams.mIsCaptionVisible).isFalse();
}
@@ -809,7 +909,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockTransaction).apply();
verify(mMockRootSurfaceControl, never()).applyTransactionOnDraw(any());
@@ -824,7 +924,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
// Make non-resizable to avoid dealing with input-permissions (MONITOR_INPUT)
taskInfo.isResizeable = false;
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockTransaction, never()).apply();
verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockTransaction);
@@ -836,7 +936,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockSurfaceControlViewHostFactory, never()).create(any(), any(), any());
}
@@ -848,7 +948,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
// Once for view host, the other for the AppHandle input layer.
verify(mMockHandler, times(2)).post(runnableArgument.capture());
@@ -865,7 +965,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
// Make non-resizable to avoid dealing with input-permissions (MONITOR_INPUT)
taskInfo.isResizeable = false;
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockSurfaceControlViewHostFactory).create(any(), any(), any());
verify(mMockHandler, never()).post(any());
@@ -877,11 +977,11 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
// Once for view host, the other for the AppHandle input layer.
verify(mMockHandler, times(2)).post(runnableArgument.capture());
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockHandler).removeCallbacks(runnableArgument.getValue());
}
@@ -892,7 +992,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
// Once for view host, the other for the AppHandle input layer.
verify(mMockHandler, times(2)).post(runnableArgument.capture());
@@ -1132,7 +1232,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
runnableArgument.getValue().run();
// Relayout decor with same captured link
- decor.relayout(taskInfo, true /* hasGlobalFocus */);
+ decor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
// Verify handle menu's browser link not set to captured link since link is expired
createHandleMenu(decor);
@@ -1313,7 +1413,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockCaptionHandleRepository, never()).notifyCaptionChanged(any());
}
@@ -1330,7 +1430,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
ArgumentCaptor<CaptionState> captionStateArgumentCaptor = ArgumentCaptor.forClass(
CaptionState.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockCaptionHandleRepository, atLeastOnce()).notifyCaptionChanged(
captionStateArgumentCaptor.capture());
@@ -1357,7 +1457,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
ArgumentCaptor<CaptionState> captionStateArgumentCaptor = ArgumentCaptor.forClass(
CaptionState.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
verify(mMockAppHeaderViewHolder, atLeastOnce()).runOnAppChipGlobalLayout(
runnableArgumentCaptor.capture());
runnableArgumentCaptor.getValue().invoke();
@@ -1380,7 +1480,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
ArgumentCaptor<CaptionState> captionStateArgumentCaptor = ArgumentCaptor.forClass(
CaptionState.class);
- spyWindowDecor.relayout(taskInfo, false /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, false /* hasGlobalFocus */, mExclusionRegion);
verify(mMockCaptionHandleRepository, atLeastOnce()).notifyCaptionChanged(
captionStateArgumentCaptor.capture());
@@ -1400,7 +1500,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
ArgumentCaptor<CaptionState> captionStateArgumentCaptor = ArgumentCaptor.forClass(
CaptionState.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
createHandleMenu(spyWindowDecor);
verify(mMockCaptionHandleRepository, atLeastOnce()).notifyCaptionChanged(
@@ -1425,7 +1525,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
ArgumentCaptor<CaptionState> captionStateArgumentCaptor = ArgumentCaptor.forClass(
CaptionState.class);
- spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ spyWindowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
createHandleMenu(spyWindowDecor);
spyWindowDecor.closeHandleMenu();
@@ -1543,7 +1643,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
windowDecor.setOpenInBrowserClickListener(mMockOpenInBrowserClickListener);
windowDecor.mDecorWindowContext = mContext;
if (relayout) {
- windowDecor.relayout(taskInfo, true /* hasGlobalFocus */);
+ windowDecor.relayout(taskInfo, true /* hasGlobalFocus */, mExclusionRegion);
}
return windowDecor;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 8e0434cb28f7..534803db5fe0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -60,6 +60,7 @@ import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.Region;
import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
@@ -508,7 +509,7 @@ public class WindowDecorationTests extends ShellTestCase {
final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
windowDecor.relayout(taskInfo, true /* applyStartTransactionOnDraw */,
- true /* hasGlobalFocus */);
+ true /* hasGlobalFocus */, Region.obtain());
verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
}
@@ -525,7 +526,7 @@ public class WindowDecorationTests extends ShellTestCase {
mRelayoutParams.mCaptionTopPadding = 50;
windowDecor.relayout(taskInfo, false /* applyStartTransactionOnDraw */,
- true /* hasGlobalFocus */);
+ true /* hasGlobalFocus */, Region.obtain());
assertEquals(50, mRelayoutResult.mCaptionTopPadding);
}
@@ -944,7 +945,7 @@ public class WindowDecorationTests extends ShellTestCase {
decor.onInsetsStateChanged(createInsetsState(statusBars(), false /* visible */));
- verify(decor, times(2)).relayout(task, true /* hasGlobalFocus */);
+ verify(decor, times(2)).relayout(any(), any(), any(), any(), any(), any());
}
@Test
@@ -958,7 +959,7 @@ public class WindowDecorationTests extends ShellTestCase {
decor.onInsetsStateChanged(createInsetsState(statusBars(), true /* visible */));
- verify(decor, times(1)).relayout(task, true /* hasGlobalFocus */);
+ verify(decor, times(1)).relayout(any(), any(), any(), any(), any(), any());
}
@Test
@@ -973,7 +974,7 @@ public class WindowDecorationTests extends ShellTestCase {
decor.onKeyguardStateChanged(true /* visible */, true /* occluding */);
assertTrue(decor.mIsKeyguardVisibleAndOccluded);
- verify(decor, times(2)).relayout(task, true /* hasGlobalFocus */);
+ verify(decor, times(2)).relayout(any(), any(), any(), any(), any(), any());
}
@Test
@@ -987,7 +988,7 @@ public class WindowDecorationTests extends ShellTestCase {
decor.onKeyguardStateChanged(false /* visible */, true /* occluding */);
- verify(decor, times(1)).relayout(task, true /* hasGlobalFocus */);
+ verify(decor, times(1)).relayout(any(), any(), any(), any(), any(), any());
}
private ActivityManager.RunningTaskInfo createTaskInfo() {
@@ -1061,9 +1062,16 @@ public class WindowDecorationTests extends ShellTestCase {
surfaceControlViewHostFactory, desktopModeEventLogger);
}
- @Override
void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus) {
- relayout(taskInfo, false /* applyStartTransactionOnDraw */, hasGlobalFocus);
+ relayout(taskInfo, false /* applyStartTransactionOnDraw */, hasGlobalFocus,
+ Region.obtain());
+ }
+
+ @Override
+ void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion) {
+ relayout(taskInfo, false /* applyStartTransactionOnDraw */, hasGlobalFocus,
+ displayExclusionRegion);
}
@Override
@@ -1085,11 +1093,13 @@ public class WindowDecorationTests extends ShellTestCase {
}
void relayout(ActivityManager.RunningTaskInfo taskInfo,
- boolean applyStartTransactionOnDraw, boolean hasGlobalFocus) {
+ boolean applyStartTransactionOnDraw, boolean hasGlobalFocus,
+ @NonNull Region displayExclusionRegion) {
mRelayoutParams.mRunningTaskInfo = taskInfo;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
mRelayoutParams.mLayoutResId = R.layout.caption_layout;
mRelayoutParams.mHasGlobalFocus = hasGlobalFocus;
+ mRelayoutParams.mDisplayExclusionRegion.set(displayExclusionRegion);
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
}