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

Commit 6486d31d authored by Robert Carr's avatar Robert Carr
Browse files

Expose SurfaceControl method to screenshot to GraphicBuffer.

A graphic buffer is most useful, as we can both attach it
to starting windows, and directly use it in Sys-UI. The old
codepath for starting windows/saved surfaces, is co-existing
at the moment, so I don't make large attempts to clean up
the existing screenshot code.

Bug: 31339431
Test: Manual test in combination with other branches
Change-Id: I562fdd5460dbce3201ba090272e8731850780f20
parent d26d2af7
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.view;

import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
@@ -42,6 +43,9 @@ public class SurfaceControl {
    private static native Bitmap nativeScreenshot(IBinder displayToken,
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform, int rotation);
    private static native GraphicBuffer nativeScreenshotToBuffer(IBinder displayToken,
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform, int rotation);
    private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform);
@@ -827,6 +831,19 @@ public class SurfaceControl {
                minLayer, maxLayer, false, useIdentityTransform, rotation);
    }

    /**
     * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)}
     * but returns a GraphicBuffer.
     */
    public static GraphicBuffer screenshotToBuffer(Rect sourceCrop, int width, int height,
            int minLayer, int maxLayer, boolean useIdentityTransform,
            int rotation) {
        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
        return nativeScreenshotToBuffer(displayToken, sourceCrop, width, height,
                minLayer, maxLayer, false, useIdentityTransform, rotation);
    }

    /**
     * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
     * includes all Surfaces in the screenshot.
+11 −2
Original line number Diff line number Diff line
@@ -101,6 +101,13 @@ public:
// GraphicBuffer lifecycle
// ----------------------------------------------------------------------------

static jlong android_graphics_GraphicBuffer_wrap(JNIEnv* env, jobject clazz,
        jlong unwrapped) {
    sp<GraphicBuffer> b(reinterpret_cast<GraphicBuffer*>(unwrapped));
    GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(b);
    return reinterpret_cast<jlong>(wrapper);
}

static jlong android_graphics_GraphicBuffer_create(JNIEnv* env, jobject clazz,
        jint width, jint height, jint format, jint usage) {

@@ -298,7 +305,9 @@ static const JNINativeMethod gMethods[] = {
    { "nLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)Z",
            (void*) android_graphics_GraphicBuffer_lockCanvas },
    { "nUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)Z",
            (void*) android_graphics_GraphicBuffer_unlockCanvasAndPost }
            (void*) android_graphics_GraphicBuffer_unlockCanvasAndPost },
    { "nWrapGraphicBuffer", "(J)J",
            (void*) android_graphics_GraphicBuffer_wrap }
};

int register_android_graphics_GraphicBuffer(JNIEnv* env) {
+54 −6
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#define LOG_TAG "SurfaceControl"
#define LOG_NDEBUG 0

#include "android_os_Parcel.h"
#include "android_util_Binder.h"
@@ -89,6 +90,11 @@ static struct {
    jmethodID ctor;
} gHdrCapabilitiesClassInfo;

static struct {
    jclass clazz;
    jmethodID builder;
} gGraphicBufferClassInfo;

// ----------------------------------------------------------------------------

static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
@@ -123,6 +129,44 @@ static void nativeDisconnect(JNIEnv* env, jclass clazz, jlong nativeObject) {
    }
}

static Rect rectFromObj(JNIEnv* env, jobject rectObj) {
    int left = env->GetIntField(rectObj, gRectClassInfo.left);
    int top = env->GetIntField(rectObj, gRectClassInfo.top);
    int right = env->GetIntField(rectObj, gRectClassInfo.right);
    int bottom = env->GetIntField(rectObj, gRectClassInfo.bottom);
    return Rect(left, top, right, bottom);
}

static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz,
        jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
        int rotation) {
    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    if (displayToken == NULL) {
        return NULL;
    }
    Rect sourceCrop = rectFromObj(env, sourceCropObj);
    if (allLayers) {
        minLayer = 0;
        maxLayer = -1;
    }
    sp<GraphicBuffer> buffer;
    status_t res = ScreenshotClient::captureToBuffer(displayToken,
            sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform,
            rotation, &buffer);
    if (res != NO_ERROR) {
        return NULL;
    }

    return env->CallStaticObjectMethod(gGraphicBufferClassInfo.clazz,
            gGraphicBufferClassInfo.builder,
            buffer->getWidth(),
            buffer->getHeight(),
            buffer->getPixelFormat(),
            buffer->getUsage(),
            (void*)buffer.get());
}

static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
        jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
@@ -132,11 +176,7 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
        return NULL;
    }

    int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
    int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
    int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
    int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
    Rect sourceCrop(left, top, right, bottom);
    Rect sourceCrop = rectFromObj(env, sourceCropObj);

    std::unique_ptr<ScreenshotClient> screenshot(new ScreenshotClient());
    status_t res;
@@ -787,6 +827,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeGetHandle },
    {"nativeGetTransformToDisplayInverse", "(J)Z",
     (void*)nativeGetTransformToDisplayInverse },
    {"nativeScreenshotToBuffer",
     "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;",
     (void*)nativeScreenshotToBuffer },
};

int register_android_view_SurfaceControl(JNIEnv* env)
@@ -836,6 +879,11 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gHdrCapabilitiesClassInfo.ctor = GetMethodIDOrDie(env, hdrCapabilitiesClazz, "<init>",
            "([IFFF)V");

    jclass graphicsBufferClazz = FindClassOrDie(env, "android/graphics/GraphicBuffer");
    gGraphicBufferClassInfo.clazz = MakeGlobalRefOrDie(env, graphicsBufferClazz);
    gGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env, graphicsBufferClazz,
            "createFromExisting", "(IIIIJ)Landroid/graphics/GraphicBuffer;");

    return err;
}

+14 −0
Original line number Diff line number Diff line
@@ -92,6 +92,19 @@ public class GraphicBuffer implements Parcelable {
        mNativeObject = nativeObject;
    }

    /**
     * For SurfaceControl JNI.
     * @hide
     */
    public static GraphicBuffer createFromExisting(int width, int height,
            int format, int usage, long unwrappedNativeObject) {
        long nativeObject = nWrapGraphicBuffer(unwrappedNativeObject);
        if (nativeObject != 0) {
            return new GraphicBuffer(width, height, format, usage, nativeObject);
        }
        return null;
    }

    /**
     * Returns the width of this buffer in pixels.
     */
@@ -286,4 +299,5 @@ public class GraphicBuffer implements Parcelable {
    private static native long nReadGraphicBufferFromParcel(Parcel in);
    private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty);
    private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas);
    private static native long nWrapGraphicBuffer(long nativeObject);
}