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

Commit 45acebc8 authored by chaviw's avatar chaviw
Browse files

Updated layer capture in JNI to match updated function

Modified Java and JNI layer capture functions to match the new
function in SurfaceComposerClient. The Java method will send an args
object instead of individual arguments to SurfaceComposerClient

Test: Layer screenshots in recents
Bug: 162367424
Change-Id: Ib060a0238e47edfc19f6f34a5c6a508fc6c9f7fd
parent bc27bc71
Loading
Loading
Loading
Loading
+29 −19
Original line number Diff line number Diff line
@@ -91,9 +91,8 @@ public final class SurfaceControl implements Parcelable {
    private static native void nativeDisconnect(long nativeObject);
    private static native ScreenshotHardwareBuffer nativeCaptureDisplay(
            DisplayCaptureArgs captureArgs);
    private static native ScreenshotHardwareBuffer nativeCaptureLayers(IBinder displayToken,
            long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects,
            int format);
    private static native ScreenshotHardwareBuffer nativeCaptureLayers(
            LayerCaptureArgs captureArgs);
    private static native long nativeMirrorSurface(long mirrorOfObject);
    private static native long nativeCreateTransaction();
    private static native long nativeGetNativeTransactionFinalizer();
@@ -570,7 +569,8 @@ public final class SurfaceControl implements Parcelable {
        * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
        * @param hardwareBuffer The existing HardwareBuffer object
        * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
        * @param containsSecureLayer Indicates whether this graphic buffer contains captured contents
        * @param containsSecureLayers Indicates whether this graphic buffer contains captured
        *                             contents
        *        of secure layers, in which case the screenshot should not be persisted.
        */
        private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer,
@@ -766,7 +766,7 @@ public final class SurfaceControl implements Parcelable {
    /**
     * The arguments class used to make layer capture requests.
     *
     * @see #nativeCaptureLayers(IBinder, long, Rect, float, long[], int)
     * @see #nativeCaptureLayers(LayerCaptureArgs)
     * @hide
     */
    public static class LayerCaptureArgs extends CaptureArgs {
@@ -778,10 +778,14 @@ public final class SurfaceControl implements Parcelable {
            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;
            }
        }

        /**
@@ -2376,24 +2380,30 @@ public final class SurfaceControl implements Parcelable {
     */
    public static ScreenshotHardwareBuffer captureLayers(SurfaceControl layer, Rect sourceCrop,
            float frameScale, int format) {
        final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
        return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale, null,
                format);
        LayerCaptureArgs captureArgs = new LayerCaptureArgs.Builder(layer)
                .setSourceCrop(sourceCrop)
                .setFrameScale(frameScale)
                .setPixelFormat(format)
                .build();

        return nativeCaptureLayers(captureArgs);
    }

    /**
     * Like {@link captureLayers} but with an array of layer handles to exclude.
     * Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer
     * handles to exclude.
     * @hide
     */
    public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer,
            Rect sourceCrop, float frameScale, int format, SurfaceControl[] exclude) {
        final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
        long[] nativeExcludeObjects = new long[exclude.length];
        for (int i = 0; i < exclude.length; i++) {
            nativeExcludeObjects[i] = exclude[i].mNativeObject;
        }
        return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale,
                nativeExcludeObjects, PixelFormat.RGBA_8888);
        LayerCaptureArgs captureArgs = new LayerCaptureArgs.Builder(layer)
                .setSourceCrop(sourceCrop)
                .setFrameScale(frameScale)
                .setPixelFormat(format)
                .setExcludeLayers(exclude)
                .build();

        return nativeCaptureLayers(captureArgs);
    }

    /**
+37 −33
Original line number Diff line number Diff line
@@ -119,6 +119,12 @@ static struct {
    jfieldID rotation;
} gDisplayCaptureArgsClassInfo;

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

// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
void DeleteScreenshot(void* addr, void* context) {
    delete ((ScreenshotClient*) context);
@@ -347,24 +353,23 @@ static jobject nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCa
                                       namedColorSpace, captureResults.capturedSecureLayers);
}

static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTokenObj,
        jlong layerObject, jobject sourceCropObj, jfloat frameScale,
        jlongArray excludeObjectArray, jint format) {

    auto layer = reinterpret_cast<SurfaceControl *>(layerObject);
    if (layer == NULL) {
        return NULL;
    }

    Rect sourceCrop;
    if (sourceCropObj != NULL) {
        sourceCrop = rectFromObj(env, sourceCropObj);
static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject) {
    LayerCaptureArgs captureArgs;
    getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
    SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
            env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
    if (layer == nullptr) {
        return nullptr;
    }

    std::unordered_set<sp<IBinder>,ISurfaceComposer::SpHash<IBinder>> excludeHandles;
    captureArgs.layerHandle = layer->getHandle();
    captureArgs.childrenOnly =
            env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly);
    jlongArray excludeObjectArray = reinterpret_cast<jlongArray>(
            env->GetObjectField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.excludeLayers));
    if (excludeObjectArray != NULL) {
        const jsize len = env->GetArrayLength(excludeObjectArray);
        excludeHandles.reserve(len);
        captureArgs.excludeHandles.reserve(len);

        const jlong* objects = env->GetLongArrayElements(excludeObjectArray, nullptr);
        for (jsize i = 0; i < len; i++) {
@@ -373,33 +378,24 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTok
                jniThrowNullPointerException(env, "Exclude layer is null");
                return NULL;
            }
            excludeHandles.emplace(excludeObject->getHandle());
            captureArgs.excludeHandles.emplace(excludeObject->getHandle());
        }
        env->ReleaseLongArrayElements(excludeObjectArray, const_cast<jlong*>(objects), JNI_ABORT);
    }

    sp<GraphicBuffer> buffer;
    ui::Dataspace dataspace = ui::Dataspace::V0_SRGB;
    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    if (displayToken != nullptr) {
        const ui::ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(displayToken);
        dataspace = pickDataspaceFromColorMode(colorMode);
    }
    status_t res = ScreenshotClient::captureChildLayers(layer->getHandle(), dataspace,
                                                        static_cast<ui::PixelFormat>(format),
                                                        sourceCrop, excludeHandles, frameScale,
                                                        &buffer);
    ScreenCaptureResults captureResults;
    status_t res = ScreenshotClient::captureLayers(captureArgs, captureResults);
    if (res != NO_ERROR) {
        return NULL;
    }

    jobject jhardwareBuffer =
            android_hardware_HardwareBuffer_createFromAHardwareBuffer(env,
                                                                      buffer->toAHardwareBuffer());
    const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(dataspace);
    jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
            env, captureResults.buffer->toAHardwareBuffer());
    const jint namedColorSpace =
            fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace);
    return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz,
                                       gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer,
                                       namedColorSpace, false /* capturedSecureLayers */);
                                       namedColorSpace, captureResults.capturedSecureLayers);
}

static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) {
@@ -1659,8 +1655,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;",
            (void*)nativeCaptureDisplay },
    {"nativeCaptureLayers",
            "(Landroid/os/IBinder;JLandroid/graphics/Rect;"
            "F[JI)"
            "(Landroid/view/SurfaceControl$LayerCaptureArgs;)"
            "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;",
            (void*)nativeCaptureLayers },
    {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V",
@@ -1856,6 +1851,15 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gDisplayCaptureArgsClassInfo.rotation =
            GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I");

    jclass layerCaptureArgsClazz =
            FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs");
    gLayerCaptureArgsClassInfo.layer =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeLayer", "J");
    gLayerCaptureArgsClassInfo.excludeLayers =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeExcludeLayers", "[J");
    gLayerCaptureArgsClassInfo.childrenOnly =
            GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");

    return err;
}