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);
}