From cc03f08373b8aa98a0ead51d23908c8a5d4cc37f Mon Sep 17 00:00:00 2001
From: Riddle Hsu <riddlehsu@google.com>
Date: Wed, 29 May 2024 17:11:15 +0800
Subject: [PATCH] Use non-protected screenshot buffer to calculate animation
 color

The screenshot for animation needs to be "setAllowProtected(true)",
otherwise the protected area will be blank. But it is unable to
be used to extract color because protected content is not readable.

To avoid the background rotation animation always showing black
color in this case (it looks flickering if the main color of screen
is light), use the source surface with excluding protected content
to calculate the color.

Bug: 342984506
Test: Enable auto rotation, home rotation.
      Set wallpaper to white color.
      Play DRM protected video in PiP mode.
      Rotate the device.
      The animation background should be white.
Change-Id: I346c9683e2c58891103031bf9adf662a7044132c
---
 .../internal/policy/TransitionAnimation.java      | 15 +++++++++++++++
 .../shell/transition/ScreenRotationAnimation.java |  2 +-
 .../java/com/android/server/wm/Transition.java    |  2 +-
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 2f09a5550fd4..66b2a9c8a424 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -1299,6 +1299,21 @@ public class TransitionAnimation {
                 == HardwareBuffer.USAGE_PROTECTED_CONTENT;
     }
 
+    /**
+     * Returns the luminance in 0~1. The surface control is the source of the hardware buffer,
+     * which will be used if the buffer is protected from reading.
+     */
+    public static float getBorderLuma(@NonNull HardwareBuffer hwBuffer,
+            @NonNull ColorSpace colorSpace, @NonNull SurfaceControl sourceSurfaceControl) {
+        if (hasProtectedContent(hwBuffer)) {
+            // The buffer cannot be read. Capture another buffer which excludes protected content
+            // from the source surface.
+            return getBorderLuma(sourceSurfaceControl, hwBuffer.getWidth(), hwBuffer.getHeight());
+        }
+        // Use the existing buffer directly.
+        return getBorderLuma(hwBuffer, colorSpace);
+    }
+
     /** Returns the luminance in 0~1. */
     public static float getBorderLuma(SurfaceControl surfaceControl, int w, int h) {
         final ScreenCapture.ScreenshotHardwareBuffer buffer =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 9ce22094d56b..e196254628d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -167,7 +167,7 @@ class ScreenRotationAnimation {
                 t.show(mScreenshotLayer);
                 if (!isCustomRotate()) {
                     mStartLuma = TransitionAnimation.getBorderLuma(hardwareBuffer,
-                            screenshotBuffer.getColorSpace());
+                            screenshotBuffer.getColorSpace(), mSurfaceControl);
                 }
                 hardwareBuffer.close();
             }
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 7ec31d5a8ecb..29a61e6d0071 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -3757,7 +3757,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
             if (changeInfo.mRotation != wc.mDisplayContent.getRotation()) {
                 // This isn't cheap, so only do it for rotation change.
                 changeInfo.mSnapshotLuma = TransitionAnimation.getBorderLuma(
-                        buffer, screenshotBuffer.getColorSpace());
+                        buffer, screenshotBuffer.getColorSpace(), wc.mSurfaceControl);
             }
             SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get();
             TransitionAnimation.configureScreenshotLayer(t, snapshotSurface, screenshotBuffer);
-- 
GitLab