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

Commit 9af04c1b authored by jeimysantiago's avatar jeimysantiago
Browse files

Pass Error Status to ScreenCapture

Changed the consumers in android_window_ScreenCapture and ScreenCapture
into ObjIntConsumer so the error status can be passed as
ScreenCaptureListener from the C++ side to the Java side.

Bug: 287081404
Test: atest layerScreenshot
Change-Id: Ic151160230f5310560fc33d4a9ba414a1f531138
parent 564efcd8
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -831,8 +831,17 @@ public final class AccessibilityInteractionClient
                    //   A11yService -> App -> SurfaceFlinger -> A11yService
                    ScreenCapture.ScreenCaptureListener listener =
                            new ScreenCapture.ScreenCaptureListener(
                                    screenshot -> sendWindowScreenshotSuccess(screenshot,
                                            interactionId));
                                    (screenshot, status) -> {
                                        if (status != 0) {
                                            sendTakeScreenshotOfWindowError(
                                                    AccessibilityService
                                                            .ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR,
                                                    interactionId);
                                        } else {
                                            sendWindowScreenshotSuccess(screenshot,
                                                    interactionId);
                                        }
                                    });
                    connection.takeScreenshotOfWindow(accessibilityWindowId, interactionId,
                            listener, this);
                    mMainHandler.postDelayed(() -> {
+12 −8
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import libcore.util.NativeAllocationRegistry;

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

/**
 * Handles display and layer captures for the system.
@@ -43,13 +43,12 @@ import java.util.function.Consumer;
public class ScreenCapture {
    private static final String TAG = "ScreenCapture";
    private static final int SCREENSHOT_WAIT_TIME_S = 1;

    private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs,
            long captureListener);
    private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs,
            long captureListener);
    private static native long nativeCreateScreenCaptureListener(
            Consumer<ScreenshotHardwareBuffer> consumer);
            ObjIntConsumer<ScreenshotHardwareBuffer> consumer);
    private static native void nativeWriteListenerToParcel(long nativeObject, Parcel out);
    private static native long nativeReadListenerFromParcel(Parcel in);
    private static native long getNativeListenerFinalizer();
@@ -695,7 +694,7 @@ public class ScreenCapture {
        /**
         * @param consumer The callback invoked when the screen capture is complete.
         */
        public ScreenCaptureListener(Consumer<ScreenshotHardwareBuffer> consumer) {
        public ScreenCaptureListener(ObjIntConsumer<ScreenshotHardwareBuffer> consumer) {
            mNativeObject = nativeCreateScreenCaptureListener(consumer);
            sRegistry.registerNativeAllocation(this, mNativeObject);
        }
@@ -748,8 +747,13 @@ public class ScreenCapture {
    public static SynchronousScreenCaptureListener createSyncCaptureListener() {
        ScreenshotHardwareBuffer[] bufferRef = new ScreenshotHardwareBuffer[1];
        CountDownLatch latch = new CountDownLatch(1);
        Consumer<ScreenshotHardwareBuffer> consumer = buffer -> {
        ObjIntConsumer<ScreenshotHardwareBuffer> consumer = (buffer, status) -> {
            if (status != 0) {
                bufferRef[0] = null;
                Log.e(TAG, "Failed to generate screen capture. Error code: " + status);
            } else {
                bufferRef[0] = buffer;
            }
            latch.countDown();
        };

@@ -758,7 +762,7 @@ public class ScreenCapture {
            // it references, the underlying JNI listener holds a weak reference to the consumer.
            // This property exists to ensure the consumer stays alive during the listener's
            // lifetime.
            private Consumer<ScreenshotHardwareBuffer> mConsumer = consumer;
            private ObjIntConsumer<ScreenshotHardwareBuffer> mConsumer = consumer;

            @Override
            public ScreenshotHardwareBuffer getBuffer() {
@@ -779,7 +783,7 @@ public class ScreenCapture {
     * {@link #captureDisplay(DisplayCaptureArgs, ScreenCaptureListener)}
     */
    public abstract static class SynchronousScreenCaptureListener extends ScreenCaptureListener {
        SynchronousScreenCaptureListener(Consumer<ScreenshotHardwareBuffer> consumer) {
        SynchronousScreenCaptureListener(ObjIntConsumer<ScreenshotHardwareBuffer> consumer) {
            super(consumer);
        }

+7 −5
Original line number Diff line number Diff line
@@ -102,7 +102,8 @@ public:
        }

        if (!captureResults.fenceResult.ok() || captureResults.buffer == nullptr) {
            env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, nullptr);
            env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, nullptr,
                                fenceStatus(captureResults.fenceResult));
            checkAndClearException(env, "accept");
            return binder::Status::ok();
        }
@@ -117,7 +118,8 @@ public:
                                            captureResults.capturedSecureLayers,
                                            captureResults.capturedHdrLayers);
        checkAndClearException(env, "builder");
        env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, screenshotHardwareBuffer);
        env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, screenshotHardwareBuffer,
                            fenceStatus(captureResults.fenceResult));
        checkAndClearException(env, "accept");
        env->DeleteLocalRef(jhardwareBuffer);
        env->DeleteLocalRef(screenshotHardwareBuffer);
@@ -285,7 +287,7 @@ static const JNINativeMethod sScreenCaptureMethods[] = {
            (void*)nativeCaptureDisplay },
    {"nativeCaptureLayers",  "(Landroid/window/ScreenCapture$LayerCaptureArgs;J)I",
            (void*)nativeCaptureLayers },
    {"nativeCreateScreenCaptureListener", "(Ljava/util/function/Consumer;)J",
    {"nativeCreateScreenCaptureListener", "(Ljava/util/function/ObjIntConsumer;)J",
            (void*)nativeCreateScreenCaptureListener },
    {"nativeWriteListenerToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteListenerToParcel },
    {"nativeReadListenerFromParcel", "(Landroid/os/Parcel;)J",
@@ -333,8 +335,8 @@ int register_android_window_ScreenCapture(JNIEnv* env) {
    gLayerCaptureArgsClassInfo.childrenOnly =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");

    jclass consumer = FindClassOrDie(env, "java/util/function/Consumer");
    gConsumerClassInfo.accept = GetMethodIDOrDie(env, consumer, "accept", "(Ljava/lang/Object;)V");
    jclass consumer = FindClassOrDie(env, "java/util/function/ObjIntConsumer");
    gConsumerClassInfo.accept = GetMethodIDOrDie(env, consumer, "accept", "(Ljava/lang/Object;I)V");

    jclass screenshotGraphicsBufferClazz =
            FindClassOrDie(env, "android/window/ScreenCapture$ScreenshotHardwareBuffer");