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

Commit 29fdbc67 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge changes from topic "hw_bitmap"

* changes:
  Update screenshot requests to render proper crop and rotation.
  Revert "Revert "Updated screenshot code to reflect native changes.""
parents efb75842 a69e0a7d
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);
+2 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app;

import android.accessibilityservice.IAccessibilityServiceClient;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.view.InputEvent;
import android.view.WindowContentFrameStats;
import android.view.WindowAnimationFrameStats;
@@ -37,7 +38,7 @@ interface IUiAutomationConnection {
    void disconnect();
    boolean injectInputEvent(in InputEvent event, boolean sync);
    boolean setRotation(int rotation);
    Bitmap takeScreenshot(int width, int height);
    Bitmap takeScreenshot(in Rect crop, int rotation);
    boolean clearWindowContentFrameStats(int windowId);
    WindowContentFrameStats getWindowContentFrameStats(int windowId);
    void clearWindowAnimationFrameStats();
+4 −45
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.annotation.TestApi;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManagerGlobal;
import android.os.IBinder;
@@ -690,42 +691,15 @@ public final class UiAutomation {
                .getRealDisplay(Display.DEFAULT_DISPLAY);
        Point displaySize = new Point();
        display.getRealSize(displaySize);
        final int displayWidth = displaySize.x;
        final int displayHeight = displaySize.y;

        final float screenshotWidth;
        final float screenshotHeight;

        final int rotation = display.getRotation();
        switch (rotation) {
            case ROTATION_FREEZE_0: {
                screenshotWidth = displayWidth;
                screenshotHeight = displayHeight;
            } break;
            case ROTATION_FREEZE_90: {
                screenshotWidth = displayHeight;
                screenshotHeight = displayWidth;
            } break;
            case ROTATION_FREEZE_180: {
                screenshotWidth = displayWidth;
                screenshotHeight = displayHeight;
            } break;
            case ROTATION_FREEZE_270: {
                screenshotWidth = displayHeight;
                screenshotHeight = displayWidth;
            } break;
            default: {
                throw new IllegalArgumentException("Invalid rotation: "
                        + rotation);
            }
        }
        int rotation = display.getRotation();

        // Take the screenshot
        Bitmap screenShot = null;
        try {
            // Calling out without a lock held.
            screenShot = mUiAutomationConnection.takeScreenshot((int) screenshotWidth,
                    (int) screenshotHeight);
            screenShot = mUiAutomationConnection.takeScreenshot(
                    new Rect(0, 0, displaySize.x, displaySize.y), rotation);
            if (screenShot == null) {
                return null;
            }
@@ -734,21 +708,6 @@ public final class UiAutomation {
            return null;
        }

        // Rotate the screenshot to the current orientation
        if (rotation != ROTATION_FREEZE_0) {
            Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight,
                    Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(unrotatedScreenShot);
            canvas.translate(unrotatedScreenShot.getWidth() / 2,
                    unrotatedScreenShot.getHeight() / 2);
            canvas.rotate(getDegreesForRotation(rotation));
            canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2);
            canvas.drawBitmap(screenShot, 0, 0, null);
            canvas.setBitmap(null);
            screenShot.recycle();
            screenShot = unrotatedScreenShot;
        }

        // Optimization
        screenShot.setHasAlpha(false);

+5 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.accessibilityservice.IAccessibilityServiceClient;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Binder;
import android.os.IBinder;
@@ -153,7 +154,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
    }

    @Override
    public Bitmap takeScreenshot(int width, int height) {
    public Bitmap takeScreenshot(Rect crop, int rotation) {
        synchronized (mLock) {
            throwIfCalledByNotTrustedUidLocked();
            throwIfShutdownLocked();
@@ -161,7 +162,9 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            return SurfaceControl.screenshot(width, height);
            int width = crop.width();
            int height = crop.height();
            return SurfaceControl.screenshot(crop, width, height, rotation);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
+34 −17
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.view;

import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import android.annotation.Size;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
@@ -55,8 +58,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);

@@ -1144,22 +1145,35 @@ public class SurfaceControl {

    /**
     * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
     * includes all Surfaces in the screenshot.
     * includes all Surfaces in the screenshot. This will also update the orientation so it
     * sends the correct coordinates to SF based on the rotation value.
     *
     * @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
     * screen will be scaled down to this size.
     * @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(int width, int height) {
    public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
        // 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, Surface.ROTATION_0);
        if (rotation == ROTATION_90 || rotation == ROTATION_270) {
            rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
        }

        SurfaceControl.rotateCropForSF(sourceCrop, rotation);
        return nativeScreenshot(displayToken, sourceCrop, width, height, 0, 0, true,
                false, rotation);
    }

    private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
@@ -1175,26 +1189,29 @@ public class SurfaceControl {
                minLayer, maxLayer, allLayers, useIdentityTransform);
    }

    private static void rotateCropForSF(Rect crop, int rot) {
        if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
            int tmp = crop.top;
            crop.top = crop.left;
            crop.left = tmp;
            tmp = crop.right;
            crop.right = crop.bottom;
            crop.bottom = tmp;
        }
    }

    /**
     * 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);
    }
Loading