DisplayCutout: Dispatch all non-zero safeInsets

Ensures that even if the display cutout does not overlap
a window, the safe insets are still dispatched if the window
overlaps any part of the cutout area and the safe insets
are therefore non-zero.

To do that, we need to compute the insets once against the
display size, then only shrink or expand the safe insets
accordingly.

Bug: 73533636
Test: atest DisplayCutoutTest
Change-Id: I1ea449178e29c7effdd92cac78af1a3875ca7e70
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d22828d..841586a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -138,6 +138,7 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.MutableBoolean;
+import android.util.Size;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
@@ -1197,14 +1198,20 @@
 
     DisplayCutout calculateDisplayCutoutForCurrentRotation() {
         final DisplayCutout cutout = mInitialDisplayCutout;
-        if (cutout == null || cutout == DisplayCutout.NO_CUTOUT || mRotation == ROTATION_0) {
+        if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
             return cutout;
         }
+        if (mRotation == ROTATION_0) {
+            return cutout.computeSafeInsets(mInitialDisplayWidth, mInitialDisplayHeight);
+        }
+        final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
         final Path bounds = cutout.getBounds().getBoundaryPath();
         transformPhysicalToLogicalCoordinates(mRotation, mInitialDisplayWidth,
                 mInitialDisplayHeight, mTmpMatrix);
         bounds.transform(mTmpMatrix);
-        return DisplayCutout.fromBounds(bounds);
+        return DisplayCutout.fromBounds(bounds).computeSafeInsets(
+                rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
+                rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index 13d0c86..57ce15bc 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -22,17 +22,12 @@
 import static com.android.server.wm.proto.DisplayFramesProto.STABLE_BOUNDS;
 
 import android.annotation.NonNull;
-import android.content.res.Resources;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 import java.io.PrintWriter;
-import java.util.Arrays;
 
 /**
  * Container class for all the display frames that affect how we do window layout on a display.
@@ -173,7 +168,7 @@
         mStableFullscreen.set(mUnrestricted);
         mCurrent.set(mUnrestricted);
 
-        mDisplayCutout = mDisplayInfoCutout.calculateRelativeTo(mOverscan);
+        mDisplayCutout = mDisplayInfoCutout;
         mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
                 Integer.MAX_VALUE, Integer.MAX_VALUE);
         if (!mDisplayCutout.isEmpty()) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 63ac4af..a8556bd 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -22,6 +22,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DisplayCutout.fromBoundingRect;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -38,7 +39,6 @@
 
 import android.annotation.SuppressLint;
 import android.content.res.Configuration;
-import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
@@ -396,7 +396,9 @@
             final DisplayContent dc = createNewDisplay();
             dc.mInitialDisplayWidth = 200;
             dc.mInitialDisplayHeight = 400;
-            final DisplayCutout cutout = createCutout(new Rect(80, 0, 120, 10));
+            Rect r = new Rect(80, 0, 120, 10);
+            final DisplayCutout cutout = fromBoundingRect(r.left, r.top, r.right, r.bottom)
+                    .computeSafeInsets(200, 400);
 
             dc.mInitialDisplayCutout = cutout;
             dc.setRotation(Surface.ROTATION_0);
@@ -412,13 +414,17 @@
             final DisplayContent dc = createNewDisplay();
             dc.mInitialDisplayWidth = 200;
             dc.mInitialDisplayHeight = 400;
-            final DisplayCutout cutout = createCutout(new Rect(80, 0, 120, 10));
+            Rect r1 = new Rect(80, 0, 120, 10);
+            final DisplayCutout cutout = fromBoundingRect(r1.left, r1.top, r1.right, r1.bottom)
+                    .computeSafeInsets(200, 400);
 
             dc.mInitialDisplayCutout = cutout;
             dc.setRotation(Surface.ROTATION_90);
             dc.computeScreenConfiguration(new Configuration()); // recomputes dc.mDisplayInfo.
 
-            assertEquals(createCutout(new Rect(0, 80, 10, 120)), dc.getDisplayInfo().displayCutout);
+            final Rect r = new Rect(0, 80, 10, 120);
+            assertEquals(fromBoundingRect(r.left, r.top, r.right, r.bottom)
+                    .computeSafeInsets(400, 200), dc.getDisplayInfo().displayCutout);
         }
     }
 
@@ -487,10 +493,4 @@
                 y,
                 metaState);
     }
-
-    private DisplayCutout createCutout(Rect r) {
-        Path p = new Path();
-        p.addRect(r.left, r.top, r.right, r.bottom, Path.Direction.CCW);
-        return DisplayCutout.fromBounds(p);
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 0959df2..7d6301cc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -22,7 +22,6 @@
 
 import android.app.ActivityManager.TaskDescription;
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
@@ -33,13 +32,12 @@
 import android.view.IWindow;
 import android.view.WindowManager;
 
+import static android.view.DisplayCutout.fromBoundingRect;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.FILL_PARENT;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import java.util.Arrays;
-
 /**
  * Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
  *
@@ -430,7 +428,8 @@
 
         final Rect pf = new Rect(0, 0, 1000, 1000);
         // Create a display cutout of size 50x50, aligned top-center
-        final DisplayCutout cutout = createDisplayCutoutFromRect(500, 0, 550, 50);
+        final DisplayCutout cutout = fromBoundingRect(500, 0, 550, 50)
+                .computeSafeInsets(pf.width(), pf.height());
 
         w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, cutout);
 
@@ -448,12 +447,4 @@
         return new WindowStateWithTask(attrs, task);
     }
 
-    private DisplayCutout createDisplayCutoutFromRect(int left, int top, int right, int bottom) {
-        return DisplayCutout.fromBoundingPolygon(Arrays.asList(
-                new Point(left, top),
-                new Point(left, bottom),
-                new Point(right, bottom),
-                new Point(right, top)
-        ));
-    }
 }