Merge "Try crop letterbox prior than content insets" into udc-dev am: 8edd2ab2e6 am: 0ece582f7d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23382776

Change-Id: I9c27de5340253ad21a03bcabd5decb46167bcb5b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 52e17ca..f40874b 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -43,6 +43,7 @@
 import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
 import static com.android.internal.policy.DecorView.getNavigationBarRect;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
@@ -183,7 +184,7 @@
 
             // We consider nearly matched dimensions as there can be rounding errors and the user
             // won't notice very minute differences from scaling one dimension more than the other
-            final boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshot);
+            boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshot);
 
             // Keep a reference to it such that it doesn't get destroyed when finalized.
             SurfaceControl childSurfaceControl = new SurfaceControl.Builder(session)
@@ -199,8 +200,20 @@
             // still hidden.
             mTransaction.show(childSurfaceControl);
             if (aspectRatioMismatch) {
-                // Clip off ugly navigation bar.
-                final Rect crop = calculateSnapshotCrop();
+                Rect crop = null;
+                final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
+                if (letterboxInsets.left != 0 || letterboxInsets.top != 0
+                        || letterboxInsets.right != 0 || letterboxInsets.bottom != 0) {
+                    // Clip off letterbox.
+                    crop = calculateSnapshotCrop(letterboxInsets);
+                    // If the snapshot can cover the frame, then no need to draw background.
+                    aspectRatioMismatch = !isAspectRatioMatch(mFrame, crop);
+                }
+                // if letterbox doesn't match window frame, try crop by content insets
+                if (aspectRatioMismatch) {
+                    // Clip off ugly navigation bar.
+                    crop = calculateSnapshotCrop(mSnapshot.getContentInsets());
+                }
                 frame = calculateSnapshotFrame(crop);
                 mTransaction.setWindowCrop(childSurfaceControl, crop);
                 mTransaction.setPosition(childSurfaceControl, frame.left, frame.top);
@@ -242,14 +255,13 @@
 
         /**
          * Calculates the snapshot crop in snapshot coordinate space.
-         *
+         * @param insets Content insets or Letterbox insets
          * @return crop rect in snapshot coordinate space.
          */
-        Rect calculateSnapshotCrop() {
+        Rect calculateSnapshotCrop(@NonNull Rect insets) {
             final Rect rect = new Rect();
             final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
             rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
-            final Rect insets = mSnapshot.getContentInsets();
 
             final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
             final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
@@ -334,6 +346,15 @@
                         - ((float) frame.width() / frame.height())) <= 0.01f;
     }
 
+    private static boolean isAspectRatioMatch(Rect frame1, Rect frame2) {
+        if (frame1.isEmpty() || frame2.isEmpty()) {
+            return false;
+        }
+        return Math.abs(
+                ((float) frame2.width() / frame2.height())
+                        - ((float) frame1.width() / frame1.height())) <= 0.01f;
+    }
+
     /**
      * Get or create a TaskDescription from a RunningTaskInfo.
      */
diff --git a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
index 6764ac8..0361546 100644
--- a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
+++ b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
@@ -158,32 +158,42 @@
 
     @Test
     public void testCalculateSnapshotCrop() {
-        setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(0, 0, 100, 90), mSnapshotSurface.calculateSnapshotCrop());
+        final Rect contentInsets = new Rect(0, 10, 0, 10);
+        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(0, 0, 100, 90),
+                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
     }
 
     @Test
     public void testCalculateSnapshotCrop_taskNotOnTop() {
-        setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, new Rect(0, 50, 100, 150));
-        assertEquals(new Rect(0, 10, 100, 90), mSnapshotSurface.calculateSnapshotCrop());
+        final Rect contentInsets = new Rect(0, 10, 0, 10);
+        setupSurface(100, 100, contentInsets, 0, new Rect(0, 50, 100, 150));
+        assertEquals(new Rect(0, 10, 100, 90),
+                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
     }
 
     @Test
     public void testCalculateSnapshotCrop_navBarLeft() {
-        setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(10, 0, 100, 100), mSnapshotSurface.calculateSnapshotCrop());
+        final Rect contentInsets = new Rect(0, 10, 0, 0);
+        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(10, 0, 100, 100),
+                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
     }
 
     @Test
     public void testCalculateSnapshotCrop_navBarRight() {
-        setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(0, 0, 90, 100), mSnapshotSurface.calculateSnapshotCrop());
+        final Rect contentInsets = new Rect(0, 10, 10, 0);
+        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(0, 0, 90, 100),
+                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
     }
 
     @Test
     public void testCalculateSnapshotCrop_waterfall() {
-        setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(5, 0, 95, 90), mSnapshotSurface.calculateSnapshotCrop());
+        final Rect contentInsets = new Rect(5, 10, 5, 10);
+        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(5, 0, 95, 90),
+                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
     }
 
     @Test