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

Commit 00f53584 authored by Dan Stoza's avatar Dan Stoza Committed by Android (Google) Code Review
Browse files

Merge "SurfaceFlinger: Add sourceCrop to screenshot"

parents a46d3e11 9890e341
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ int main(int argc, char** argv)

    ScreenshotClient screenshot;
    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
    if (display != NULL && screenshot.update(display, false) == NO_ERROR) {
    if (display != NULL && screenshot.update(display, Rect(), false) == NO_ERROR) {
        base = screenshot.getPixels();
        w = screenshot.getWidth();
        h = screenshot.getHeight();
+18 −16
Original line number Diff line number Diff line
@@ -38,11 +38,11 @@ public class SurfaceControl {
    private static native void nativeDestroy(long nativeObject);

    private static native Bitmap nativeScreenshot(IBinder displayToken,
            int width, int height, int minLayer, int maxLayer, boolean allLayers,
            boolean useIdentityTransform);
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform);
    private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
            int width, int height, int minLayer, int maxLayer, boolean allLayers,
            boolean useIdentityTransform);
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform);

    private static native void nativeOpenTransaction();
    private static native void nativeCloseTransaction();
@@ -597,8 +597,8 @@ public class SurfaceControl {
    public static void screenshot(IBinder display, Surface consumer,
            int width, int height, int minLayer, int maxLayer,
            boolean useIdentityTransform) {
        screenshot(display, consumer, width, height, minLayer, maxLayer, false,
                useIdentityTransform);
        screenshot(display, consumer, new Rect(), width, height, minLayer, maxLayer,
                false, useIdentityTransform);
    }

    /**
@@ -613,7 +613,7 @@ public class SurfaceControl {
     */
    public static void screenshot(IBinder display, Surface consumer,
            int width, int height) {
        screenshot(display, consumer, width, height, 0, 0, true, false);
        screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
    }

    /**
@@ -623,7 +623,7 @@ public class SurfaceControl {
     * @param consumer The {@link Surface} to take the screenshot into.
     */
    public static void screenshot(IBinder display, Surface consumer) {
        screenshot(display, consumer, 0, 0, 0, 0, true, false);
        screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false);
    }

    /**
@@ -634,6 +634,8 @@ public class SurfaceControl {
     * the versions that use a {@link Surface} instead, such as
     * {@link SurfaceControl#screenshot(IBinder, Surface)}.
     *
     * @param sourceCrop The portion of the screen to capture into the Bitmap;
     * caller may pass in 'new Rect()' if no cropping is desired.
     * @param width The desired width of the returned bitmap; the raw
     * screen will be scaled down to this size.
     * @param height The desired height of the returned bitmap; the raw
@@ -649,13 +651,13 @@ public class SurfaceControl {
     * if an error occurs. Make sure to call Bitmap.recycle() as soon as
     * possible, once its content is not needed anymore.
     */
    public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer,
            boolean useIdentityTransform) {
    public static Bitmap screenshot(Rect sourceCrop, int width, int height,
            int minLayer, int maxLayer, boolean useIdentityTransform) {
        // TODO: should take the display as a parameter
        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
        return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false,
                useIdentityTransform);
        return nativeScreenshot(displayToken, sourceCrop, width, height,
                minLayer, maxLayer, false, useIdentityTransform);
    }

    /**
@@ -674,10 +676,10 @@ public class SurfaceControl {
        // TODO: should take the display as a parameter
        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
        return nativeScreenshot(displayToken, width, height, 0, 0, true, false);
        return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true, false);
    }

    private static void screenshot(IBinder display, Surface consumer,
    private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
            int width, int height, int minLayer, int maxLayer, boolean allLayers,
            boolean useIdentityTransform) {
        if (display == null) {
@@ -686,7 +688,7 @@ public class SurfaceControl {
        if (consumer == null) {
            throw new IllegalArgumentException("consumer must not be null");
        }
        nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers,
                useIdentityTransform);
        nativeScreenshot(display, consumer, sourceCrop, width, height,
                minLayer, maxLayer, allLayers, useIdentityTransform);
    }
}
+40 −15
Original line number Diff line number Diff line
@@ -61,6 +61,13 @@ static struct {
    jfieldID secure;
} gPhysicalDisplayInfoClassInfo;

static struct {
    jfieldID bottom;
    jfieldID left;
    jfieldID right;
    jfieldID top;
} gRectClassInfo;

// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
void DeleteScreenshot(void* addr, void* context) {
    SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
@@ -104,25 +111,32 @@ static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
    ctrl->decStrong((void *)nativeCreate);
}

static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj,
        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
        bool useIdentityTransform) {
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
        jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    if (displayToken == NULL) {
        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);

    ScreenshotClient* screenshot = new ScreenshotClient();
    status_t res;
    if (width > 0 && height > 0) {
        if (allLayers) {
            res = screenshot->update(displayToken, width, height, useIdentityTransform);
        } else {
            res = screenshot->update(displayToken, width, height, minLayer, maxLayer,
            res = screenshot->update(displayToken, sourceCrop, width, height,
                    useIdentityTransform);
        } else {
            res = screenshot->update(displayToken, sourceCrop, width, height,
                    minLayer, maxLayer, useIdentityTransform);
        }
    } else {
        res = screenshot->update(displayToken, useIdentityTransform);
        res = screenshot->update(displayToken, sourceCrop, useIdentityTransform);
    }
    if (res != NO_ERROR) {
        delete screenshot;
@@ -174,20 +188,25 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display
            GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
}

static void nativeScreenshot(JNIEnv* env, jclass clazz,
        jobject displayTokenObj, jobject surfaceObj,
        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
        bool useIdentityTransform) {
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 = 0;
                maxLayer = -1;
            }
            ScreenshotClient::capture(
                    displayToken, consumer->getIGraphicBufferProducer(),
            ScreenshotClient::capture(displayToken,
                    consumer->getIGraphicBufferProducer(), sourceCrop,
                    width, height, uint32_t(minLayer), uint32_t(maxLayer),
                    useIdentityTransform);
        }
@@ -563,9 +582,9 @@ static JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeRelease },
    {"nativeDestroy", "(J)V",
            (void*)nativeDestroy },
    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZZ)Landroid/graphics/Bitmap;",
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;",
            (void*)nativeScreenshotBitmap },
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZZ)V",
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
            (void*)nativeScreenshot },
    {"nativeOpenTransaction", "()V",
            (void*)nativeOpenTransaction },
@@ -640,6 +659,12 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");

    jclass rectClazz = env->FindClass("android/graphics/Rect");
    gRectClassInfo.bottom = env->GetFieldID(rectClazz, "bottom", "I");
    gRectClassInfo.left = env->GetFieldID(rectClazz, "left", "I");
    gRectClassInfo.right = env->GetFieldID(rectClazz, "right", "I");
    gRectClassInfo.top = env->GetFieldID(rectClazz, "top", "I");

    jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
    jfieldID undefined_time_nano_field =  env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
    nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
+3 −1
Original line number Diff line number Diff line
@@ -5802,7 +5802,9 @@ public class WindowManagerService extends IWindowManager.Stub
                // whether the screenshot should use the identity transformation matrix
                // (e.g., enable it when taking a screenshot for recents, since we might be in
                // the middle of the rotation animation, but don't want a rotated recent image).
                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer, false);
                // TODO: Replace 'new Rect()' with the portion of the screen to capture for the
                // screenshot.
                rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer, false);
            }
        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +