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

Commit 4d1ac039 authored by Patrick Williams's avatar Patrick Williams
Browse files

Implement ScreenCapture system API

Bug: 370855681
Flag: com.android.graphics.surfaceflinger.flags.readback_screenshot
Test: atest CtsWindowManagerDeviceOther:android.server.wm.other.ScreenCaptureTest
Change-Id: I59cd630cd179964e00e14aa5fb3981db6a66b91c
parent 5e116051
Loading
Loading
Loading
Loading
+23 −12
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
package android.gui;

import android.gui.ARect;
import android.gui.CaptureMode;
import android.gui.ProtectedLayerMode;
import android.gui.SecureLayerMode;

// Common arguments for capturing content on-screen
parcelable CaptureArgs {
@@ -34,8 +37,10 @@ parcelable CaptureArgs {
    // Scale in the y-direction for the screenshotted result.
    float frameScaleY = 1.0f;

    // True if capturing secure layers is permitted
    boolean captureSecureLayers = false;
    // Specifies how to handle secure layers. If the client wants DPU composition only,
    // they should specify SecureLayerMode.Error. Otherwise, set to SecureLayerMode.Redact (default)
    // to redact secure layers or SecureLayerMode.Capture to capture them.
    SecureLayerMode secureLayerMode = SecureLayerMode.Redact;

    // UID whose content we want to screenshot
    int uid = UNSET_UID;
@@ -47,13 +52,10 @@ parcelable CaptureArgs {
    // NOTE: In normal cases, we want the screen to be captured in display's colorspace.
    int /*ui::Dataspace*/ dataspace = 0;

    // The receiver of the capture can handle protected buffer. A protected buffer has
    // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour.
    // Any read/write access from unprotected context will result in undefined behaviour.
    // Protected contents are typically DRM contents. This has no direct implication to the
    // secure property of the surface, which is specified by the application explicitly to avoid
    // the contents being accessed/captured by screenshot or unsecure display.
    boolean allowProtected = false;
    // Specifies how to handle protected layers. A protected buffer has GRALLOC_USAGE_PROTECTED
    // usage bit. If the client wants DPU composition only, they should specify
    // ProtectedLayerMode.Error. Otherwise, set to ProtectedLayerMode.Redact (default).
    ProtectedLayerMode protectedLayerMode = ProtectedLayerMode.Redact;

    // True if the content should be captured in grayscale
    boolean grayscale = false;
@@ -65,9 +67,18 @@ parcelable CaptureArgs {
    // The canonical example would be screen rotation - in such a case any color shift in the
    // screenshot is a detractor so composition in the display's colorspace is required.
    // Otherwise, the system may choose a colorspace that is more appropriate for use-cases
    // such as file encoding or for blending HDR content into an ap's UI, where the display's
    // such as file encoding or for blending HDR content into an app's UI, where the display's
    // exact colorspace is not an appropriate intermediate result.
    // Note that if the caller is requesting a specific dataspace, this hint does nothing.
    boolean hintForSeamlessTransition = false;
}
    boolean preserveDisplayColors = false;

    // Specifies the capture mode. CaptureMode.None is the default. It uses the GPU path and
    // applies any optimizations such as DPU if possible. CaptureMode.RequireOptimized attempts
    // to use the DPU optimized path; if not possible, a screenshot error is returned.
    CaptureMode captureMode = CaptureMode.None;

    // If true, the system renders the buffer in display installation orientation.
    boolean useDisplayInstallationOrientation = false;
    // If true, the screenshot will include system overlay layers, such as the screen decor layers.
    boolean includeAllLayers = false;
}
+40 −0
Original line number Diff line number Diff line
package android.gui;

/**
 * Specifies the requested capture mode for a screenshot operation.
 * This allows clients to indicate their preference for how the screenshot is captured,
 * particularly to request an optimized path if available and its constraints are acceptable.
 */
enum CaptureMode {
    /**
     * Default capture mode.
     * Uses the standard screenshot path, which may involve GPU composition or other
     * optimized paths if possible. This mode typically allows for more flexibility,
     * such as layer exclusion or redaction of secure content.
     */
    None = 0,

    /**
     * Requires the system to use an optimized capture path, such as DPU (Display
     * Processing Unit) readback. This path is designed for minimal performance and
     * power impact, making it suitable for frequent captures.
     *
     * Constraints when using RequireOptimized:
     * - The content is captured exactly as presented on the display.
     * - Layers generally cannot be excluded (e.g., screen decorations like rounded
     *   corners or camera cutouts might be included if they are part of the
     *   final displayed image).
     * - Secure layers: If present, they must be captured. If capturing secure
     *   layers is not permitted by policy or not possible with the optimized path,
     *   the operation will fail.
     * - Protected layers: If present, the screenshot operation will fail as these
     *   cannot be captured by the optimized path.
     *
     * If the optimized path cannot satisfy the request under these constraints
     * (e.g., due to the presence of protected layers, or if the hardware path
     * is unavailable or cannot fulfill the request for other reasons), the
     * screenshot operation will return an error. It will NOT automatically
     * fall back to the 'None' behavior.
     */
    RequireOptimized = 1
}
+13 −0
Original line number Diff line number Diff line
package android.gui;

/**
 * Defines how protected layers are handled during screen capture.
 */
enum ProtectedLayerMode {
    /** When a protected layer is encountered, redact its content by blacking out the layer. */
    Redact = 0,
    /** When a protected layer is encountered, capture its content. */
    Capture = 1,
    /** When a protected layer is encountered, throw an error. */
    Error = 2
}
+13 −0
Original line number Diff line number Diff line
package android.gui;

/**
 * Defines how secure layers are handled during screen capture.
 */
enum SecureLayerMode {
    /** When a secure layer is encountered, redact its content, by blacking out the layer. */
    Redact = 0,
    /** When a secure layer is encountered, attempt to capture its content. */
    Capture = 1,
    /** When a secure layer is encountered, return an error. */
    Error = 2
}
+1 −1
Original line number Diff line number Diff line
@@ -355,7 +355,7 @@ void RegionSamplingThread::captureSample() {
                           .disableBlur = true,
                           .isGrayscale = false,
                           .isSecure = true,
                           .seamlessTransition = false,
                           .preserveDisplayColors = false,
                           .debugName = "RegionSampling"};

    std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
Loading