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

Commit 689e091c authored by chaviw's avatar chaviw
Browse files

Updated screenshot code to reflect native changes.

The changes in native code removed using a GraphicBufferProducer and
instead use only a GraphicBuffer to generate screenshots. Updated JNI
code so it calls the screensot function that returns a GraphicBuffer
and handle returning either a Surface, GraphicBuffer, or Bitmap.

Also updated screencap shell code so it uses the new GraphicBuffer
screenshot code.

Test: Recents, screenshot from SystemUi, screenshot from shell.
Change-Id: I6cb4f619e59461790a2a8f0cd2ea1192d9ae66b6
parent 418346a8
Loading
Loading
Loading
Loading
+51 −46
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ int main(int argc, char** argv)
    void const* mapbase = MAP_FAILED;
    ssize_t mapsize = -1;

    void const* base = NULL;
    void* base = NULL;
    uint32_t w, s, h, f;
    android_dataspace d;
    size_t size = 0;
@@ -179,7 +179,6 @@ int main(int argc, char** argv)
    ProcessState::self()->setThreadPoolMaxThreadCount(0);
    ProcessState::self()->startThreadPool();

    ScreenshotClient screenshot;
    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
    if (display == NULL) {
        fprintf(stderr, "Unable to get handle for display %d\n", displayId);
@@ -199,25 +198,32 @@ int main(int argc, char** argv)
    uint8_t displayOrientation = configs[activeConfig].orientation;
    uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];

    status_t result = screenshot.update(display, Rect(),
            0 /* reqWidth */, 0 /* reqHeight */,
            INT32_MIN, INT32_MAX, /* all layers */
            false, captureOrientation);
    if (result == NO_ERROR) {
        base = screenshot.getPixels();
        w = screenshot.getWidth();
        h = screenshot.getHeight();
        s = screenshot.getStride();
        f = screenshot.getFormat();
        d = screenshot.getDataSpace();
        size = screenshot.getSize();
    sp<GraphicBuffer> outBuffer;
    status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */,
            0 /* reqHeight */, INT32_MIN, INT32_MAX, /* all layers */ false, captureOrientation,
            &outBuffer);
    if (result != NO_ERROR) {
        close(fd);
        _exit(1);
    }

    if (base != NULL) {
    result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);

    if (base == NULL) {
        close(fd);
        _exit(1);
    }

    w = outBuffer->getWidth();
    h = outBuffer->getHeight();
    s = outBuffer->getStride();
    f = outBuffer->getPixelFormat();
    d = HAL_DATASPACE_UNKNOWN;
    size = s * h * bytesPerPixel(f);

    if (png) {
        const SkImageInfo info =
                SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
                    dataSpaceToColorSpace(d));
            SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d));
        SkPixmap pixmap(info, base, s * bytesPerPixel(f));
        struct FDWStream final : public SkWStream {
          size_t fBytesWritten = 0;
@@ -245,7 +251,6 @@ int main(int argc, char** argv)
            base = (void *)((char *)base + s*Bpp);
        }
    }
    }
    close(fd);
    if (mapbase != MAP_FAILED) {
        munmap((void *)mapbase, mapsize);
+3 −13
Original line number Diff line number Diff line
@@ -55,8 +55,6 @@ public class SurfaceControl {
    private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform);
    private static native void nativeCaptureLayers(IBinder layerHandleToken, Surface consumer,
            Rect sourceCrop, float frameScale);
    private static native GraphicBuffer nativeCaptureLayers(IBinder layerHandleToken,
            Rect sourceCrop, float frameScale);

@@ -1179,22 +1177,14 @@ public class SurfaceControl {
     * Captures a layer and its children into the provided {@link Surface}.
     *
     * @param layerHandleToken The root layer to capture.
     * @param consumer         The {@link Surface} to capture the layer into.
     * @param sourceCrop       The portion of the root surface to capture; caller may pass in 'new
     *                         Rect()' or null if no cropping is desired.
     * @param frameScale       The desired scale of the returned buffer; the raw
     *                         screen will be scaled up/down.
     *
     * @return Returns a GraphicBuffer that contains the layer capture.
     */
    public static void captureLayers(IBinder layerHandleToken, Surface consumer, Rect sourceCrop,
            float frameScale) {
        nativeCaptureLayers(layerHandleToken, consumer, sourceCrop, frameScale);
    }

    /**
     * Same as {@link #captureLayers(IBinder, Surface, Rect, float)} except this
     * captures to a {@link GraphicBuffer} instead of a {@link Surface}.
     */
    public static GraphicBuffer captureLayersToBuffer(IBinder layerHandleToken, Rect sourceCrop,
    public static GraphicBuffer captureLayers(IBinder layerHandleToken, Rect sourceCrop,
            float frameScale) {
        return nativeCaptureLayers(layerHandleToken, sourceCrop, frameScale);
    }
+1 −17
Original line number Diff line number Diff line
@@ -517,23 +517,7 @@ static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeOb
        jobject graphicBuffer) {
    Surface* surface = reinterpret_cast<Surface*>(nativeObject);
    sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
    if (bp == nullptr) {
        return BAD_VALUE;
    }
    int err = ((ANativeWindow*)surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
            NATIVE_WINDOW_API_CPU);
    if (err != OK) {
        return err;
    }
    err = surface->attachBuffer(bp->getNativeBuffer());
    if (err != OK) {
        return err;
    }
    err = ((ANativeWindow*)surface)->queueBuffer(surface, bp->getNativeBuffer(), -1);
    if (err != OK) {
        return err;
    }
    err = surface->disconnect(NATIVE_WINDOW_API_CPU);
    int err = Surface::attachAndQueueBuffer(surface, bp);
    return err;
}

+27 −65
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz,
        maxLayer = INT32_MAX;
    }
    sp<GraphicBuffer> buffer;
    status_t res = ScreenshotClient::captureToBuffer(displayToken,
    status_t res = ScreenshotClient::capture(displayToken,
            sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform,
            rotation, &buffer);
    if (res != NO_ERROR) {
@@ -201,15 +201,18 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
        maxLayer = INT32_MAX;
    }

    res = screenshot->update(displayToken, sourceCrop, width, height,
        minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
    sp<GraphicBuffer> buffer;
    res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
        minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation), &buffer);
    if (res != NO_ERROR) {
        return NULL;
    }

    SkColorType colorType;
    SkAlphaType alphaType;
    switch (screenshot->getFormat()) {

    PixelFormat format = buffer->getPixelFormat();
    switch (format) {
        case PIXEL_FORMAT_RGBX_8888: {
            colorType = kRGBA_8888_SkColorType;
            alphaType = kOpaque_SkAlphaType;
@@ -235,33 +238,12 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
        }
    }

    sk_sp<SkColorSpace> colorSpace;
    if (screenshot->getDataSpace() == HAL_DATASPACE_DISPLAY_P3) {
        colorSpace = SkColorSpace::MakeRGB(
                SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
    } else {
        colorSpace = SkColorSpace::MakeSRGB();
    }

    SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
                                                   screenshot->getHeight(),
                                                   colorType,
                                                   alphaType,
                                                   colorSpace);

    const size_t rowBytes =
            screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());

    if (!screenshotInfo.width() || !screenshotInfo.height()) {
        return NULL;
    }
    SkImageInfo info = SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
                                         colorType, alphaType,
                                         SkColorSpace::MakeSRGB());

    auto bitmap = new Bitmap(
            (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
            screenshotInfo, rowBytes);
    screenshot.release();
    bitmap->setImmutable();
    return bitmap::createBitmap(env, bitmap,
    auto bitmap = sk_sp<Bitmap>(new Bitmap(buffer.get(), info));
    return bitmap::createBitmap(env, bitmap.release(),
                                android::bitmap::kBitmapCreateFlag_Premultiplied, NULL);
}

@@ -269,32 +251,7 @@ static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
        jobject surfaceObj, jobject sourceCropObj, jint width, jint height,
        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    if (displayToken != NULL) {
        sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
        if (consumer != 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);

            if (allLayers) {
                minLayer = INT32_MIN;
                maxLayer = INT32_MAX;
            }
            ScreenshotClient::capture(displayToken,
                    consumer->getIGraphicBufferProducer(), sourceCrop,
                    width, height, minLayer, maxLayer,
                    useIdentityTransform);
        }
    }
}

static void nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
        jobject surfaceObj, jobject sourceCropObj, jfloat frameScale) {

    sp<IBinder> layerHandle = ibinderForJavaObject(env, layerHandleToken);
    if (layerHandle == NULL) {
    if (displayToken == NULL) {
        return;
    }

@@ -308,11 +265,19 @@ static void nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleTo
        sourceCrop = rectFromObj(env, sourceCropObj);
    }

    ScreenshotClient::captureLayers(layerHandle, consumer->getIGraphicBufferProducer(), sourceCrop,
            frameScale);
    if (allLayers) {
        minLayer = INT32_MIN;
        maxLayer = INT32_MAX;
    }

static jobject nativeCaptureLayersToBuffer(JNIEnv* env, jclass clazz, jobject layerHandleToken,
    sp<GraphicBuffer> buffer;
    ScreenshotClient::capture(displayToken, sourceCrop, width, height, minLayer, maxLayer,
                              useIdentityTransform, 0, &buffer);

    Surface::attachAndQueueBuffer(consumer.get(), buffer);
}

static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
        jobject sourceCropObj, jfloat frameScale) {

    sp<IBinder> layerHandle = ibinderForJavaObject(env, layerHandleToken);
@@ -326,8 +291,7 @@ static jobject nativeCaptureLayersToBuffer(JNIEnv* env, jclass clazz, jobject la
    }

    sp<GraphicBuffer> buffer;
    status_t res = ScreenshotClient::captureLayersToBuffer(layerHandle, sourceCrop, frameScale,
            &buffer);
    status_t res = ScreenshotClient::captureLayers(layerHandle, sourceCrop, frameScale, &buffer);
    if (res != NO_ERROR) {
        return NULL;
    }
@@ -1010,10 +974,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
    {"nativeScreenshotToBuffer",
     "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;",
     (void*)nativeScreenshotToBuffer },
    {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;F)V",
            (void*)nativeCaptureLayers },
    {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
            (void*)nativeCaptureLayersToBuffer },
            (void*)nativeCaptureLayers },
};

int register_android_view_SurfaceControl(JNIEnv* env)
+2 −2
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
        Matrix matrix = new Matrix();
        int overlayColor = 0x40FFFFFF;

        Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, data.image.getConfig());
        Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888);
        matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
        c.setBitmap(picture);
        c.drawBitmap(data.image, matrix, paint);
@@ -171,7 +171,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {

        // Note, we can't use the preview for the small icon, since it is non-square
        float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
        Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, data.image.getConfig());
        Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
        matrix.setScale(scale, scale);
        matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
                (iconSize - (scale * mImageHeight)) / 2);
Loading