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

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

Merge "Move exclude layer to CaptureArgs." into udc-dev

parents fb094246 dfc93ddc
Loading
Loading
Loading
Loading
+62 −18
Original line number Diff line number Diff line
@@ -272,6 +272,8 @@ public class ScreenCapture {
        public final long mUid;
        public final boolean mGrayscale;

        final SurfaceControl[] mExcludeLayers;

        private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) {
            mPixelFormat = builder.mPixelFormat;
            mSourceCrop.set(builder.mSourceCrop);
@@ -281,6 +283,7 @@ public class ScreenCapture {
            mAllowProtected = builder.mAllowProtected;
            mUid = builder.mUid;
            mGrayscale = builder.mGrayscale;
            mExcludeLayers = builder.mExcludeLayers;
        }

        private CaptureArgs(Parcel in) {
@@ -292,6 +295,46 @@ public class ScreenCapture {
            mAllowProtected = in.readBoolean();
            mUid = in.readLong();
            mGrayscale = in.readBoolean();

            int excludeLayersLength = in.readInt();
            if (excludeLayersLength > 0) {
                mExcludeLayers = new SurfaceControl[excludeLayersLength];
                for (int index = 0; index < excludeLayersLength; index++) {
                    mExcludeLayers[index] = SurfaceControl.CREATOR.createFromParcel(in);
                }
            } else {
                mExcludeLayers = null;
            }
        }

        /** Release any layers if set using {@link Builder#setExcludeLayers(SurfaceControl[])}. */
        public void release() {
            if (mExcludeLayers.length == 0) {
                return;
            }

            for (SurfaceControl surfaceControl : mExcludeLayers) {
                if (surfaceControl != null) {
                    surfaceControl.release();
                }
            }
        }

        /**
         * Returns an array of {@link SurfaceControl#mNativeObject} corresponding to
         * {@link #mExcludeLayers}. Used only in native code.
         */
        private long[] getNativeExcludeLayers() {
            if (mExcludeLayers == null || mExcludeLayers.length == 0) {
                return new long[0];
            }

            long[] nativeExcludeLayers = new long[mExcludeLayers.length];
            for (int index = 0; index < mExcludeLayers.length; index++) {
                nativeExcludeLayers[index] = mExcludeLayers[index].mNativeObject;
            }

            return nativeExcludeLayers;
        }

        /**
@@ -308,6 +351,7 @@ public class ScreenCapture {
            private boolean mAllowProtected;
            private long mUid = -1;
            private boolean mGrayscale;
            private SurfaceControl[] mExcludeLayers;

            /**
             * Construct a new {@link CaptureArgs} with the set parameters. The builder remains
@@ -396,6 +440,14 @@ public class ScreenCapture {
                return getThis();
            }

            /**
             * An array of {@link SurfaceControl} layer handles to exclude.
             */
            public T setExcludeLayers(@Nullable SurfaceControl[] excludeLayers) {
                mExcludeLayers = excludeLayers;
                return getThis();
            }

            /**
             * Each sub class should return itself to allow the builder to chain properly
             */
@@ -419,6 +471,15 @@ public class ScreenCapture {
            dest.writeBoolean(mAllowProtected);
            dest.writeLong(mUid);
            dest.writeBoolean(mGrayscale);

            if (mExcludeLayers != null) {
                dest.writeInt(mExcludeLayers.length);
                for (SurfaceControl excludeLayer : mExcludeLayers) {
                    excludeLayer.writeToParcel(dest, flags);
                }
            } else {
                dest.writeInt(0);
            }
        }

        public static final Parcelable.Creator<CaptureArgs> CREATOR =
@@ -529,21 +590,12 @@ public class ScreenCapture {
     */
    public static class LayerCaptureArgs extends CaptureArgs {
        private final long mNativeLayer;
        private final long[] mNativeExcludeLayers;
        private final boolean mChildrenOnly;

        private LayerCaptureArgs(Builder builder) {
            super(builder);
            mChildrenOnly = builder.mChildrenOnly;
            mNativeLayer = builder.mLayer.mNativeObject;
            if (builder.mExcludeLayers != null) {
                mNativeExcludeLayers = new long[builder.mExcludeLayers.length];
                for (int i = 0; i < builder.mExcludeLayers.length; i++) {
                    mNativeExcludeLayers[i] = builder.mExcludeLayers[i].mNativeObject;
                }
            } else {
                mNativeExcludeLayers = null;
            }
        }

        /**
@@ -551,7 +603,6 @@ public class ScreenCapture {
         */
        public static class Builder extends CaptureArgs.Builder<Builder> {
            private SurfaceControl mLayer;
            private SurfaceControl[] mExcludeLayers;
            private boolean mChildrenOnly = true;

            /**
@@ -575,6 +626,7 @@ public class ScreenCapture {
                setAllowProtected(args.mAllowProtected);
                setUid(args.mUid);
                setGrayscale(args.mGrayscale);
                setExcludeLayers(args.mExcludeLayers);
            }

            public Builder(SurfaceControl layer) {
@@ -589,14 +641,6 @@ public class ScreenCapture {
                return this;
            }

            /**
             * An array of layer handles to exclude.
             */
            public Builder setExcludeLayers(@Nullable SurfaceControl[] excludeLayers) {
                mExcludeLayers = excludeLayers;
                return this;
            }

            /**
             * Whether to include the layer itself in the screenshot or just the children and their
             * descendants.
+22 −20
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ static struct {
    jfieldID allowProtected;
    jfieldID uid;
    jfieldID grayscale;
    jmethodID getNativeExcludeLayers;
} gCaptureArgsClassInfo;

static struct {
@@ -56,7 +57,6 @@ static struct {

static struct {
    jfieldID layer;
    jfieldID excludeLayers;
    jfieldID childrenOnly;
} gLayerCaptureArgsClassInfo;

@@ -168,6 +168,23 @@ static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs&
    captureArgs.uid = env->GetLongField(captureArgsObject, gCaptureArgsClassInfo.uid);
    captureArgs.grayscale =
            env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.grayscale);

    jlongArray excludeObjectArray = reinterpret_cast<jlongArray>(
            env->CallObjectMethod(captureArgsObject, gCaptureArgsClassInfo.getNativeExcludeLayers));
    if (excludeObjectArray != nullptr) {
        ScopedLongArrayRO excludeArray(env, excludeObjectArray);
        const jsize len = excludeArray.size();
        captureArgs.excludeHandles.reserve(len);

        for (jsize i = 0; i < len; i++) {
            auto excludeObject = reinterpret_cast<SurfaceControl*>(excludeArray[i]);
            if (excludeObject == nullptr) {
                jniThrowNullPointerException(env, "Exclude layer is null");
                return;
            }
            captureArgs.excludeHandles.emplace(excludeObject->getHandle());
        }
    }
}

static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
@@ -207,6 +224,7 @@ static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureA
                                jlong screenCaptureListenerObject) {
    LayerCaptureArgs captureArgs;
    getCaptureArgs(env, layerCaptureArgsObject, captureArgs);

    SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
            env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
    if (layer == nullptr) {
@@ -217,23 +235,6 @@ static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureA
    captureArgs.childrenOnly =
            env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly);

    jlongArray excludeObjectArray = reinterpret_cast<jlongArray>(
            env->GetObjectField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.excludeLayers));
    if (excludeObjectArray != nullptr) {
        ScopedLongArrayRO excludeArray(env, excludeObjectArray);
        const jsize len = excludeArray.size();
        captureArgs.excludeHandles.reserve(len);

        for (jsize i = 0; i < len; i++) {
            auto excludeObject = reinterpret_cast<SurfaceControl*>(excludeArray[i]);
            if (excludeObject == nullptr) {
                jniThrowNullPointerException(env, "Exclude layer is null");
                return BAD_VALUE;
            }
            captureArgs.excludeHandles.emplace(excludeObject->getHandle());
        }
    }

    sp<gui::IScreenCaptureListener> captureListener =
            reinterpret_cast<gui::IScreenCaptureListener*>(screenCaptureListenerObject);
    return ScreenshotClient::captureLayers(captureArgs, captureListener);
@@ -318,6 +319,9 @@ int register_android_window_ScreenCapture(JNIEnv* env) {
    gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J");
    gCaptureArgsClassInfo.grayscale = GetFieldIDOrDie(env, captureArgsClazz, "mGrayscale", "Z");

    gCaptureArgsClassInfo.getNativeExcludeLayers =
            GetMethodIDOrDie(env, captureArgsClazz, "getNativeExcludeLayers", "()[J");

    jclass displayCaptureArgsClazz =
            FindClassOrDie(env, "android/window/ScreenCapture$DisplayCaptureArgs");
    gDisplayCaptureArgsClassInfo.displayToken =
@@ -333,8 +337,6 @@ int register_android_window_ScreenCapture(JNIEnv* env) {
            FindClassOrDie(env, "android/window/ScreenCapture$LayerCaptureArgs");
    gLayerCaptureArgsClassInfo.layer =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeLayer", "J");
    gLayerCaptureArgsClassInfo.excludeLayers =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeExcludeLayers", "[J");
    gLayerCaptureArgsClassInfo.childrenOnly =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");

+16 −3
Original line number Diff line number Diff line
@@ -74,8 +74,10 @@ import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.view.IWindowManager;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.window.ScreenCapture;
@@ -1186,13 +1188,24 @@ public class BubbleController implements ConfigurationChangeListener,
    /**
     * Performs a screenshot that may exclude the bubble layer, if one is present. The screenshot
     * can be access via the supplied {@link ScreenshotSync#get()} asynchronously.
     *
     * TODO(b/267324693): Implement the exclude layer functionality in screenshot.
     */
    public void getScreenshotExcludingBubble(int displayId,
            Pair<ScreenCaptureListener, ScreenshotSync> screenCaptureListener) {
        try {
            mWmService.captureDisplay(displayId, null, screenCaptureListener.first);
            ScreenCapture.CaptureArgs args = null;
            if (mStackView != null) {
                ViewRootImpl viewRoot = mStackView.getViewRootImpl();
                if (viewRoot != null) {
                    SurfaceControl bubbleLayer = viewRoot.getSurfaceControl();
                    if (bubbleLayer != null) {
                        args = new ScreenCapture.CaptureArgs.Builder<>()
                                .setExcludeLayers(new SurfaceControl[] {bubbleLayer})
                                .build();
                    }
                }
            }

            mWmService.captureDisplay(displayId, args, screenCaptureListener.first);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to capture screenshot");
        }
+8 −1
Original line number Diff line number Diff line
@@ -9315,7 +9315,14 @@ public class WindowManagerService extends IWindowManager.Stub
            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
        }

        ScreenCapture.captureLayers(getCaptureArgs(displayId, captureArgs), listener);
        ScreenCapture.LayerCaptureArgs layerCaptureArgs = getCaptureArgs(displayId, captureArgs);
        ScreenCapture.captureLayers(layerCaptureArgs, listener);

        if (Binder.getCallingUid() != SYSTEM_UID) {
            // Release the SurfaceControl objects only if the caller is not in system server as no
            // parcelling occurs in this case.
            layerCaptureArgs.release();
        }
    }

    @VisibleForTesting