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

Commit 7b85af82 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Expose ScreenCapture as a system api" into main

parents 522ba90e 36232b63
Loading
Loading
Loading
Loading
+32 −0
Original line number Original line Diff line number Diff line
@@ -19950,6 +19950,38 @@ package android.webkit {
package android.window {
package android.window {
  @FlaggedApi("com.android.graphics.surfaceflinger.flags.readback_screenshot") public class ScreenCapture {
    method public static void capture(@NonNull android.window.ScreenCapture.ScreenCaptureParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.window.ScreenCapture.ScreenCaptureResult,java.lang.Exception>);
    method public static boolean isScreenCaptureOptimizationEnabled();
  }
  @FlaggedApi("com.android.graphics.surfaceflinger.flags.readback_screenshot") public static final class ScreenCapture.ScreenCaptureParams implements android.os.Parcelable {
    method public int describeContents();
    method public int getCaptureMode();
    method public int getDisplayId();
    method public int getPixelFormat();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field public static final int CAPTURE_MODE_NONE = 0; // 0x0
    field public static final int CAPTURE_MODE_REQUIRE_OPTIMIZED = 1; // 0x1
    field @NonNull public static final android.os.Parcelable.Creator<android.window.ScreenCapture.ScreenCaptureParams> CREATOR;
  }
  @FlaggedApi("com.android.graphics.surfaceflinger.flags.readback_screenshot") public static final class ScreenCapture.ScreenCaptureParams.Builder {
    ctor public ScreenCapture.ScreenCaptureParams.Builder(@NonNull android.view.Display);
    method @NonNull public android.window.ScreenCapture.ScreenCaptureParams build();
    method @NonNull public android.window.ScreenCapture.ScreenCaptureParams.Builder setCaptureMode(int);
    method @NonNull public android.window.ScreenCapture.ScreenCaptureParams.Builder setPixelFormat(int);
  }
  @FlaggedApi("com.android.graphics.surfaceflinger.flags.readback_screenshot") public static final class ScreenCapture.ScreenCaptureResult implements android.os.Parcelable {
    ctor public ScreenCapture.ScreenCaptureResult(@NonNull android.graphics.ColorSpace, @NonNull android.hardware.HardwareBuffer);
    method public int describeContents();
    method @NonNull public android.graphics.ColorSpace getColorSpace();
    method @NonNull public android.hardware.HardwareBuffer getHardwareBuffer();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.window.ScreenCapture.ScreenCaptureResult> CREATOR;
  }
  public abstract class TaskFpsCallback {
  public abstract class TaskFpsCallback {
    ctor public TaskFpsCallback();
    ctor public TaskFpsCallback();
    method public abstract void onFpsReported(float);
    method public abstract void onFpsReported(float);
+48 −14
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.graphics.surfaceflinger.flags.Flags.FLAG_READBACK_SCRE
import android.annotation.FlaggedApi;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.graphics.ColorSpace;
import android.graphics.ColorSpace;
import android.graphics.ParcelableColorSpace;
import android.graphics.ParcelableColorSpace;
import android.hardware.HardwareBuffer;
import android.hardware.HardwareBuffer;
@@ -28,6 +29,7 @@ import android.os.OutcomeReceiver;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.view.Display;
import android.view.Display;
import android.view.IWindowManager;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerGlobal;
@@ -36,16 +38,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;



/**
/**
 * Provides an API for capturing the contents of a display.
 * Provides an API for capturing the contents of a display.
 *
 *
 * <p>This class allows capturing the screen content based on specified parameters and
 * <p>This class allows capturing the screen content based on specified parameters and returns the
 * returns the result asynchronously. It defines parameters for the capture via
 * result asynchronously. It defines parameters for the capture via {@link ScreenCaptureParams} and
 * {@link ScreenCaptureParams} and the result via {@link ScreenCaptureResult}.</p>
 * the result via {@link ScreenCaptureResult}.
 *
 *
 * @hide
 * @hide
 */
 */
@SystemApi
@FlaggedApi(FLAG_READBACK_SCREENSHOT)
@FlaggedApi(FLAG_READBACK_SCREENSHOT)
public class ScreenCapture {
public class ScreenCapture {


@@ -84,6 +86,7 @@ public class ScreenCapture {
         * @hide
         * @hide
         */
         */
        public static final int SECURE_CONTENT_POLICY_CAPTURE = 1;
        public static final int SECURE_CONTENT_POLICY_CAPTURE = 1;

        /**
        /**
         * When a secure window is encountered, throw an exception.
         * When a secure window is encountered, throw an exception.
         *
         *
@@ -176,6 +179,7 @@ public class ScreenCapture {
         * Returns the policy for handling secure content.
         * Returns the policy for handling secure content.
         *
         *
         * @see Builder#setSecureContentPolicy(int)
         * @see Builder#setSecureContentPolicy(int)
         * @hide
         */
         */
        public @SecureContentPolicy int getSecureContentPolicy() {
        public @SecureContentPolicy int getSecureContentPolicy() {
            return mSecureContentPolicy;
            return mSecureContentPolicy;
@@ -185,6 +189,7 @@ public class ScreenCapture {
         * Returns the policy for handling protected content.
         * Returns the policy for handling protected content.
         *
         *
         * @see Builder#setProtectedContentPolicy(int)
         * @see Builder#setProtectedContentPolicy(int)
         * @hide
         */
         */
        public @ProtectedContentPolicy int getProtectedContentPolicy() {
        public @ProtectedContentPolicy int getProtectedContentPolicy() {
            return mProtectedContentPolicy;
            return mProtectedContentPolicy;
@@ -212,6 +217,7 @@ public class ScreenCapture {
         * Returns whether to use the display's native orientation for the capture.
         * Returns whether to use the display's native orientation for the capture.
         *
         *
         * @see Builder#setUseDisplayInstallationOrientation(boolean)
         * @see Builder#setUseDisplayInstallationOrientation(boolean)
         * @hide
         */
         */
        public boolean isUseDisplayInstallationOrientation() {
        public boolean isUseDisplayInstallationOrientation() {
            return mUseDisplayInstallationOrientation;
            return mUseDisplayInstallationOrientation;
@@ -221,6 +227,7 @@ public class ScreenCapture {
         * Returns whether to include system overlays in the capture.
         * Returns whether to include system overlays in the capture.
         *
         *
         * @see Builder#setIncludeSystemOverlays(boolean)
         * @see Builder#setIncludeSystemOverlays(boolean)
         * @hide
         */
         */
        public boolean isIncludeSystemOverlays() {
        public boolean isIncludeSystemOverlays() {
            return mIncludeSystemOverlays;
            return mIncludeSystemOverlays;
@@ -230,6 +237,7 @@ public class ScreenCapture {
         * Returns whether to preserve the display's colors in the capture.
         * Returns whether to preserve the display's colors in the capture.
         *
         *
         * @see Builder#setPreserveDisplayColors(boolean)
         * @see Builder#setPreserveDisplayColors(boolean)
         * @hide
         */
         */
        public boolean isPreserveDisplayColors() {
        public boolean isPreserveDisplayColors() {
            return mPreserveDisplayColors;
            return mPreserveDisplayColors;
@@ -320,10 +328,11 @@ public class ScreenCapture {
            /**
            /**
             * Specifies how to handle secure windows.
             * Specifies how to handle secure windows.
             *
             *
             * <p>A secure window is the window with
             * <p>A secure window is a window with {@link
             * {@link android.view.WindowManager.LayoutParams.FLAG_SECURE} set.}
             * android.view.WindowManager.LayoutParams.FLAG_SECURE} set.
             *
             *
             * <p>Default value is {@link #SECURE_CONTENT_POLICY_REDACT}.
             * <p>Default value is {@link #SECURE_CONTENT_POLICY_REDACT}.
             *
             * @hide
             * @hide
             */
             */
            public @NonNull Builder setSecureContentPolicy(
            public @NonNull Builder setSecureContentPolicy(
@@ -335,9 +344,10 @@ public class ScreenCapture {
            /**
            /**
             * Specifies how to handle protected windows.
             * Specifies how to handle protected windows.
             *
             *
             * <p>A protected window is the window that has buffers with protected bit set.
             * <p>A protected window is a window that has buffers with the protected bit set.
             *
             *
             * <p>Default value is {@link #PROTECTED_CONTENT_POLICY_REDACT}.
             * <p>Default value is {@link #PROTECTED_CONTENT_POLICY_REDACT}.
             *
             * @hide
             * @hide
             */
             */
            public @NonNull Builder setProtectedContentPolicy(
            public @NonNull Builder setProtectedContentPolicy(
@@ -371,10 +381,12 @@ public class ScreenCapture {
             * <p>If {@code true}, the screenshot will be oriented according to the display's
             * <p>If {@code true}, the screenshot will be oriented according to the display's
             * physical installation orientation, ignoring any current logical orientation.
             * physical installation orientation, ignoring any current logical orientation.
             *
             *
             * <p>If {@code false} (the default), the screenshot will be oriented according
             * <p>If {@code false}, the screenshot will be oriented according to the current logical
             * to the current logical orientation of the display, including any software rotation.
             * orientation of the display, including any software rotation.
             *
             *
             * <p>Default value is {@code false}
             * <p>Default value is {@code false}
             *
             * @hide
             */
             */
            public @NonNull Builder setUseDisplayInstallationOrientation(
            public @NonNull Builder setUseDisplayInstallationOrientation(
                    boolean useDisplayInstallationOrientation) {
                    boolean useDisplayInstallationOrientation) {
@@ -392,6 +404,8 @@ public class ScreenCapture {
             * user-visible content.
             * user-visible content.
             *
             *
             * <p>Default value is {@code false}
             * <p>Default value is {@code false}
             *
             * @hide
             */
             */
            public @NonNull Builder setIncludeSystemOverlays(boolean includeSystemOverlays) {
            public @NonNull Builder setIncludeSystemOverlays(boolean includeSystemOverlays) {
                mIncludeSystemOverlays = includeSystemOverlays;
                mIncludeSystemOverlays = includeSystemOverlays;
@@ -399,10 +413,12 @@ public class ScreenCapture {
            }
            }


            /**
            /**
             * Sets to true to preserves the native display colorspace. Useful for mixed HDR + SDR
             * Set to true to preserves the native display colorspace. Useful for mixed HDR + SDR
             * content, using identical processing as the display's.
             * content, using identical processing as the display's.
             *
             *
             * <p>Default value is {@code false}
             * <p>Default value is {@code false}
             *
             * @hide
             */
             */
            public @NonNull Builder setPreserveDisplayColors(boolean preserveDisplayColors) {
            public @NonNull Builder setPreserveDisplayColors(boolean preserveDisplayColors) {
                mPreserveDisplayColors = preserveDisplayColors;
                mPreserveDisplayColors = preserveDisplayColors;
@@ -509,6 +525,13 @@ public class ScreenCapture {
     */
     */
    public static final int SCREEN_CAPTURE_ERROR_SENSITIVE_CONTENT = 2;
    public static final int SCREEN_CAPTURE_ERROR_SENSITIVE_CONTENT = 2;


    /**
     * Screen capture failed due to missing permissions.
     *
     * @hide
     */
    public static final int SCREEN_CAPTURE_ERROR_MISSING_PERMISSIONS = 3;

    /** Capture a screenshot. */
    /** Capture a screenshot. */
    public static void capture(
    public static void capture(
            @NonNull ScreenCaptureParams params,
            @NonNull ScreenCaptureParams params,
@@ -521,8 +544,15 @@ public class ScreenCapture {
                    }
                    }


                    public void onFailure(@ScreenCaptureErrorCode int errorCode) {
                    public void onFailure(@ScreenCaptureErrorCode int errorCode) {
                        executor.execute(() -> receiver.onError(
                        Exception e;
                                new IllegalStateException("Failed to capture.")));
                        if (errorCode == SCREEN_CAPTURE_ERROR_MISSING_PERMISSIONS) {
                            e =
                                    new SecurityException(
                                            "Caller does not have READ_FRAME_BUFFER permission");
                        } else {
                            e = new IllegalStateException("Screen capture failed.");
                        }
                        executor.execute(() -> receiver.onError(e));
                    }
                    }
                };
                };
        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
@@ -534,8 +564,12 @@ public class ScreenCapture {
                        new IllegalStateException("Failed to retrieve WindowManagerService."));
                        new IllegalStateException("Failed to retrieve WindowManagerService."));
            }
            }
        } catch (RemoteException exception) {
        } catch (RemoteException exception) {
            receiver.onError(exception.rethrowFromSystemServer());
            receiver.onError(new RuntimeException(exception));
        }
    }
    }

    public static boolean isScreenCaptureOptimizationEnabled() {
        return SystemProperties.getBoolean("debug.sf.productionize_readback_screenshot", false);
    }
    }


    private ScreenCapture() {
    private ScreenCapture() {
+10 −1
Original line number Original line Diff line number Diff line
@@ -10315,8 +10315,17 @@ public class WindowManagerService extends IWindowManager.Stub
            @NonNull ScreenCapture.ScreenCaptureParams params,
            @NonNull ScreenCapture.ScreenCaptureParams params,
            @NonNull IScreenCaptureCallback callback) {
            @NonNull IScreenCaptureCallback callback) {
        if (!checkCallingPermission(READ_FRAME_BUFFER, "screenCapture()")) {
        if (!checkCallingPermission(READ_FRAME_BUFFER, "screenCapture()")) {
            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
            try {
                callback.onFailure(ScreenCapture.SCREEN_CAPTURE_ERROR_MISSING_PERMISSIONS);
            } catch (RemoteException remoteException) {
                Slog.e(
                        TAG,
                        "Failed to deliver screenshot permission error to client",
                        remoteException);
            }
            }
            return;
        }

        // Translate ScreenCaptureParams to DisplayCaptureArgs.
        // Translate ScreenCaptureParams to DisplayCaptureArgs.
        ScreenCaptureInternal.DisplayCaptureArgs.Builder argsBuilder =
        ScreenCaptureInternal.DisplayCaptureArgs.Builder argsBuilder =
                new ScreenCaptureInternal.DisplayCaptureArgs.Builder()
                new ScreenCaptureInternal.DisplayCaptureArgs.Builder()