Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db9ea13d authored by Melody Hsu's avatar Melody Hsu
Browse files

Remove most uses of ScreenCapture#captureDisplay.

Replace with methods that use ScreenCapture#captureLayers so
ScreenCapture#captureDisplay can be removed. Usages in ColorFade
are not removed due to b/301083608.

Bug: 293445881
Test: Rotate screen with wm.debug.shell disabled
Test: Lock and unlock device
Test: Take screenshots
Test: atest AccessibilityTakeScreenshotTest
Change-Id: I71ce63421e018342111d235521b0486ae23840e4
parent ef8cae9e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -32,3 +32,10 @@ flag {
    description: "Enable public API for Window Surfaces"
    bug: "287076178"
}

flag {
    namespace: "window_surfaces"
    name: "remove_capture_display"
    description: "Remove uses of ScreenCapture#captureDisplay"
    bug: "293445881"
}
 No newline at end of file
+76 −30
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCE
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;

import static com.android.window.flags.Flags.removeCaptureDisplay;

import android.accessibilityservice.AccessibilityGestureEvent;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
@@ -1444,8 +1446,29 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
                    AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
            return;
        }

        final long identity = Binder.clearCallingIdentity();
        if (removeCaptureDisplay()) {
            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);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        } else {
            try {
                mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
                    final ScreenshotHardwareBuffer screenshotBuffer = LocalServices
@@ -1454,16 +1477,20 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
                        sendScreenshotSuccess(screenshotBuffer, callback);
                    } else {
                        sendScreenshotFailure(
                            AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
                                AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
                                callback);
                    }
                }, null).recycleOnUse());
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    private void sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer,
            RemoteCallback callback) {
        if (removeCaptureDisplay()) {
            mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
                final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
                final ParcelableColorSpace colorSpace =
                        new ParcelableColorSpace(screenshotBuffer.getColorSpace());
@@ -1480,6 +1507,25 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
                // Send back the result.
                callback.sendResult(payload);
                hardwareBuffer.close();
            }, null).recycleOnUse());
        } else {
            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());

            // Send back the result.
            callback.sendResult(payload);
            hardwareBuffer.close();
        }
    }

    private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode,
+15 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATI
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.utils.CoordinateTransforms.computeRotationMatrix;
import static com.android.window.flags.Flags.removeCaptureDisplay;

import android.animation.ArgbEvaluator;
import android.content.Context;
@@ -170,7 +171,7 @@ class ScreenRotationAnimation {

        try {
            final ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer;
            if (isSizeChanged) {
            if (isSizeChanged && !removeCaptureDisplay()) {
                final DisplayAddress address = displayInfo.address;
                if (!(address instanceof DisplayAddress.Physical)) {
                    Slog.e(TAG, "Display does not have a physical address: " + displayId);
@@ -196,6 +197,19 @@ class ScreenRotationAnimation {
                                .setHintForSeamlessTransition(true)
                                .build();
                screenshotBuffer = ScreenCapture.captureDisplay(captureArgs);
            } else if (isSizeChanged) {
                // Temporarily not skip screenshot for the rounded corner overlays and screenshot
                // the whole display to include the rounded corner overlays.
                setSkipScreenshotForRoundedCornerOverlays(false, t);
                ScreenCapture.LayerCaptureArgs captureArgs =
                        new ScreenCapture.LayerCaptureArgs.Builder(
                                displayContent.getSurfaceControl())
                                .setCaptureSecureLayers(true)
                                .setAllowProtected(true)
                                .setSourceCrop(new Rect(0, 0, width, height))
                                .setHintForSeamlessTransition(true)
                                .build();
                screenshotBuffer = ScreenCapture.captureLayers(captureArgs);
            } else {
                ScreenCapture.LayerCaptureArgs captureArgs =
                        new ScreenCapture.LayerCaptureArgs.Builder(
+9 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.view.SurfaceControlViewHost;
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;
@@ -955,6 +956,14 @@ public abstract class WindowManagerInternal {
    /** Returns the SurfaceControl accessibility services should use for accessibility overlays. */
    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.
     *
+6 −0
Original line number Diff line number Diff line
@@ -8518,6 +8518,12 @@ public class WindowManagerService extends IWindowManager.Stub
            return null;
        }

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