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

Commit 1d134065 authored by Riley Andrews's avatar Riley Andrews
Browse files

Use surfaceflinger for recents thumbnail rotations.

+ This removes 30ms of latency on app to home transitions
  on volantis.
Change-Id: Ia3747b8f8be0d41b9b3d095753edfe1df185c84d
parent 1893d9b3
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ public class SurfaceControl {

    private static native Bitmap nativeScreenshot(IBinder displayToken,
            Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
            boolean allLayers, boolean useIdentityTransform);
            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);
@@ -688,17 +688,23 @@ public class SurfaceControl {
     * @param useIdentityTransform Replace whatever transformation (rotation,
     * scaling, translation) the surface layers are currently using with the
     * identity transformation while taking the screenshot.
     * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
     * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
     * screenshots in its native portrait orientation by default, so this is
     * useful for returning screenshots that are independent of device
     * orientation.
     * @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(Rect sourceCrop, int width, int height,
            int minLayer, int maxLayer, boolean useIdentityTransform) {
            int minLayer, int maxLayer, boolean useIdentityTransform,
            int rotation) {
        // TODO: should take the display as a parameter
        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
        return nativeScreenshot(displayToken, sourceCrop, width, height,
                minLayer, maxLayer, false, useIdentityTransform);
                minLayer, maxLayer, false, useIdentityTransform, rotation);
    }

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

    private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
+9 −12
Original line number Diff line number Diff line
@@ -117,7 +117,8 @@ static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {

static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
        jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
        jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
        int rotation) {
    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    if (displayToken == NULL) {
        return NULL;
@@ -131,17 +132,13 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,

    SkAutoTDelete<ScreenshotClient> screenshot(new ScreenshotClient());
    status_t res;
    if (width > 0 && height > 0) {
    if (allLayers) {
            res = screenshot->update(displayToken, sourceCrop, width, height,
                    useIdentityTransform);
        } else {
            res = screenshot->update(displayToken, sourceCrop, width, height,
                    minLayer, maxLayer, useIdentityTransform);
        }
    } else {
        res = screenshot->update(displayToken, sourceCrop, useIdentityTransform);
        minLayer = 0;
        maxLayer = -1UL;
    }

    res = screenshot->update(displayToken, sourceCrop, width, height,
        minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
    if (res != NO_ERROR) {
        return NULL;
    }
@@ -588,7 +585,7 @@ static JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeRelease },
    {"nativeDestroy", "(J)V",
            (void*)nativeDestroy },
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;",
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
            (void*)nativeScreenshotBitmap },
    {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
            (void*)nativeScreenshot },
+12 −22
Original line number Diff line number Diff line
@@ -5860,7 +5860,7 @@ public class WindowManagerService extends IWindowManager.Stub
    @Override
    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
            int height, boolean force565) {
        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
        if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
                "screenshotApplications()")) {
            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
        }
@@ -5880,7 +5880,7 @@ public class WindowManagerService extends IWindowManager.Stub
            return null;
        }

        Bitmap rawss = null;
        Bitmap bm = null;

        int maxLayer = 0;
        final Rect frame = new Rect();
@@ -6021,10 +6021,8 @@ public class WindowManagerService extends IWindowManager.Stub

                // The screenshot API does not apply the current screen rotation.
                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();

                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
                    final int tmp = width;
                    width = height;
                    height = tmp;
                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
                }

@@ -6050,9 +6048,9 @@ public class WindowManagerService extends IWindowManager.Stub
                if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
                        "Taking screenshot while rotating");

                rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
                        inRotation);
                if (rawss == null) {
                bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
                        inRotation, rot);
                if (bm == null) {
                    Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
                            + ") to layer " + maxLayer);
                    return null;
@@ -6062,17 +6060,6 @@ public class WindowManagerService extends IWindowManager.Stub
            break;
        }

        Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
                Config.RGB_565 : rawss.getConfig());
        if (DEBUG_SCREENSHOT) {
            bm.eraseColor(0xFF000000);
        }
        Matrix matrix = new Matrix();
        ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
        Canvas canvas = new Canvas(bm);
        canvas.drawBitmap(rawss, matrix, null);
        canvas.setBitmap(null);

        if (DEBUG_SCREENSHOT) {
            // TEST IF IT's ALL BLACK
            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
@@ -6093,9 +6080,12 @@ public class WindowManagerService extends IWindowManager.Stub
            }
        }

        rawss.recycle();

        return bm;
        // Copy the screenshot bitmap to another buffer so that the gralloc backed
        // bitmap will not have a long lifetime. Gralloc memory can be pinned or
        // duplicated and might have a higher cost than a skia backed buffer.
        Bitmap ret = bm.copy(bm.getConfig(),true);
        bm.recycle();
        return ret;
    }

    /**