Count letterbox into non-magnified bounds

On device with display cutout, apps could decide if their windows
are allowed to extend into the cutout area. If not, a letterbox will
be applied such that the window does not extend into the cutout. The
letterbox area won't be magnified so we wouldn't draw magnification
overlay there.

In this case, the magnification overlay would draw around the entire
screen when there is a heads-up notification or another bigger
magnifiable window becomes visible on top of letterbox area at that
moment.

However, we don't really count the letterbox into non-magnifiable
area which would be counted as dirty rect. Hence, we only redraw
smaller dirty rect. The old bigger boundary is outside the dirty
rect and still in the surface.

Bug: 79117529
Test: a11y CTS & unit test
Test: manual
Change-Id: Ie1cee78713016716fa1a203ffd12cf1612329590
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 545b69b..e36d413 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -607,6 +607,13 @@
                         availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
                     }
 
+                    // Count letterbox into nonMagnifiedBounds
+                    if (windowState.isLetterboxedForDisplayCutoutLw()) {
+                        Region letterboxBounds = getLetterboxBounds(windowState);
+                        nonMagnifiedBounds.op(letterboxBounds, Region.Op.UNION);
+                        availableBounds.op(letterboxBounds, Region.Op.DIFFERENCE);
+                    }
+
                     // Update accounted bounds
                     Region accountedBounds = mTempRegion2;
                     accountedBounds.set(mMagnificationRegion);
@@ -658,6 +665,25 @@
                 }
             }
 
+            private Region getLetterboxBounds(WindowState windowState) {
+                final AppWindowToken appToken = windowState.mAppToken;
+                if (appToken == null) {
+                    return new Region();
+                }
+
+                mDisplay.getRealSize(mTempPoint);
+                final Rect letterboxInsets = appToken.getLetterboxInsets();
+                final int screenWidth = mTempPoint.x;
+                final int screenHeight = mTempPoint.y;
+                final Rect nonLetterboxRect = mTempRect1;
+                final Region letterboxBounds = mTempRegion3;
+                nonLetterboxRect.set(0, 0, screenWidth, screenHeight);
+                nonLetterboxRect.inset(letterboxInsets);
+                letterboxBounds.set(0, 0, screenWidth, screenHeight);
+                letterboxBounds.op(nonLetterboxRect, Region.Op.DIFFERENCE);
+                return letterboxBounds;
+            }
+
             public void onRotationChangedLocked() {
                 // If we are showing the magnification border, hide it immediately so
                 // the user does not see strange artifacts during rotation. The screenshot