Update input sink to entire screen while resizing.

When a drag resize event has begun, increase the size of the input sink
to cover the entire screen. This prevents input and focus requests from
reaching any task behind the one being dragged.

Bug: 296926373
Test: Manual - drag task to various sizes/positions and attempt to have
another task steal focus

Change-Id: I27c15ef73ce28270cca92ac327b1c8cb68a8a60a
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 aff35a3..c12ac8b 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
@@ -149,7 +149,8 @@
                     mDecorationContainerSurface,
                     mDragPositioningCallback,
                     mSurfaceControlBuilderSupplier,
-                    mSurfaceControlTransactionSupplier);
+                    mSurfaceControlTransactionSupplier,
+                    mDisplayController);
         }
 
         final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
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 eba1a36..e1d177a 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
@@ -293,7 +293,8 @@
                     mDecorationContainerSurface,
                     mDragPositioningCallback,
                     mSurfaceControlBuilderSupplier,
-                    mSurfaceControlTransactionSupplier);
+                    mSurfaceControlTransactionSupplier,
+                    mDisplayController);
         }
 
         final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
index 1669cf4..8ce2d6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
@@ -40,8 +40,9 @@
      *                 {@code 0} to indicate it's a move
      * @param x x coordinate in window decoration coordinate system where the drag starts
      * @param y y coordinate in window decoration coordinate system where the drag starts
+     * @return the starting task bounds
      */
-    void onDragPositioningStart(@CtrlType int ctrlType, float x, float y);
+    Rect onDragPositioningStart(@CtrlType int ctrlType, float x, float y);
 
     /**
      * Called when the pointer moves during a drag-resize or drag-move.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 518f4b8..190b635 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -50,6 +50,8 @@
 import android.view.WindowManagerGlobal;
 
 import com.android.internal.view.BaseIWindow;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayLayout;
 
 import java.util.function.Supplier;
 
@@ -78,6 +80,7 @@
     private final SurfaceControl mInputSinkSurface;
     private final BaseIWindow mFakeSinkWindow;
     private final InputChannel mSinkInputChannel;
+    private final DisplayController mDisplayController;
 
     private int mTaskWidth;
     private int mTaskHeight;
@@ -92,6 +95,7 @@
 
     private int mDragPointerId = -1;
     private DragDetector mDragDetector;
+    private final Region mTouchRegion = new Region();
 
     DragResizeInputListener(
             Context context,
@@ -102,7 +106,8 @@
             SurfaceControl decorationSurface,
             DragPositioningCallback callback,
             Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
-            Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier) {
+            Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
+            DisplayController displayController) {
         mInputManager = context.getSystemService(InputManager.class);
         mHandler = handler;
         mChoreographer = choreographer;
@@ -110,6 +115,7 @@
         mDisplayId = displayId;
         mTaskCornerRadius = taskCornerRadius;
         mDecorationSurface = decorationSurface;
+        mDisplayController = displayController;
         // Use a fake window as the backing surface is a container layer, and we don't want to
         // create a buffer layer for it, so we can't use ViewRootImpl.
         mFakeWindow = new BaseIWindow();
@@ -195,34 +201,34 @@
         mCornerSize = cornerSize;
         mDragDetector.setTouchSlop(touchSlop);
 
-        Region touchRegion = new Region();
+        mTouchRegion.setEmpty();
         final Rect topInputBounds = new Rect(
                 -mResizeHandleThickness,
                 -mResizeHandleThickness,
                 mTaskWidth + mResizeHandleThickness,
                 0);
-        touchRegion.union(topInputBounds);
+        mTouchRegion.union(topInputBounds);
 
         final Rect leftInputBounds = new Rect(
                 -mResizeHandleThickness,
                 0,
                 0,
                 mTaskHeight);
-        touchRegion.union(leftInputBounds);
+        mTouchRegion.union(leftInputBounds);
 
         final Rect rightInputBounds = new Rect(
                 mTaskWidth,
                 0,
                 mTaskWidth + mResizeHandleThickness,
                 mTaskHeight);
-        touchRegion.union(rightInputBounds);
+        mTouchRegion.union(rightInputBounds);
 
         final Rect bottomInputBounds = new Rect(
                 -mResizeHandleThickness,
                 mTaskHeight,
                 mTaskWidth + mResizeHandleThickness,
                 mTaskHeight + mResizeHandleThickness);
-        touchRegion.union(bottomInputBounds);
+        mTouchRegion.union(bottomInputBounds);
 
         // Set up touch areas in each corner.
         int cornerRadius = mCornerSize / 2;
@@ -231,28 +237,28 @@
                 -cornerRadius,
                 cornerRadius,
                 cornerRadius);
-        touchRegion.union(mLeftTopCornerBounds);
+        mTouchRegion.union(mLeftTopCornerBounds);
 
         mRightTopCornerBounds = new Rect(
                 mTaskWidth - cornerRadius,
                 -cornerRadius,
                 mTaskWidth + cornerRadius,
                 cornerRadius);
-        touchRegion.union(mRightTopCornerBounds);
+        mTouchRegion.union(mRightTopCornerBounds);
 
         mLeftBottomCornerBounds = new Rect(
                 -cornerRadius,
                 mTaskHeight - cornerRadius,
                 cornerRadius,
                 mTaskHeight + cornerRadius);
-        touchRegion.union(mLeftBottomCornerBounds);
+        mTouchRegion.union(mLeftBottomCornerBounds);
 
         mRightBottomCornerBounds = new Rect(
                 mTaskWidth - cornerRadius,
                 mTaskHeight - cornerRadius,
                 mTaskWidth + cornerRadius,
                 mTaskHeight + cornerRadius);
-        touchRegion.union(mRightBottomCornerBounds);
+        mTouchRegion.union(mRightBottomCornerBounds);
 
         try {
             mWindowSession.updateInputChannel(
@@ -262,7 +268,7 @@
                     FLAG_NOT_FOCUSABLE,
                     PRIVATE_FLAG_TRUSTED_OVERLAY,
                     INPUT_FEATURE_SPY,
-                    touchRegion);
+                    mTouchRegion);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
@@ -281,19 +287,8 @@
         // issue. However, were there touchscreen-only a region out of the task bounds, mouse
         // gestures will become no-op in that region, even though the mouse gestures may appear to
         // be performed on the input window behind the resize handle.
-        touchRegion.op(0, 0, mTaskWidth, mTaskHeight, Region.Op.DIFFERENCE);
-        try {
-            mWindowSession.updateInputChannel(
-                    mSinkInputChannel.getToken(),
-                    mDisplayId,
-                    mInputSinkSurface,
-                    FLAG_NOT_FOCUSABLE,
-                    0 /* privateFlags */,
-                    INPUT_FEATURE_NO_INPUT_CHANNEL,
-                    touchRegion);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
+        mTouchRegion.op(0, 0, mTaskWidth, mTaskHeight, Region.Op.DIFFERENCE);
+        updateSinkInputChannel(mTouchRegion);
         return true;
     }
 
@@ -309,6 +304,21 @@
         return region;
     }
 
+    private void updateSinkInputChannel(Region region) {
+        try {
+            mWindowSession.updateInputChannel(
+                    mSinkInputChannel.getToken(),
+                    mDisplayId,
+                    mInputSinkSurface,
+                    FLAG_NOT_FOCUSABLE,
+                    0 /* privateFlags */,
+                    INPUT_FEATURE_NO_INPUT_CHANNEL,
+                    region);
+        } catch (RemoteException ex) {
+            ex.rethrowFromSystemServer();
+        }
+    }
+
     @Override
     public void close() {
         mInputEventReceiver.dispose();
@@ -337,6 +347,7 @@
         private boolean mConsumeBatchEventScheduled;
         private boolean mShouldHandleEvents;
         private int mLastCursorType = PointerIcon.TYPE_DEFAULT;
+        private Rect mDragStartTaskBounds;
 
         private TaskResizeInputEventReceiver(
                 InputChannel inputChannel, Handler handler, Choreographer choreographer) {
@@ -398,12 +409,15 @@
                     }
                     if (mShouldHandleEvents) {
                         mInputManager.pilferPointers(mInputChannel.getToken());
-
                         mDragPointerId = e.getPointerId(0);
                         float rawX = e.getRawX(0);
                         float rawY = e.getRawY(0);
                         int ctrlType = calculateCtrlType(isTouch, x, y);
-                        mCallback.onDragPositioningStart(ctrlType, rawX, rawY);
+                        mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
+                                rawX, rawY);
+                        // Increase the input sink region to cover the whole screen; this is to
+                        // prevent input and focus from going to other tasks during a drag resize.
+                        updateInputSinkRegionForDrag(mDragStartTaskBounds);
                         result = true;
                     }
                     break;
@@ -415,7 +429,8 @@
                     int dragPointerIndex = e.findPointerIndex(mDragPointerId);
                     float rawX = e.getRawX(dragPointerIndex);
                     float rawY = e.getRawY(dragPointerIndex);
-                    mCallback.onDragPositioningMove(rawX, rawY);
+                    final Rect taskBounds = mCallback.onDragPositioningMove(rawX, rawY);
+                    updateInputSinkRegionForDrag(taskBounds);
                     result = true;
                     break;
                 }
@@ -423,8 +438,13 @@
                 case MotionEvent.ACTION_CANCEL: {
                     if (mShouldHandleEvents) {
                         int dragPointerIndex = e.findPointerIndex(mDragPointerId);
-                        mCallback.onDragPositioningEnd(
+                        final Rect taskBounds = mCallback.onDragPositioningEnd(
                                 e.getRawX(dragPointerIndex), e.getRawY(dragPointerIndex));
+                        // If taskBounds has changed, setGeometry will be called and update the
+                        // sink region. Otherwise, we should revert it here.
+                        if (taskBounds.equals(mDragStartTaskBounds)) {
+                            updateSinkInputChannel(mTouchRegion);
+                        }
                     }
                     mShouldHandleEvents = false;
                     mDragPointerId = -1;
@@ -444,6 +464,18 @@
             return result;
         }
 
+        private void updateInputSinkRegionForDrag(Rect taskBounds) {
+            final DisplayLayout layout = mDisplayController.getDisplayLayout(mDisplayId);
+            final Region dragTouchRegion = new Region(-taskBounds.left,
+                    -taskBounds.top,
+                    -taskBounds.left + layout.width(),
+                    -taskBounds.top + layout.height());
+            // Remove the localized task bounds from the touch region.
+            taskBounds.offsetTo(0, 0);
+            dragTouchRegion.op(taskBounds, Region.Op.DIFFERENCE);
+            updateSinkInputChannel(dragTouchRegion);
+        }
+
         private boolean isInCornerBounds(float xf, float yf) {
             return calculateCornersCtrlType(xf, yf) != 0;
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
index dadd264..bf11c8b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
@@ -68,7 +68,7 @@
     }
 
     @Override
-    public void onDragPositioningStart(int ctrlType, float x, float y) {
+    public Rect onDragPositioningStart(int ctrlType, float x, float y) {
         mCtrlType = ctrlType;
         mTaskBoundsAtDragStart.set(
                 mWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
@@ -87,6 +87,7 @@
             mDisplayController.getDisplayLayout(mWindowDecoration.mDisplay.getDisplayId())
                     .getStableBounds(mStableBounds);
         }
+        return mRepositionTaskBounds;
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
index 852c037..79fec09 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -85,7 +85,7 @@
     }
 
     @Override
-    public void onDragPositioningStart(int ctrlType, float x, float y) {
+    public Rect onDragPositioningStart(int ctrlType, float x, float y) {
         mCtrlType = ctrlType;
         mTaskBoundsAtDragStart.set(
                 mDesktopWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
@@ -107,6 +107,7 @@
             mDisplayController.getDisplayLayout(mDesktopWindowDecoration.mDisplay.getDisplayId())
                     .getStableBounds(mStableBounds);
         }
+        return mRepositionTaskBounds;
     }
 
     @Override