Merge "Revert "Remove usages of ScreenCapture#captureDisplay."" into main
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index b1aa7de..4700720 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -32,6 +32,7 @@
 import android.view.SurfaceControl.RefreshRateRange;
 import android.view.SurfaceControl.Transaction;
 import android.window.DisplayWindowPolicyController;
+import android.window.ScreenCapture;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -111,6 +112,25 @@
     public abstract void unregisterDisplayGroupListener(DisplayGroupListener listener);
 
     /**
+     * Screenshot for internal system-only use such as rotation, etc.  This method includes
+     * secure layers and the result should never be exposed to non-system applications.
+     * This method does not apply any rotation and provides the output in natural orientation.
+     *
+     * @param displayId The display id to take the screenshot of.
+     * @return The buffer or null if we have failed.
+     */
+    public abstract ScreenCapture.ScreenshotHardwareBuffer systemScreenshot(int displayId);
+
+    /**
+     * General screenshot functionality that excludes secure layers and applies appropriate
+     * rotation that the device is currently in.
+     *
+     * @param displayId The display id to take the screenshot of.
+     * @return The buffer or null if we have failed.
+     */
+    public abstract ScreenCapture.ScreenshotHardwareBuffer userScreenshot(int displayId);
+
+    /**
      * Returns information about the specified logical display.
      *
      * @param displayId The logical display id.
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 44ffb51..05b6eb4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -56,6 +56,7 @@
 import android.graphics.Region;
 import android.hardware.HardwareBuffer;
 import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -97,6 +98,7 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.LocalServices;
 import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
 import com.android.server.accessibility.magnification.MagnificationProcessor;
 import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -1439,24 +1441,19 @@
                     AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
             return;
         }
+
         final long identity = Binder.clearCallingIdentity();
         try {
-            ScreenCapture.ScreenCaptureListener screenCaptureListener = new
-                    ScreenCapture.ScreenCaptureListener(
-                    (screenshotBuffer, result) -> {
-                        if (screenshotBuffer != null && result == 0) {
-                            sendScreenshotSuccess(screenshotBuffer, callback);
-                        } else {
-                            sendScreenshotFailure(
-                                    AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
-                                    callback);
-                        }
-                    }
-            );
-            mWindowManagerService.captureDisplay(displayId, null, screenCaptureListener);
-        } catch (Exception e) {
-            sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
-                    callback);
+            mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
+                final ScreenshotHardwareBuffer screenshotBuffer = LocalServices
+                        .getService(DisplayManagerInternal.class).userScreenshot(displayId);
+                if (screenshotBuffer != null) {
+                    sendScreenshotSuccess(screenshotBuffer, callback);
+                } else {
+                    sendScreenshotFailure(
+                            AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
+                }
+            }, null).recycleOnUse());
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1464,24 +1461,22 @@
 
     private void sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer,
             RemoteCallback callback) {
-        mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
-            final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
-            final ParcelableColorSpace colorSpace =
-                    new ParcelableColorSpace(screenshotBuffer.getColorSpace());
+        final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
+        final ParcelableColorSpace colorSpace =
+                new ParcelableColorSpace(screenshotBuffer.getColorSpace());
 
-            final Bundle payload = new Bundle();
-            payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
-                    AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
-            payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
-                    hardwareBuffer);
-            payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
-            payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
-                    SystemClock.uptimeMillis());
+        final Bundle payload = new Bundle();
+        payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
+                AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
+        payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
+                hardwareBuffer);
+        payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
+        payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
+                SystemClock.uptimeMillis());
 
-            // Send back the result.
-            callback.sendResult(payload);
-            hardwareBuffer.close();
-        }, null).recycleOnUse());
+        // Send back the result.
+        callback.sendResult(payload);
+        hardwareBuffer.close();
     }
 
     private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode,
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 2e5f2dc..0d6635d 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -43,7 +43,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.wm.WindowManagerInternal;
 
 import libcore.io.Streams;
 
@@ -568,21 +567,8 @@
     }
 
     private ScreenCapture.ScreenshotHardwareBuffer captureScreen() {
-        WindowManagerInternal windowManagerService = LocalServices.getService(
-                WindowManagerInternal.class);
-        ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer;
-        ScreenCapture.SynchronousScreenCaptureListener screenCaptureListener =
-                ScreenCapture.createSyncCaptureListener();
-        ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
-                .setCaptureSecureLayers(true)
-                .setAllowProtected(true)
-                .build();
-        try {
-            windowManagerService.captureDisplay(mDisplayId, captureArgs, screenCaptureListener);
-            screenshotBuffer = screenCaptureListener.getBuffer();
-        } catch (Exception e) {
-            screenshotBuffer = null;
-        }
+        ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer =
+                mDisplayManagerInternal.systemScreenshot(mDisplayId);
         if (screenshotBuffer == null) {
             Slog.e(TAG, "Failed to take screenshot. Buffer is null");
             return null;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index df45001..46ef6c3 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -137,6 +137,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.RefreshRateRange;
 import android.window.DisplayWindowPolicyController;
+import android.window.ScreenCapture;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -2673,6 +2674,42 @@
         return null;
     }
 
+    private ScreenCapture.ScreenshotHardwareBuffer systemScreenshotInternal(int displayId) {
+        final ScreenCapture.DisplayCaptureArgs captureArgs;
+        synchronized (mSyncRoot) {
+            final IBinder token = getDisplayToken(displayId);
+            if (token == null) {
+                return null;
+            }
+            final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId);
+            if (logicalDisplay == null) {
+                return null;
+            }
+
+            final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
+            captureArgs = new ScreenCapture.DisplayCaptureArgs.Builder(token)
+                    .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
+                    .setCaptureSecureLayers(true)
+                    .setAllowProtected(true)
+                    .build();
+        }
+        return ScreenCapture.captureDisplay(captureArgs);
+    }
+
+    private ScreenCapture.ScreenshotHardwareBuffer userScreenshotInternal(int displayId) {
+        synchronized (mSyncRoot) {
+            final IBinder token = getDisplayToken(displayId);
+            if (token == null) {
+                return null;
+            }
+
+            final ScreenCapture.DisplayCaptureArgs captureArgs =
+                    new ScreenCapture.DisplayCaptureArgs.Builder(token)
+                            .build();
+            return ScreenCapture.captureDisplay(captureArgs);
+        }
+    }
+
     @VisibleForTesting
     DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal(
             int displayId) {
@@ -4441,6 +4478,16 @@
         }
 
         @Override
+        public ScreenCapture.ScreenshotHardwareBuffer systemScreenshot(int displayId) {
+            return systemScreenshotInternal(displayId);
+        }
+
+        @Override
+        public ScreenCapture.ScreenshotHardwareBuffer userScreenshot(int displayId) {
+            return userScreenshotInternal(displayId);
+        }
+
+        @Override
         public DisplayInfo getDisplayInfo(int displayId) {
             return getDisplayInfoInternal(displayId, Process.myUid());
         }
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 2c142cb..bbb8563 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -40,9 +40,11 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
+import android.os.IBinder;
 import android.os.Trace;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
+import android.view.DisplayAddress;
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.Surface.OutOfResourcesException;
@@ -55,6 +57,7 @@
 import com.android.internal.R;
 import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.display.DisplayControl;
 import com.android.server.wm.SurfaceAnimator.AnimationType;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 
@@ -168,10 +171,32 @@
         try {
             final ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer;
             if (isSizeChanged) {
+                final DisplayAddress address = displayInfo.address;
+                if (!(address instanceof DisplayAddress.Physical)) {
+                    Slog.e(TAG, "Display does not have a physical address: " + displayId);
+                    return;
+                }
+                final DisplayAddress.Physical physicalAddress =
+                        (DisplayAddress.Physical) address;
+                final IBinder displayToken = DisplayControl.getPhysicalDisplayToken(
+                        physicalAddress.getPhysicalDisplayId());
+                if (displayToken == null) {
+                    Slog.e(TAG, "Display token is null.");
+                    return;
+                }
                 // Temporarily not skip screenshot for the rounded corner overlays and screenshot
                 // the whole display to include the rounded corner overlays.
                 setSkipScreenshotForRoundedCornerOverlays(false, t);
-            }
+                mRoundedCornerOverlay = displayContent.findRoundedCornerOverlays();
+                final ScreenCapture.DisplayCaptureArgs captureArgs =
+                        new ScreenCapture.DisplayCaptureArgs.Builder(displayToken)
+                                .setSourceCrop(new Rect(0, 0, width, height))
+                                .setAllowProtected(true)
+                                .setCaptureSecureLayers(true)
+                                .setHintForSeamlessTransition(true)
+                                .build();
+                screenshotBuffer = ScreenCapture.captureDisplay(captureArgs);
+            } else {
                 ScreenCapture.LayerCaptureArgs captureArgs =
                         new ScreenCapture.LayerCaptureArgs.Builder(
                                 displayContent.getSurfaceControl())
@@ -181,6 +206,7 @@
                                 .setHintForSeamlessTransition(true)
                                 .build();
                 screenshotBuffer = ScreenCapture.captureLayers(captureArgs);
+            }
 
             if (screenshotBuffer == null) {
                 Slog.w(TAG, "Unable to take screenshot of display " + displayId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index a4d43d8..9f1bccb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -45,7 +45,6 @@
 import android.view.WindowInfo;
 import android.view.WindowManager.DisplayImePolicy;
 import android.view.inputmethod.ImeTracker;
-import android.window.ScreenCapture;
 
 import com.android.internal.policy.KeyInterceptionInfo;
 import com.android.server.input.InputManagerService;
@@ -957,14 +956,6 @@
     public abstract SurfaceControl getA11yOverlayLayer(int displayId);
 
     /**
-     * Captures the entire display specified by the displayId using the args provided. If the args
-     * are null or if the sourceCrop is invalid or null, the entire display bounds will be captured.
-     */
-    public abstract void captureDisplay(int displayId,
-                                        @Nullable ScreenCapture.CaptureArgs captureArgs,
-                                        ScreenCapture.ScreenCaptureListener listener);
-
-    /**
      * Device has a software navigation bar (separate from the status bar) on specific display.
      *
      * @param displayId the id of display to check if there is a software navigation bar.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8fe104c..9a1920d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8415,12 +8415,6 @@
         }
 
         @Override
-        public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs,
-                                   ScreenCapture.ScreenCaptureListener listener) {
-            WindowManagerService.this.captureDisplay(displayId, captureArgs, listener);
-        }
-
-        @Override
         public boolean hasNavigationBar(int displayId) {
             return WindowManagerService.this.hasNavigationBar(displayId);
         }