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

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

Merge changes from topic "revert_capture_display"

* changes:
  Revert "Add captureDisplay API in WMS."
  Revert "Convert invalid crop to display bounds for captureDisplay"
parents 650c211a 0fff17bd
Loading
Loading
Loading
Loading
+0 −8
Original line number Original line Diff line number Diff line
@@ -67,7 +67,6 @@ import android.view.SurfaceControl;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.VerifiedDisplayHash;
import android.view.displayhash.VerifiedDisplayHash;
import android.window.ITaskFpsCallback;
import android.window.ITaskFpsCallback;
import android.window.ScreenCapture;


/**
/**
 * System private interface to the window manager.
 * System private interface to the window manager.
@@ -969,11 +968,4 @@ interface IWindowManager
     * treatment.
     * treatment.
     */
     */
    boolean isLetterboxBackgroundMultiColored();
    boolean isLetterboxBackgroundMultiColored();

    /**
     * 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.
     */
    oneway void captureDisplay(int displayId, in @nullable ScreenCapture.CaptureArgs captureArgs,
            in ScreenCapture.ScreenCaptureListener listener);
}
}
+0 −26
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.window;

/** @hide */
parcelable ScreenCapture.CaptureArgs;

/** @hide */
parcelable ScreenCapture.ScreenshotHardwareBuffer;

/** @hide */
parcelable ScreenCapture.ScreenCaptureListener;
 No newline at end of file
+88 −224
Original line number Original line Diff line number Diff line
@@ -24,16 +24,11 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.Log;
import android.view.SurfaceControl;
import android.view.SurfaceControl;


import libcore.util.NativeAllocationRegistry;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;


/**
/**
 * Handles display and layer captures for the system.
 * Handles display and layer captures for the system.
@@ -44,14 +39,9 @@ public class ScreenCapture {
    private static final String TAG = "ScreenCapture";
    private static final String TAG = "ScreenCapture";


    private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs,
    private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs,
            long captureListener);
            ScreenCaptureListener captureListener);
    private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs,
    private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs,
            long captureListener);
            ScreenCaptureListener captureListener);
    private static native long nativeCreateScreenCaptureListener(
            Consumer<ScreenshotHardwareBuffer> consumer);
    private static native void nativeWriteListenerToParcel(long nativeObject, Parcel out);
    private static native long nativeReadListenerFromParcel(Parcel in);
    private static native long getNativeListenerFinalizer();


    /**
    /**
     * @param captureArgs Arguments about how to take the screenshot
     * @param captureArgs Arguments about how to take the screenshot
@@ -60,7 +50,7 @@ public class ScreenCapture {
     */
     */
    public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs,
    public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs,
            @NonNull ScreenCaptureListener captureListener) {
            @NonNull ScreenCaptureListener captureListener) {
        return nativeCaptureDisplay(captureArgs, captureListener.mNativeObject);
        return nativeCaptureDisplay(captureArgs, captureListener);
    }
    }


    /**
    /**
@@ -71,8 +61,10 @@ public class ScreenCapture {
     */
     */
    public static ScreenshotHardwareBuffer captureDisplay(
    public static ScreenshotHardwareBuffer captureDisplay(
            DisplayCaptureArgs captureArgs) {
            DisplayCaptureArgs captureArgs) {
        SyncScreenCaptureListener screenCaptureListener = new SyncScreenCaptureListener();
        SyncScreenCaptureListener
        int status = captureDisplay(captureArgs, screenCaptureListener.getScreenCaptureListener());
                screenCaptureListener = new SyncScreenCaptureListener();

        int status = captureDisplay(captureArgs, screenCaptureListener);
        if (status != 0) {
        if (status != 0) {
            return null;
            return null;
        }
        }
@@ -88,8 +80,9 @@ public class ScreenCapture {
     *                         Rect()' or null if no cropping is desired. If the root layer does not
     *                         Rect()' or null if no cropping is desired. If the root layer does not
     *                         have a buffer or a crop set, then a non-empty source crop must be
     *                         have a buffer or a crop set, then a non-empty source crop must be
     *                         specified.
     *                         specified.
     * @param frameScale The desired scale of the returned buffer; the raw screen will be scaled
     * @param frameScale       The desired scale of the returned buffer; the raw
     *                   up/down.
     *                         screen will be scaled up/down.
     *
     * @return Returns a HardwareBuffer that contains the layer capture.
     * @return Returns a HardwareBuffer that contains the layer capture.
     * @hide
     * @hide
     */
     */
@@ -106,9 +99,10 @@ public class ScreenCapture {
     *                         Rect()' or null if no cropping is desired. If the root layer does not
     *                         Rect()' or null if no cropping is desired. If the root layer does not
     *                         have a buffer or a crop set, then a non-empty source crop must be
     *                         have a buffer or a crop set, then a non-empty source crop must be
     *                         specified.
     *                         specified.
     * @param frameScale The desired scale of the returned buffer; the raw screen will be scaled
     * @param frameScale       The desired scale of the returned buffer; the raw
     *                   up/down.
     *                         screen will be scaled up/down.
     * @param format           The desired pixel format of the returned buffer.
     * @param format           The desired pixel format of the returned buffer.
     *
     * @return Returns a HardwareBuffer that contains the layer capture.
     * @return Returns a HardwareBuffer that contains the layer capture.
     * @hide
     * @hide
     */
     */
@@ -130,7 +124,7 @@ public class ScreenCapture {
            LayerCaptureArgs captureArgs) {
            LayerCaptureArgs captureArgs) {
        SyncScreenCaptureListener screenCaptureListener = new SyncScreenCaptureListener();
        SyncScreenCaptureListener screenCaptureListener = new SyncScreenCaptureListener();


        int status = captureLayers(captureArgs, screenCaptureListener.getScreenCaptureListener());
        int status = captureLayers(captureArgs, screenCaptureListener);
        if (status != 0) {
        if (status != 0) {
            return null;
            return null;
        }
        }
@@ -141,7 +135,6 @@ public class ScreenCapture {
    /**
    /**
     * Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer
     * Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer
     * handles to exclude.
     * handles to exclude.
     *
     * @hide
     * @hide
     */
     */
    public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer,
    public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer,
@@ -163,7 +156,18 @@ public class ScreenCapture {
     */
     */
    public static int captureLayers(@NonNull LayerCaptureArgs captureArgs,
    public static int captureLayers(@NonNull LayerCaptureArgs captureArgs,
            @NonNull ScreenCaptureListener captureListener) {
            @NonNull ScreenCaptureListener captureListener) {
        return nativeCaptureLayers(captureArgs, captureListener.mNativeObject);
        return nativeCaptureLayers(captureArgs, captureListener);
    }

    /**
     * @hide
     */
    public interface ScreenCaptureListener {
        /**
         * The callback invoked when the screen capture is complete.
         * @param hardwareBuffer Data containing info about the screen capture.
         */
        void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer);
    }
    }


    /**
    /**
@@ -188,7 +192,6 @@ public class ScreenCapture {


       /**
       /**
        * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
        * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
         *
        * @param hardwareBuffer The existing HardwareBuffer object
        * @param hardwareBuffer The existing HardwareBuffer object
        * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
        * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
        * @param containsSecureLayers Indicates whether this graphic buffer contains captured
        * @param containsSecureLayers Indicates whether this graphic buffer contains captured
@@ -217,7 +220,6 @@ public class ScreenCapture {
        public boolean containsSecureLayers() {
        public boolean containsSecureLayers() {
            return mContainsSecureLayers;
            return mContainsSecureLayers;
        }
        }

        /**
        /**
         * Returns whether the screenshot contains at least one HDR layer.
         * Returns whether the screenshot contains at least one HDR layer.
         * This information may be useful for informing the display whether this screenshot
         * This information may be useful for informing the display whether this screenshot
@@ -232,7 +234,7 @@ public class ScreenCapture {
         * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
         * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
         * into
         * into
         * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
         * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
         * <p>
         *
         * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
         * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
         * directly
         * directly
         * use the {@link HardwareBuffer} directly.
         * use the {@link HardwareBuffer} directly.
@@ -248,23 +250,44 @@ public class ScreenCapture {
        }
        }
    }
    }


    private static class SyncScreenCaptureListener implements ScreenCaptureListener {
        private static final int SCREENSHOT_WAIT_TIME_S = 1;
        private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
        private final CountDownLatch mCountDownLatch = new CountDownLatch(1);

        @Override
        public void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) {
            mScreenshotHardwareBuffer = hardwareBuffer;
            mCountDownLatch.countDown();
        }

        private ScreenshotHardwareBuffer waitForScreenshot() {
            try {
                mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
            } catch (Exception e) {
                Log.e(TAG, "Failed to wait for screen capture result", e);
            }

            return mScreenshotHardwareBuffer;
        }
    }

    /**
    /**
     * A common arguments class used for various screenshot requests. This contains arguments that
     * A common arguments class used for various screenshot requests. This contains arguments that
     * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
     * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
     *
     * @hide
     * @hide
     */
     */
    public static class CaptureArgs implements Parcelable {
    private abstract static class CaptureArgs {
        public final int mPixelFormat;
        private final int mPixelFormat;
        public final Rect mSourceCrop = new Rect();
        private final Rect mSourceCrop = new Rect();
        public final float mFrameScaleX;
        private final float mFrameScaleX;
        public final float mFrameScaleY;
        private final float mFrameScaleY;
        public final boolean mCaptureSecureLayers;
        private final boolean mCaptureSecureLayers;
        public final boolean mAllowProtected;
        private final boolean mAllowProtected;
        public final long mUid;
        private final long mUid;
        public final boolean mGrayscale;
        private final boolean mGrayscale;


        private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) {
        private CaptureArgs(Builder<? extends Builder<?>> builder) {
            mPixelFormat = builder.mPixelFormat;
            mPixelFormat = builder.mPixelFormat;
            mSourceCrop.set(builder.mSourceCrop);
            mSourceCrop.set(builder.mSourceCrop);
            mFrameScaleX = builder.mFrameScaleX;
            mFrameScaleX = builder.mFrameScaleX;
@@ -275,23 +298,12 @@ public class ScreenCapture {
            mGrayscale = builder.mGrayscale;
            mGrayscale = builder.mGrayscale;
        }
        }


        private CaptureArgs(Parcel in) {
            mPixelFormat = in.readInt();
            mSourceCrop.readFromParcel(in);
            mFrameScaleX = in.readFloat();
            mFrameScaleY = in.readFloat();
            mCaptureSecureLayers = in.readBoolean();
            mAllowProtected = in.readBoolean();
            mUid = in.readLong();
            mGrayscale = in.readBoolean();
        }

        /**
        /**
         * The Builder class used to construct {@link CaptureArgs}
         * The Builder class used to construct {@link CaptureArgs}
         *
         *
         * @param <T> A builder that extends {@link CaptureArgs.Builder}
         * @param <T> A builder that extends {@link Builder}
         */
         */
        public static class Builder<T extends CaptureArgs.Builder<T>> {
        abstract static class Builder<T extends Builder<T>> {
            private int mPixelFormat = PixelFormat.RGBA_8888;
            private int mPixelFormat = PixelFormat.RGBA_8888;
            private final Rect mSourceCrop = new Rect();
            private final Rect mSourceCrop = new Rect();
            private float mFrameScaleX = 1;
            private float mFrameScaleX = 1;
@@ -301,14 +313,6 @@ public class ScreenCapture {
            private long mUid = -1;
            private long mUid = -1;
            private boolean mGrayscale;
            private boolean mGrayscale;


            /**
             * Construct a new {@link CaptureArgs} with the set parameters. The builder remains
             * valid.
             */
            public CaptureArgs build() {
                return new CaptureArgs(this);
            }

            /**
            /**
             * The desired pixel format of the returned buffer.
             * The desired pixel format of the returned buffer.
             */
             */
@@ -391,47 +395,15 @@ public class ScreenCapture {
            /**
            /**
             * Each sub class should return itself to allow the builder to chain properly
             * Each sub class should return itself to allow the builder to chain properly
             */
             */
            T getThis() {
            abstract T getThis();
                return (T) this;
            }
        }
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeInt(mPixelFormat);
            mSourceCrop.writeToParcel(dest, flags);
            dest.writeFloat(mFrameScaleX);
            dest.writeFloat(mFrameScaleY);
            dest.writeBoolean(mCaptureSecureLayers);
            dest.writeBoolean(mAllowProtected);
            dest.writeLong(mUid);
            dest.writeBoolean(mGrayscale);
        }

        public static final Parcelable.Creator<CaptureArgs> CREATOR =
                new Parcelable.Creator<CaptureArgs>() {
                    @Override
                    public CaptureArgs createFromParcel(Parcel in) {
                        return new CaptureArgs(in);
                    }

                    @Override
                    public CaptureArgs[] newArray(int size) {
                        return new CaptureArgs[size];
                    }
                };
    }
    }


    /**
    /**
     * The arguments class used to make display capture requests.
     * The arguments class used to make display capture requests.
     *
     *
     * @see #nativeCaptureDisplay(DisplayCaptureArgs, ScreenCaptureListener)
     * @hide
     * @hide
     * @see #nativeCaptureDisplay(DisplayCaptureArgs, long)
     */
     */
    public static class DisplayCaptureArgs extends CaptureArgs {
    public static class DisplayCaptureArgs extends CaptureArgs {
        private final IBinder mDisplayToken;
        private final IBinder mDisplayToken;
@@ -516,8 +488,8 @@ public class ScreenCapture {
    /**
    /**
     * The arguments class used to make layer capture requests.
     * The arguments class used to make layer capture requests.
     *
     *
     * @see #nativeCaptureLayers(LayerCaptureArgs, ScreenCaptureListener)
     * @hide
     * @hide
     * @see #nativeCaptureLayers(LayerCaptureArgs, long)
     */
     */
    public static class LayerCaptureArgs extends CaptureArgs {
    public static class LayerCaptureArgs extends CaptureArgs {
        private final long mNativeLayer;
        private final long mNativeLayer;
@@ -558,17 +530,6 @@ public class ScreenCapture {
                return new LayerCaptureArgs(this);
                return new LayerCaptureArgs(this);
            }
            }


            public Builder(SurfaceControl layer, CaptureArgs args) {
                setLayer(layer);
                setPixelFormat(args.mPixelFormat);
                setSourceCrop(args.mSourceCrop);
                setFrameScale(args.mFrameScaleX, args.mFrameScaleY);
                setCaptureSecureLayers(args.mCaptureSecureLayers);
                setAllowProtected(args.mAllowProtected);
                setUid(args.mUid);
                setGrayscale(args.mGrayscale);
            }

            public Builder(SurfaceControl layer) {
            public Builder(SurfaceControl layer) {
                setLayer(layer);
                setLayer(layer);
            }
            }
@@ -581,6 +542,7 @@ public class ScreenCapture {
                return this;
                return this;
            }
            }



            /**
            /**
             * An array of layer handles to exclude.
             * An array of layer handles to exclude.
             */
             */
@@ -602,106 +564,8 @@ public class ScreenCapture {
            Builder getThis() {
            Builder getThis() {
                return this;
                return this;
            }
            }
        }
    }

    /**
     * The object used to receive the results when invoking screen capture requests via
     * {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)} or
     * {@link #captureLayers(LayerCaptureArgs, ScreenCaptureListener)}
     */
    public static class ScreenCaptureListener implements Parcelable {
        private final long mNativeObject;
        private static final NativeAllocationRegistry sRegistry =
                NativeAllocationRegistry.createMalloced(
                        ScreenCaptureListener.class.getClassLoader(), getNativeListenerFinalizer());

        /**
         * @param consumer The callback invoked when the screen capture is complete.
         */
        public ScreenCaptureListener(Consumer<ScreenshotHardwareBuffer> consumer) {
            mNativeObject = nativeCreateScreenCaptureListener(consumer);
            sRegistry.registerNativeAllocation(this, mNativeObject);
        }


        private ScreenCaptureListener(Parcel in) {
            if (in.readBoolean()) {
                mNativeObject = nativeReadListenerFromParcel(in);
                sRegistry.registerNativeAllocation(this, mNativeObject);
            } else {
                mNativeObject = 0;
        }
        }
    }
    }


        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            if (mNativeObject == 0) {
                dest.writeBoolean(false);
            } else {
                dest.writeBoolean(true);
                nativeWriteListenerToParcel(mNativeObject, dest);
            }
        }

        public static final Parcelable.Creator<ScreenCaptureListener> CREATOR =
                new Parcelable.Creator<ScreenCaptureListener>() {
                    @Override
                    public ScreenCaptureListener createFromParcel(Parcel in) {
                        return new ScreenCaptureListener(in);
                    }

                    @Override
                    public ScreenCaptureListener[] newArray(int size) {
                        return new ScreenCaptureListener[0];
                    }
                };
    }

    /**
     * A helper class to handle the async screencapture callbacks synchronously. This should only
     * be used if the screencapture caller doesn't care that it blocks waiting for a screenshot.
     */
    public static class SyncScreenCaptureListener {
        private static final int SCREENSHOT_WAIT_TIME_S = 1;
        private ScreenshotHardwareBuffer mScreenshotHardwareBuffer;
        private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
        private final ScreenCaptureListener mScreenCaptureListener;

        public SyncScreenCaptureListener() {
            mScreenCaptureListener = new ScreenCaptureListener(screenshotHardwareBuffer -> {
                mScreenshotHardwareBuffer = screenshotHardwareBuffer;
                mCountDownLatch.countDown();
            });
        }

        /**
         * @return The underlying {@link ScreenCaptureListener}
         */
        public ScreenCaptureListener getScreenCaptureListener() {
            return mScreenCaptureListener;
        }

        /**
         * Waits until the screenshot callback has been invoked and the screenshot is ready. This
         * can return {@code null} if the screenshot callback wasn't invoked after
         * {@link #SCREENSHOT_WAIT_TIME_S} or the screencapture request resulted in an error
         *
         * @return A ScreenshotHardwareBuffer for the content that was captured.
         */
        @Nullable
        public ScreenshotHardwareBuffer waitForScreenshot() {
            try {
                mCountDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS);
            } catch (Exception e) {
                Log.e(TAG, "Failed to wait for screen capture result", e);
            }

            return mScreenshotHardwareBuffer;
        }
    }
}
}
+32 −73

File changed.

Preview size limit exceeded, changes collapsed.

+0 −42
Original line number Original line Diff line number Diff line
@@ -9279,46 +9279,4 @@ public class WindowManagerService extends IWindowManager.Stub
                        "Unexpected letterbox background type: " + letterboxBackgroundType);
                        "Unexpected letterbox background type: " + letterboxBackgroundType);
        }
        }
    }
    }

    @Override
    public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs,
            ScreenCapture.ScreenCaptureListener listener) {
        Slog.d(TAG, "captureDisplay");
        if (!checkCallingPermission(READ_FRAME_BUFFER, "captureDisplay()")) {
            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
        }

        ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener);
    }

    @VisibleForTesting
    ScreenCapture.LayerCaptureArgs getCaptureArgs(int displayId,
            @Nullable ScreenCapture.CaptureArgs captureArgs) {
        final SurfaceControl displaySurfaceControl;
        synchronized (mGlobalLock) {
            DisplayContent displayContent = mRoot.getDisplayContent(displayId);
            if (displayContent == null) {
                throw new IllegalArgumentException("Trying to screenshot and invalid display: "
                        + displayId);
            }

            displaySurfaceControl = displayContent.getSurfaceControl();

            if (captureArgs == null) {
                captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
                        .build();
            }

            if (captureArgs.mSourceCrop.isEmpty()) {
                displayContent.getBounds(mTmpRect);
                mTmpRect.offsetTo(0, 0);
            } else {
                mTmpRect.set(captureArgs.mSourceCrop);
            }
        }

        return new ScreenCapture.LayerCaptureArgs.Builder(displaySurfaceControl, captureArgs)
                        .setSourceCrop(mTmpRect)
                        .build();
    }
}
}
Loading