diff options
| author | 2024-11-09 05:09:21 +0000 | |
|---|---|---|
| committer | 2024-11-09 05:09:21 +0000 | |
| commit | 31a500258294c0ffe310ff099d3ec97948752a0d (patch) | |
| tree | a10f037cbab95893d30bdd050d7db1af14e0a8e1 | |
| parent | ff515c54dd84a824d308afee15266255d34ff162 (diff) | |
| parent | 5bf63371a180a15d3bcb48947d7aefb55b864519 (diff) | |
Merge "Replace custom header spy window with custom touchable regions" into main
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); } |