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

Commit f6396c68 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "PixelCopy API feedback"

parents bf720fc4 056e5dc0
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -49747,7 +49747,7 @@ package android.view {
    method public static void request(@NonNull android.view.Surface, @Nullable android.graphics.Rect, @NonNull android.graphics.Bitmap, @NonNull android.view.PixelCopy.OnPixelCopyFinishedListener, @NonNull android.os.Handler);
    method public static void request(@NonNull android.view.Window, @NonNull android.graphics.Bitmap, @NonNull android.view.PixelCopy.OnPixelCopyFinishedListener, @NonNull android.os.Handler);
    method public static void request(@NonNull android.view.Window, @Nullable android.graphics.Rect, @NonNull android.graphics.Bitmap, @NonNull android.view.PixelCopy.OnPixelCopyFinishedListener, @NonNull android.os.Handler);
    method public static void request(@NonNull android.view.PixelCopy.Request);
    method public static void request(@NonNull android.view.PixelCopy.Request, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.PixelCopy.Result>);
    field public static final int ERROR_DESTINATION_INVALID = 5; // 0x5
    field public static final int ERROR_SOURCE_INVALID = 4; // 0x4
    field public static final int ERROR_SOURCE_NO_DATA = 3; // 0x3
@@ -49763,14 +49763,14 @@ package android.view {
  public static final class PixelCopy.Request {
    method @Nullable public android.graphics.Bitmap getDestinationBitmap();
    method @Nullable public android.graphics.Rect getSourceRect();
    method @NonNull public static android.view.PixelCopy.Request.Builder ofSurface(@NonNull android.view.Surface, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.PixelCopy.Result>);
    method @NonNull public static android.view.PixelCopy.Request.Builder ofSurface(@NonNull android.view.SurfaceView, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.PixelCopy.Result>);
    method @NonNull public static android.view.PixelCopy.Request.Builder ofWindow(@NonNull android.view.Window, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.PixelCopy.Result>);
    method @NonNull public static android.view.PixelCopy.Request.Builder ofWindow(@NonNull android.view.View, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.PixelCopy.Result>);
  }
  public static final class PixelCopy.Request.Builder {
    method @NonNull public android.view.PixelCopy.Request build();
    method @NonNull public static android.view.PixelCopy.Request.Builder ofSurface(@NonNull android.view.Surface);
    method @NonNull public static android.view.PixelCopy.Request.Builder ofSurface(@NonNull android.view.SurfaceView);
    method @NonNull public static android.view.PixelCopy.Request.Builder ofWindow(@NonNull android.view.Window);
    method @NonNull public static android.view.PixelCopy.Request.Builder ofWindow(@NonNull android.view.View);
    method @NonNull public android.view.PixelCopy.Request.Builder setDestinationBitmap(@Nullable android.graphics.Bitmap);
    method @NonNull public android.view.PixelCopy.Request.Builder setSourceRect(@Nullable android.graphics.Rect);
  }
+86 −96
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.view;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.HardwareRenderer;
import android.graphics.Rect;
@@ -355,27 +356,23 @@ public final class PixelCopy {
     * PixelCopy.Request.ofSurface factories to create a {@link Request.Builder} for the
     * given source content. After setting any optional parameters, such as
     * {@link Builder#setSourceRect(Rect)}, build the request with {@link Builder#build()} and
     * then execute it with {@link PixelCopy#request(Request)}
     * then execute it with {@link PixelCopy#request(Request, Executor, Consumer)}
     */
    public static final class Request {
        private final Surface mSource;
        private final Consumer<Result> mListener;
        private final Executor mListenerThread;
        private final Rect mSourceInsets;
        private Rect mSrcRect;
        private Bitmap mDest;

        private Request(Surface source, Rect sourceInsets, Executor listenerThread,
                        Consumer<Result> listener) {
        private Request(Surface source, Rect sourceInsets) {
            this.mSource = source;
            this.mSourceInsets = sourceInsets;
            this.mListenerThread = listenerThread;
            this.mListener = listener;
        }

        /**
         * A builder to create the complete PixelCopy request, which is then executed by calling
         * {@link #request(Request)} with the built request returned from {@link #build()}
         * {@link #request(Request, Executor, Consumer)} with the built request returned from
         * {@link #build()}
         */
        public static final class Builder {
            private Request mRequest;
@@ -384,92 +381,33 @@ public final class PixelCopy {
                mRequest = request;
            }

            private void requireNotBuilt() {
                if (mRequest == null) {
                    throw new IllegalStateException("build() already called on this builder");
                }
            }

            /**
             * Sets the region of the source to copy from. By default, the entire source is copied
             * to the output. If only a subset of the source is necessary to be copied, specifying
             * a srcRect will improve performance by reducing
             * the amount of data being copied.
             *
             * @param srcRect The area of the source to read from. Null or empty will be treated to
             *                mean the entire source
             * @return this
             */
            public @NonNull Builder setSourceRect(@Nullable Rect srcRect) {
                requireNotBuilt();
                mRequest.mSrcRect = srcRect;
                return this;
            }

            /**
             * Specifies the output bitmap in which to store the result. By default, a Bitmap of
             * format {@link android.graphics.Bitmap.Config#ARGB_8888} with a width & height
             * matching that of the {@link #setSourceRect(Rect) source area} will be created to
             * place the result.
             *
             * @param destination The bitmap to store the result, or null to have a bitmap
             *                    automatically created of the appropriate size. If not null, must
             *                    not be {@link Bitmap#isRecycled() recycled} and must be
             *                    {@link Bitmap#isMutable() mutable}.
             * @return this
             */
            public @NonNull Builder setDestinationBitmap(@Nullable Bitmap destination) {
                requireNotBuilt();
                if (destination != null) {
                    validateBitmapDest(destination);
                }
                mRequest.mDest = destination;
                return this;
            }

            /**
             * @return The built {@link PixelCopy.Request}
             */
            public @NonNull Request build() {
                requireNotBuilt();
                Request ret = mRequest;
                mRequest = null;
                return ret;
            }
        }

            /**
             * Creates a PixelCopy request for the given {@link Window}
             * @param source The Window to copy from
         * @param callbackExecutor The executor to run the callback on
         * @param listener The callback for when the copy request is completed
             * @return A {@link Builder} builder to set the optional params & execute the request
             */
        public static @NonNull Builder ofWindow(@NonNull Window source,
                                                @NonNull Executor callbackExecutor,
                                                @NonNull Consumer<Result> listener) {
            @SuppressLint("BuilderSetStyle")
            public static @NonNull Builder ofWindow(@NonNull Window source) {
                final Rect insets = new Rect();
                final Surface surface = sourceForWindow(source, insets);
            return new Builder(new Request(surface, insets, callbackExecutor, listener));
                return new Builder(new Request(surface, insets));
            }

            /**
             * Creates a PixelCopy request for the {@link Window} that the given {@link View} is
             * attached to.
             *
         * Note that this copy request is not cropped to the area the View occupies by default. If
         * that behavior is desired, use {@link View#getLocationInWindow(int[])} combined with
         * {@link Builder#setSourceRect(Rect)} to set a crop area to restrict the copy operation.
             * Note that this copy request is not cropped to the area the View occupies by default.
             * If that behavior is desired, use {@link View#getLocationInWindow(int[])} combined
             * with {@link Builder#setSourceRect(Rect)} to set a crop area to restrict the copy
             * operation.
             *
         * @param source A View that {@link View#isAttachedToWindow() is attached} to a window that
         *               will be used to retrieve the window to copy from.
         * @param callbackExecutor The executor to run the callback on
         * @param listener The callback for when the copy request is completed
             * @param source A View that {@link View#isAttachedToWindow() is attached} to a window
             *               that will be used to retrieve the window to copy from.
             * @return A {@link Builder} builder to set the optional params & execute the request
             */
        public static @NonNull Builder ofWindow(@NonNull View source,
                                                @NonNull Executor callbackExecutor,
                                                @NonNull Consumer<Result> listener) {
            @SuppressLint("BuilderSetStyle")
            public static @NonNull Builder ofWindow(@NonNull View source) {
                if (source == null || !source.isAttachedToWindow()) {
                    throw new IllegalArgumentException(
                            "View must not be null & must be attached to window");
@@ -485,24 +423,21 @@ public final class PixelCopy {
                    throw new IllegalArgumentException(
                            "Window doesn't have a backing surface!");
                }
            return new Builder(new Request(surface, insets, callbackExecutor, listener));
                return new Builder(new Request(surface, insets));
            }

            /**
             * Creates a PixelCopy request for the given {@link Surface}
             *
             * @param source The Surface to copy from. Must be {@link Surface#isValid() valid}.
         * @param callbackExecutor The executor to run the callback on
         * @param listener The callback for when the copy request is completed
             * @return A {@link Builder} builder to set the optional params & execute the request
             */
        public static @NonNull Builder ofSurface(@NonNull Surface source,
                                                 @NonNull Executor callbackExecutor,
                                                 @NonNull Consumer<Result> listener) {
            @SuppressLint("BuilderSetStyle")
            public static @NonNull Builder ofSurface(@NonNull Surface source) {
                if (source == null || !source.isValid()) {
                    throw new IllegalArgumentException("Source must not be null & must be valid");
                }
            return new Builder(new Request(source, null, callbackExecutor, listener));
                return new Builder(new Request(source, null));
            }

            /**
@@ -511,14 +446,65 @@ public final class PixelCopy {
             *
             * @param source The SurfaceView to copy from. The backing surface must be
             *               {@link Surface#isValid() valid}
         * @param callbackExecutor The executor to run the callback on
         * @param listener The callback for when the copy request is completed
             * @return A {@link Builder} builder to set the optional params & execute the request
             */
        public static @NonNull Builder ofSurface(@NonNull SurfaceView source,
                                                 @NonNull Executor callbackExecutor,
                                                 @NonNull Consumer<Result> listener) {
            return ofSurface(source.getHolder().getSurface(), callbackExecutor, listener);
            @SuppressLint("BuilderSetStyle")
            public static @NonNull Builder ofSurface(@NonNull SurfaceView source) {
                return ofSurface(source.getHolder().getSurface());
            }

            private void requireNotBuilt() {
                if (mRequest == null) {
                    throw new IllegalStateException("build() already called on this builder");
                }
            }

            /**
             * Sets the region of the source to copy from. By default, the entire source is copied
             * to the output. If only a subset of the source is necessary to be copied, specifying
             * a srcRect will improve performance by reducing
             * the amount of data being copied.
             *
             * @param srcRect The area of the source to read from. Null or empty will be treated to
             *                mean the entire source
             * @return this
             */
            public @NonNull Builder setSourceRect(@Nullable Rect srcRect) {
                requireNotBuilt();
                mRequest.mSrcRect = srcRect;
                return this;
            }

            /**
             * Specifies the output bitmap in which to store the result. By default, a Bitmap of
             * format {@link android.graphics.Bitmap.Config#ARGB_8888} with a width & height
             * matching that of the {@link #setSourceRect(Rect) source area} will be created to
             * place the result.
             *
             * @param destination The bitmap to store the result, or null to have a bitmap
             *                    automatically created of the appropriate size. If not null, must
             *                    not be {@link Bitmap#isRecycled() recycled} and must be
             *                    {@link Bitmap#isMutable() mutable}.
             * @return this
             */
            public @NonNull Builder setDestinationBitmap(@Nullable Bitmap destination) {
                requireNotBuilt();
                if (destination != null) {
                    validateBitmapDest(destination);
                }
                mRequest.mDest = destination;
                return this;
            }

            /**
             * @return The built {@link PixelCopy.Request}
             */
            public @NonNull Request build() {
                requireNotBuilt();
                Request ret = mRequest;
                mRequest = null;
                return ret;
            }
        }

        /**
@@ -538,9 +524,10 @@ public final class PixelCopy {
        /**
         * @hide
         */
        public void request() {
        public void request(@NonNull Executor callbackExecutor,
                            @NonNull Consumer<Result> listener) {
            if (!mSource.isValid()) {
                mListenerThread.execute(() -> mListener.accept(
                callbackExecutor.execute(() -> listener.accept(
                        new Result(ERROR_SOURCE_INVALID, null)));
                return;
            }
@@ -548,7 +535,7 @@ public final class PixelCopy {
                    adjustSourceRectForInsets(mSourceInsets, mSrcRect), mDest) {
                @Override
                public void onCopyFinished(int result) {
                    mListenerThread.execute(() -> mListener.accept(
                    callbackExecutor.execute(() -> listener.accept(
                            new Result(result, mDestinationBitmap)));
                }
            });
@@ -558,9 +545,12 @@ public final class PixelCopy {
    /**
     * Executes the pixel copy request
     * @param request The request to execute
     * @param callbackExecutor The executor to run the callback on
     * @param listener The callback for when the copy request is completed
     */
    public static void request(@NonNull Request request) {
        request.request();
    public static void request(@NonNull Request request, @NonNull Executor callbackExecutor,
                               @NonNull Consumer<Result> listener) {
        request.request(callbackExecutor, listener);
    }

    private PixelCopy() {}