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

Commit 16ec12ae authored by Dan Stoza's avatar Dan Stoza
Browse files

Allow disabling layer rotation during screenshots

Add the ability to ignore layers' transformation matrices during
screenshot capture, which will allow the window manager to capture
unrotated images for recents during the device rotation animation.

Bug: 11805195
Change-Id: I96e65506b198d34724eb3aa84815aae6f6de4935
parent d5c8044e
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) == NO_ERROR) {
    if (display != NULL && screenshot.update(display, false) == NO_ERROR) {
        base = screenshot.getPixels();
        w = screenshot.getWidth();
        h = screenshot.getHeight();
+25 −11
Original line number Diff line number Diff line
@@ -39,9 +39,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);
            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);
            int width, int height, int minLayer, int maxLayer, boolean allLayers,
            boolean useIdentityTransform);

    private static native void nativeOpenTransaction();
    private static native void nativeCloseTransaction();
@@ -554,10 +556,15 @@ public class SurfaceControl {
     * include in the screenshot.
     * @param maxLayer The highest (top-most Z order) surface layer to
     * include in the screenshot.
     * @param useIdentityTransform Replace whatever transformation (rotation,
     * scaling, translation) the surface layers are currently using with the
     * identity transformation while taking the screenshot.
     */
    public static void screenshot(IBinder display, Surface consumer,
            int width, int height, int minLayer, int maxLayer) {
        screenshot(display, consumer, width, height, minLayer, maxLayer, false);
            int width, int height, int minLayer, int maxLayer,
            boolean useIdentityTransform) {
        screenshot(display, consumer, width, height, minLayer, maxLayer, false,
                useIdentityTransform);
    }

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

    /**
@@ -582,7 +589,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);
        screenshot(display, consumer, 0, 0, 0, 0, true, false);
    }


@@ -602,15 +609,20 @@ public class SurfaceControl {
     * include in the screenshot.
     * @param maxLayer The highest (top-most Z order) surface layer to
     * include in the screenshot.
     * @param useIdentityTransform Replace whatever transformation (rotation,
     * scaling, translation) the surface layers are currently using with the
     * identity transformation while taking the screenshot.
     * @return Returns a Bitmap containing the screen contents, or null
     * 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) {
    public static Bitmap screenshot(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);
        return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false,
                useIdentityTransform);
    }

    /**
@@ -629,17 +641,19 @@ 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);
        return nativeScreenshot(displayToken, width, height, 0, 0, true, false);
    }

    private static void screenshot(IBinder display, Surface consumer,
            int width, int height, int minLayer, int maxLayer, boolean allLayers) {
            int width, int height, int minLayer, int maxLayer, boolean allLayers,
            boolean useIdentityTransform) {
        if (display == null) {
            throw new IllegalArgumentException("displayToken must not be null");
        }
        if (consumer == null) {
            throw new IllegalArgumentException("consumer must not be null");
        }
        nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers);
        nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers,
                useIdentityTransform);
    }
}
+16 −10
Original line number Diff line number Diff line
@@ -72,12 +72,15 @@ public:
    }

    status_t update(const sp<IBinder>& display, int width, int height,
            int minLayer, int maxLayer, bool allLayers) {
            int minLayer, int maxLayer, bool allLayers,
            bool useIdentityTransform) {
        status_t res = (width > 0 && height > 0)
                ? (allLayers
                        ? mScreenshot.update(display, width, height)
                        : mScreenshot.update(display, width, height, minLayer, maxLayer))
                : mScreenshot.update(display);
                        ? mScreenshot.update(display, width, height,
                                useIdentityTransform)
                        : mScreenshot.update(display, width, height,
                                minLayer, maxLayer, useIdentityTransform))
                : mScreenshot.update(display, useIdentityTransform);
        if (res != NO_ERROR) {
            return res;
        }
@@ -162,7 +165,8 @@ static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
}

static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj,
        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
        bool useIdentityTransform) {
    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    if (displayToken == NULL) {
        return NULL;
@@ -170,7 +174,7 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display

    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
    if (pixels->update(displayToken, width, height,
            minLayer, maxLayer, allLayers) != NO_ERROR) {
            minLayer, maxLayer, allLayers, useIdentityTransform) != NO_ERROR) {
        delete pixels;
        return NULL;
    }
@@ -202,7 +206,8 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display

static void nativeScreenshot(JNIEnv* env, jclass clazz,
        jobject displayTokenObj, jobject surfaceObj,
        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
        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);
@@ -213,7 +218,8 @@ static void nativeScreenshot(JNIEnv* env, jclass clazz,
            }
            ScreenshotClient::capture(
                    displayToken, consumer->getIGraphicBufferProducer(),
                    width, height, uint32_t(minLayer), uint32_t(maxLayer));
                    width, height, uint32_t(minLayer), uint32_t(maxLayer),
                    useIdentityTransform);
        }
    }
}
@@ -417,9 +423,9 @@ static JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeRelease },
    {"nativeDestroy", "(J)V",
            (void*)nativeDestroy },
    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZZ)Landroid/graphics/Bitmap;",
            (void*)nativeScreenshotBitmap },
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZ)V",
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZZ)V",
            (void*)nativeScreenshot },
    {"nativeOpenTransaction", "()V",
            (void*)nativeOpenTransaction },
+5 −1
Original line number Diff line number Diff line
@@ -5757,7 +5757,11 @@ public class WindowManagerService extends IWindowManager.Stub
                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
                    }
                }
                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
                // TODO: Replace 'false' in the following line with a variable that indicates
                // 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);
            }
        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +