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

Commit 2da90f79 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Remove rotation and use flag useIdentityTransform for screenshots."

parents 24f2922c ca2eb018
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ interface IUiAutomationConnection {
    boolean injectInputEvent(in InputEvent event, boolean sync);
    void syncInputTransactions();
    boolean setRotation(int rotation);
    Bitmap takeScreenshot(in Rect crop, int rotation);
    Bitmap takeScreenshot(in Rect crop);
    boolean clearWindowContentFrameStats(int windowId);
    WindowContentFrameStats getWindowContentFrameStats(int windowId);
    void clearWindowAnimationFrameStats();
+1 −1
Original line number Diff line number Diff line
@@ -903,7 +903,7 @@ public final class UiAutomation {
        try {
            // Calling out without a lock held.
            screenShot = mUiAutomationConnection.takeScreenshot(
                    new Rect(0, 0, displaySize.x, displaySize.y), rotation);
                    new Rect(0, 0, displaySize.x, displaySize.y));
            if (screenShot == null) {
                return null;
            }
+10 −2
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
    }

    @Override
    public Bitmap takeScreenshot(Rect crop, int rotation) {
    public Bitmap takeScreenshot(Rect crop) {
        synchronized (mLock) {
            throwIfCalledByNotTrustedUidLocked();
            throwIfShutdownLocked();
@@ -190,7 +190,15 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
        try {
            int width = crop.width();
            int height = crop.height();
            return SurfaceControl.screenshot(crop, width, height, rotation);
            final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
            final SurfaceControl.DisplayCaptureArgs captureArgs =
                    new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
                            .setSourceCrop(crop)
                            .setSize(width, height)
                            .build();
            final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
                    SurfaceControl.captureDisplay(captureArgs);
            return screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
+29 −138
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@ import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.SurfaceControlProto.HASH_CODE;
import static android.view.SurfaceControlProto.NAME;

@@ -590,6 +588,26 @@ public final class SurfaceControl implements Parcelable {
        public boolean containsSecureLayers() {
            return mContainsSecureLayers;
        }

        /**
         * Copy content of ScreenshotHardwareBuffer into a hardware bitmap and return it.
         * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
         * into
         * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
         *
         * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
         * directly
         * use the {@link HardwareBuffer} directly.
         *
         * @return Bitmap generated from the {@link HardwareBuffer}
         */
        public Bitmap asBitmap() {
            if (mHardwareBuffer == null) {
                Log.w(TAG, "Failed to take screenshot. Null screenshot object");
                return null;
            }
            return Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace);
        }
    }

    /**
@@ -597,7 +615,7 @@ public final class SurfaceControl implements Parcelable {
     * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
     * @hide
     */
    public abstract static class CaptureArgs {
    private abstract static class CaptureArgs {
        private final int mPixelFormat;
        private final Rect mSourceCrop = new Rect();
        private final float mFrameScale;
@@ -615,7 +633,7 @@ public final class SurfaceControl implements Parcelable {
         *
         * @param <T> A builder that extends {@link Builder}
         */
        public abstract static class Builder<T extends Builder<T>> {
        abstract static class Builder<T extends Builder<T>> {
            private int mPixelFormat = PixelFormat.RGBA_8888;
            private final Rect mSourceCrop = new Rect();
            private float mFrameScale = 1;
@@ -675,7 +693,6 @@ public final class SurfaceControl implements Parcelable {
        private final int mWidth;
        private final int mHeight;
        private final boolean mUseIdentityTransform;
        private final int mRotation;

        private DisplayCaptureArgs(Builder builder) {
            super(builder);
@@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable {
            mWidth = builder.mWidth;
            mHeight = builder.mHeight;
            mUseIdentityTransform = builder.mUseIdentityTransform;
            mRotation = builder.mRotation;
        }

        /**
@@ -694,7 +710,6 @@ public final class SurfaceControl implements Parcelable {
            private int mWidth;
            private int mHeight;
            private boolean mUseIdentityTransform;
            private @Surface.Rotation int mRotation = Surface.ROTATION_0;

            /**
             * Construct a new {@link LayerCaptureArgs} with the set parameters. The builder
@@ -736,26 +751,16 @@ public final class SurfaceControl implements Parcelable {
            }

            /**
             * Replace whatever transformation (rotation, scaling, translation) the surface
             * layers are currently using with the identity transformation while taking the
             * screenshot.
             * Replace the rotation transform of the display with the identity transformation while
             * taking the screenshot. This ensures the screenshot is taken in the ROTATION_0
             * orientation. Set this value to false if the screenshot should be taken in the
             * current screen orientation.
             */
            public Builder setUseIdentityTransform(boolean useIdentityTransform) {
                mUseIdentityTransform = useIdentityTransform;
                return this;
            }

            /**
             * Apply a custom clockwise rotation to the screenshot, i.e.
             * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take screenshots in its
             * native portrait orientation by default, so this is useful for returning screenshots
             * that are independent of device orientation.
             */
            public Builder setRotation(@Surface.Rotation int rotation) {
                mRotation = rotation;
                return this;
            }

            @Override
            Builder getThis() {
                return this;
@@ -2221,129 +2226,15 @@ public final class SurfaceControl implements Parcelable {
    }

    /**
     * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
     * @hide
     */
    @UnsupportedAppUsage
    public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
        return screenshot(sourceCrop, width, height, false, rotation);
    }

    /**
     * Copy the current screen contents into a hardware bitmap and return it.
     * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
     * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
     *
     * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use
     * unless absolutely necessary; prefer the versions that use a {@link HardwareBuffer} such as
     * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
     *
     * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
     * @hide
     */
    @UnsupportedAppUsage
    public static Bitmap screenshot(Rect sourceCrop, int width, int height,
            boolean useIdentityTransform, int rotation) {
        // TODO: should take the display as a parameter
        final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
        if (displayToken == null) {
            Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
            return null;
        }

        if (rotation == ROTATION_90 || rotation == ROTATION_270) {
            rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
        }

        SurfaceControl.rotateCropForSF(sourceCrop, rotation);
        final ScreenshotHardwareBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width,
                height, useIdentityTransform, rotation);

        if (buffer == null) {
            Log.w(TAG, "Failed to take screenshot");
            return null;
        }
        return Bitmap.wrapHardwareBuffer(buffer.getHardwareBuffer(), buffer.getColorSpace());
    }

    /**
     * Captures all the surfaces in a display and returns a {@link HardwareBuffer} with the content.
     *
     * @param display              The display to take the screenshot of.
     * @param sourceCrop           The portion of the screen to capture into the Bitmap; caller may
     *                             pass in 'new Rect()' if no cropping is desired.
     * @param width                The desired width of the returned bitmap; the raw screen will be
     *                             scaled down to this size; caller may pass in 0 if no scaling is
     *                             desired.
     * @param height               The desired height of the returned bitmap; the raw screen will
     *                             be scaled down to this size; caller may pass in 0 if no scaling
     *                             is desired.
     * @param useIdentityTransform Replace whatever transformation (rotation, scaling, translation)
     *                             the surface layers are currently using with the identity
     *                             transformation while taking the screenshot.
     * @param rotation             Apply a custom clockwise rotation to the screenshot, i.e.
     *                             Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take
     *                             screenshots in its native portrait orientation by default, so
     *                             this is useful for returning screenshots that are independent of
     *                             device orientation.
     * @return Returns a HardwareBuffer that contains the captured content.
     * @hide
     */
    public static ScreenshotHardwareBuffer screenshotToBuffer(IBinder display, Rect sourceCrop,
            int width, int height, boolean useIdentityTransform, int rotation) {
        if (display == null) {
            throw new IllegalArgumentException("displayToken must not be null");
        }

        DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
                .setSourceCrop(sourceCrop)
                .setSize(width, height)
                .setUseIdentityTransform(useIdentityTransform)
                .setRotation(rotation)
                .build();

        return nativeCaptureDisplay(captureArgs);
    }

    /**
     * Like screenshotToBuffer, but if the caller is AID_SYSTEM, allows
     * for the capture of secure layers. This is used for the screen rotation
     * animation where the system server takes screenshots but does
     * not persist them or allow them to leave the server. However in other
     * cases in the system server, we mostly want to omit secure layers
     * like when we take a screenshot on behalf of the assistant.
     * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with
     * the content.
     *
     * @hide
     */
    public static ScreenshotHardwareBuffer screenshotToBufferWithSecureLayersUnsafe(IBinder display,
            Rect sourceCrop, int width, int height, boolean useIdentityTransform,
            int rotation) {
        if (display == null) {
            throw new IllegalArgumentException("displayToken must not be null");
        }

        DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
                .setSourceCrop(sourceCrop)
                .setSize(width, height)
                .setUseIdentityTransform(useIdentityTransform)
                .setRotation(rotation)
                .setCaptureSecureLayers(true)
                .build();

    public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) {
        return nativeCaptureDisplay(captureArgs);
    }

    private static void rotateCropForSF(Rect crop, int rot) {
        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
            int tmp = crop.top;
            crop.top = crop.left;
            crop.left = tmp;
            tmp = crop.right;
            crop.right = crop.bottom;
            crop.bottom = tmp;
        }
    }

    /**
     * Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
     *
+0 −5
Original line number Diff line number Diff line
@@ -116,7 +116,6 @@ static struct {
    jfieldID width;
    jfieldID height;
    jfieldID useIdentityTransform;
    jfieldID rotation;
} gDisplayCaptureArgsClassInfo;

static struct {
@@ -325,8 +324,6 @@ static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
    captureArgs.useIdentityTransform =
            env->GetBooleanField(displayCaptureArgsObject,
                                 gDisplayCaptureArgsClassInfo.useIdentityTransform);
    captureArgs.rotation = ui::toRotation(
            env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation));
    return captureArgs;
}

@@ -1849,8 +1846,6 @@ int register_android_view_SurfaceControl(JNIEnv* env)
            GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I");
    gDisplayCaptureArgsClassInfo.useIdentityTransform =
            GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z");
    gDisplayCaptureArgsClassInfo.rotation =
            GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I");

    jclass layerCaptureArgsClazz =
            FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs");
Loading