WM: Fix Letterbox placement

The letterbox is still being placed as if there were
no surface hierarchy. It is now attached to the AppWindowToken,
and when that is not positioned at (0,0), the Letterbox is
placed at the wrong place.

Instead, we now keep track of where the Letterbox is attached
to the hierarchy and offset it accordingly.

Test: Put the phone in seascape, open a max aspect ratio activity, go home. Verify the wallpaper does not flicker though the letterbox.
Bug: 120129697
Change-Id: I16068c62c11c8a1f4814405c0340600397db3fd4
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8624bff..ca306aa 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1702,7 +1702,8 @@
             if (mLetterbox == null) {
                 mLetterbox = new Letterbox(() -> makeChildSurface(null));
             }
-            mLetterbox.layout(getParent().getBounds(), w.getFrameLw());
+            getPosition(mTmpPoint);
+            mLetterbox.layout(getParent().getBounds(), w.getFrameLw(), mTmpPoint);
         } else if (mLetterbox != null) {
             mLetterbox.hide();
         }
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index ded45c9..650d0be 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -37,6 +37,7 @@
 import android.annotation.CallSuper;
 import android.app.WindowConfiguration;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
 
@@ -243,6 +244,14 @@
     }
 
     /**
+     * Sets {@code out} to the top-left corner of the bounds as returned by {@link #getBounds()}.
+     */
+    public void getPosition(Point out) {
+        Rect bounds = getBounds();
+        out.set(bounds.left, bounds.top);
+    }
+
+    /**
      * Returns the bounds requested on this container. These may not be the actual bounds the
      * container ends up with due to policy constraints. The {@link Rect} handed back is
      * shared for all calls to this method and should not be modified.
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 1a2aa2f..33ff194 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -18,6 +18,7 @@
 
 import static android.view.SurfaceControl.HIDDEN;
 
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.view.SurfaceControl;
 
@@ -30,6 +31,7 @@
 public class Letterbox {
 
     private static final Rect EMPTY_RECT = new Rect();
+    private static final Point ZERO_POINT = new Point(0, 0);
 
     private final Supplier<SurfaceControl.Builder> mFactory;
     private final Rect mOuter = new Rect();
@@ -53,14 +55,19 @@
      * frames will be covered by black color surfaces.
      *
      * The caller must use {@link #applySurfaceChanges} to apply the new layout to the surface.
-     *
      * @param outer the outer frame of the letterbox (this frame will be black, except the area
-     *              that intersects with the {code inner} frame).
-     * @param inner the inner frame of the letterbox (this frame will be clear)
+     *              that intersects with the {code inner} frame), in global coordinates
+     * @param inner the inner frame of the letterbox (this frame will be clear), in global
+     *              coordinates
+     * @param surfaceOrigin the origin of the surface factory in global coordinates
      */
-    public void layout(Rect outer, Rect inner) {
+    public void layout(Rect outer, Rect inner, Point surfaceOrigin) {
         mOuter.set(outer);
         mInner.set(inner);
+        mOuter.offset(-surfaceOrigin.x, -surfaceOrigin.y);
+        mInner.offset(-surfaceOrigin.x, -surfaceOrigin.y);
+        outer = mOuter;
+        inner = mInner;
 
         mTop.layout(outer.left, outer.top, inner.right, inner.top);
         mLeft.layout(outer.left, inner.top, inner.left, outer.bottom);
@@ -94,7 +101,7 @@
      * The caller must use {@link #applySurfaceChanges} to apply the new layout to the surface.
      */
     public void hide() {
-        layout(EMPTY_RECT, EMPTY_RECT);
+        layout(EMPTY_RECT, EMPTY_RECT, ZERO_POINT);
     }
 
     /**