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

Commit 38b17ad2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Use screenshotToBuffer"

parents ef99fb85 6a7a8599
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -617,7 +617,7 @@ public class AppWindowContainerController
            }
            return dc.screenshotApplications(mToken.asBinder(), width, height,
                    false /* includeFullDisplay */, frameScale, Bitmap.Config.RGB_565,
                    false /* wallpaperOnly */, false /* includeDecor */, true /* toAshmem */);
                    false /* wallpaperOnly */, false /* includeDecor */);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }
+60 −40
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ import android.annotation.NonNull;
import android.app.ActivityManager.StackId;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -2105,12 +2106,55 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
     * @param includeDecor whether to include window decors, like the status or navigation bar
     *                     background of the window
     * @param toAshmem whether to convert the resulting bitmap to ashmem; this should be set to
     *                 true if the Bitmap is sent over binder, and false otherwise
     */
    Bitmap screenshotApplications(IBinder appToken, int width, int height,
            boolean includeFullDisplay, float frameScale, Bitmap.Config config,
            boolean wallpaperOnly, boolean includeDecor, boolean toAshmem) {
            boolean wallpaperOnly, boolean includeDecor) {
        Bitmap bitmap = screenshotApplications(appToken, width, height, includeFullDisplay,
                frameScale, wallpaperOnly, includeDecor, SurfaceControl::screenshot);

        if (DEBUG_SCREENSHOT) {
            // TEST IF IT's ALL BLACK
            int[] buffer = new int[bitmap.getWidth() * bitmap.getHeight()];
            bitmap.getPixels(buffer, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),
                    bitmap.getHeight());
            boolean allBlack = true;
            final int firstColor = buffer[0];
            for (int i = 0; i < buffer.length; i++) {
                if (buffer[i] != firstColor) {
                    allBlack = false;
                    break;
                }
            }
            if (allBlack) {
                final WindowState appWin = mScreenshotApplicationState.appWin;
                final int maxLayer = mScreenshotApplicationState.maxLayer;
                final int minLayer = mScreenshotApplicationState.minLayer;
                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
                        (appWin != null ?
                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
            }
        }

        // Create a copy of the screenshot that is immutable and backed in ashmem.
        // This greatly reduces the overhead of passing the bitmap between processes.
        Bitmap ret = bitmap.createAshmemBitmap(config);
        bitmap.recycle();
        return ret;
    }

    GraphicBuffer screenshotApplicationsToBuffer(IBinder appToken, int width, int height,
            boolean includeFullDisplay, float frameScale, boolean wallpaperOnly,
            boolean includeDecor) {
        return screenshotApplications(appToken, width, height, includeFullDisplay, frameScale,
                wallpaperOnly, includeDecor, SurfaceControl::screenshotToBuffer);
    }

    private <E> E screenshotApplications(IBinder appToken, int width, int height,
            boolean includeFullDisplay, float frameScale, boolean wallpaperOnly,
            boolean includeDecor, Screenshoter<E> screenshoter) {
        int dw = mDisplayInfo.logicalWidth;
        int dh = mDisplayInfo.logicalHeight;
        if (dw == 0 || dh == 0) {
@@ -2119,7 +2163,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            return null;
        }

        Bitmap bm = null;
        E bitmap;

        mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
        final Rect frame = new Rect();
@@ -2327,48 +2371,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            SurfaceControl.openTransaction();
            SurfaceControl.closeTransactionSync();

            bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
            bitmap = screenshoter.screenshot(crop, width, height, minLayer, maxLayer,
                    inRotation, rot);
            if (bm == null) {
            if (bitmap == null) {
                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
                        + ") to layer " + maxLayer);
                return null;
            }
        }

        if (DEBUG_SCREENSHOT) {
            // TEST IF IT's ALL BLACK
            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
            boolean allBlack = true;
            final int firstColor = buffer[0];
            for (int i = 0; i < buffer.length; i++) {
                if (buffer[i] != firstColor) {
                    allBlack = false;
                    break;
                }
            }
            if (allBlack) {
                final WindowState appWin = mScreenshotApplicationState.appWin;
                final int maxLayer = mScreenshotApplicationState.maxLayer;
                final int minLayer = mScreenshotApplicationState.minLayer;
                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
                        (appWin != null ?
                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
            }
        }

        // Create a copy of the screenshot that is immutable and backed in ashmem.
        // This greatly reduces the overhead of passing the bitmap between processes.
        if (toAshmem) {
            Bitmap ret = bm.createAshmemBitmap(config);
            bm.recycle();
            return ret;
        } else {
            return bm;
        }
        return bitmap;
    }

    // TODO: Can this use createRotationMatrix()?
@@ -2721,4 +2732,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            return mName;
        }
    }

    /**
     * Interface to screenshot into various types, i.e. {@link Bitmap} and {@link GraphicBuffer}.
     */
    @FunctionalInterface
    private interface Screenshoter<E> {
        E screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
                boolean useIdentityTransform, int rotation);
    }
}
+3 −9
Original line number Diff line number Diff line
@@ -96,17 +96,11 @@ class TaskSnapshotController {
        if (top == null) {
            return null;
        }
        final Bitmap bmp = top.mDisplayContent.screenshotApplications(top.token, -1, -1, false,
                1.0f, ARGB_8888, false, true, false);
        if (bmp == null) {
        final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token,
                -1, -1, false, 1.0f, false, true);
        if (buffer == null) {
            return null;
        }
        // TODO: Already use a GraphicBuffer when snapshotting the content.
        final GraphicBuffer buffer = GraphicBuffer.create(bmp.getWidth(), bmp.getHeight(),
                RGBA_8888, USAGE_HW_TEXTURE | USAGE_SW_WRITE_NEVER | USAGE_SW_READ_NEVER);
        final Canvas c = buffer.lockCanvas();
        c.drawBitmap(bmp, 0, 0, null);
        buffer.unlockCanvasAndPost(c);
        return new TaskSnapshot(buffer, top.getConfiguration().orientation,
                top.findMainWindow().mStableInsets);
    }
+4 −7
Original line number Diff line number Diff line
@@ -3862,8 +3862,7 @@ public class WindowManagerService extends IWindowManager.Stub
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
            return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
                    -1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
                    Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */,
                    true /* toAshmem */);
                    Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }
@@ -3885,7 +3884,7 @@ public class WindowManagerService extends IWindowManager.Stub
            Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY,
                    -1 /* width */, -1 /* height */, true /* includeFullDisplay */,
                    1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */,
                    false /* includeDecor */, true /* toAshmem */);
                    false /* includeDecor */);
            try {
                receiver.send(bm);
            } catch (RemoteException e) {
@@ -3908,12 +3907,10 @@ public class WindowManagerService extends IWindowManager.Stub
     * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
     * @param includeDecor whether to include window decors, like the status or navigation bar
     *                     background of the window
     * @param toAshmem whether to convert the resulting bitmap to ashmem; this should be set to
     *                 true if the Bitmap is sent over binder, and false otherwise
     */
    private Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
            int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config,
            boolean wallpaperOnly, boolean includeDecor, boolean toAshmem) {
            boolean wallpaperOnly, boolean includeDecor) {
        final DisplayContent displayContent;
        synchronized(mWindowMap) {
            displayContent = mRoot.getDisplayContentOrCreate(displayId);
@@ -3924,7 +3921,7 @@ public class WindowManagerService extends IWindowManager.Stub
            }
        }
        return displayContent.screenshotApplications(appToken, width, height,
                includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor, toAshmem);
                includeFullDisplay, frameScale, config, wallpaperOnly, includeDecor);
    }

    /**