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

Commit fd6989cd authored by Riley Andrews's avatar Riley Andrews
Browse files

Use the crop function in the surfaceflinger screenshot api.

- By having surfaceflinger crop the screenshot instead of
  WindowManagerService, this greatly reduces the size of
  of temporary screenshot buffers that tablets have to
  allocate.
- App to home, App to recents times are improved noticeably.

Change-Id: Iff889cc8c57b157778fb16993a71546fd9abfc00
Bug 17006948
Bug 16987565
parent 23ad2790
Loading
Loading
Loading
Loading
+44 −13
Original line number Diff line number Diff line
@@ -5801,6 +5801,29 @@ public class WindowManagerService extends IWindowManager.Stub
        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
    }

    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
        if (rot == Surface.ROTATION_90) {
            final int tmp = crop.top;
            crop.top = dw - crop.right;
            crop.right = crop.bottom;
            crop.bottom = dw - crop.left;
            crop.left = tmp;
        } else if (rot == Surface.ROTATION_180) {
            int tmp = crop.top;
            crop.top = dh - crop.bottom;
            crop.bottom = dh - tmp;
            tmp = crop.right;
            crop.right = dw - crop.left;
            crop.left = dw - tmp;
        } else if (rot == Surface.ROTATION_270) {
            final int tmp = crop.top;
            crop.top = crop.left;
            crop.left = dh - crop.bottom;
            crop.bottom = crop.right;
            crop.right = dh - tmp;
        }
    }

    /**
     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
@@ -5962,21 +5985,31 @@ public class WindowManagerService extends IWindowManager.Stub

                // Constrain frame to the screen size.
                frame.intersect(0, 0, dw, dh);
                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
                // of thumbnail is the same as the screen (in landscape) or square.
                scale = Math.max(width / (float) frame.width(), height / (float) frame.height());
                dw = (int)(dw * scale);
                dh = (int)(dh * scale);

                // Tell surface flinger what part of the image to crop. Take the top
                // right part of the application, and crop the larger dimension to fit.
                Rect crop = new Rect(frame);
                if (width / (float) frame.width() < height / (float) frame.height()) {
                    int cropWidth = (int)((float)width / (float)height * frame.height());
                    crop.right = crop.left + cropWidth;
                } else {
                    int cropHeight = (int)((float)height / (float)width * frame.width());
                    crop.bottom = crop.top + cropHeight;
                }

                // 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 = dw;
                    dw = dh;
                    dh = tmp;
                    final int tmp = width;
                    width = height;
                    height = tmp;
                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
                }

                // Surfaceflinger is not aware of orientation, so convert our logical
                // crop to surfaceflinger's portrait orientation.
                convertCropForSurfaceFlinger(crop, rot, dw, dh);

                if (DEBUG_SCREENSHOT) {
                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
                            + maxLayer + " appToken=" + appToken);
@@ -5995,7 +6028,7 @@ public class WindowManagerService extends IWindowManager.Stub
                if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
                        "Taking screenshot while rotating");

                rawss = SurfaceControl.screenshot(new Rect(), dw, dh, minLayer, maxLayer,
                rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
                        inRotation);
                if (rawss == null) {
                    Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
@@ -6012,11 +6045,8 @@ public class WindowManagerService extends IWindowManager.Stub
        if (DEBUG_SCREENSHOT) {
            bm.eraseColor(0xFF000000);
        }
        frame.scale(scale);
        Matrix matrix = new Matrix();
        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
        ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
        Canvas canvas = new Canvas(bm);
        canvas.drawBitmap(rawss, matrix, null);
        canvas.setBitmap(null);
@@ -6042,6 +6072,7 @@ public class WindowManagerService extends IWindowManager.Stub
        }

        rawss.recycle();

        return bm;
    }