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

Commit 3a4bf0e5 authored by Jeimy Santiago Morales's avatar Jeimy Santiago Morales Committed by Android (Google) Code Review
Browse files

Merge "Fix screenshot buffer leaks" into udc-qpr-dev

parents ed7bbe1f 4ddd5438
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.view.SurfaceControl;
import android.view.WindowContentFrameStats;
import android.view.WindowAnimationFrameStats;
import android.os.ParcelFileDescriptor;
import android.window.ScreenCapture.ScreenCaptureListener;
import android.window.ScreenCapture.LayerCaptureArgs;

import java.util.List;

@@ -43,8 +45,8 @@ interface IUiAutomationConnection {
    void injectInputEventToInputFilter(in InputEvent event);
    void syncInputTransactions(boolean waitForAnimations);
    boolean setRotation(int rotation);
    Bitmap takeScreenshot(in Rect crop);
    Bitmap takeSurfaceControlScreenshot(in SurfaceControl surfaceControl);
    boolean takeScreenshot(in Rect crop, in ScreenCaptureListener listener);
    boolean takeSurfaceControlScreenshot(in SurfaceControl surfaceControl, in ScreenCaptureListener listener);
    boolean clearWindowContentFrameStats(int windowId);
    WindowContentFrameStats getWindowContentFrameStats(int windowId);
    void clearWindowAnimationFrameStats();
+39 −13
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.HardwareBuffer;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
import android.os.Handler;
@@ -71,6 +72,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.inputmethod.EditorInfo;
import android.window.ScreenCapture;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -1160,17 +1163,12 @@ public final class UiAutomation {
        Point displaySize = new Point();
        display.getRealSize(displaySize);

        int rotation = display.getRotation();

        // Take the screenshot
        Bitmap screenShot = null;
        ScreenCapture.SynchronousScreenCaptureListener syncScreenCapture =
                ScreenCapture.createSyncCaptureListener();
        try {
            // Calling out without a lock held.
            screenShot = mUiAutomationConnection.takeScreenshot(
                    new Rect(0, 0, displaySize.x, displaySize.y));
            if (screenShot == null) {
                Log.e(LOG_TAG, "mUiAutomationConnection.takeScreenshot() returned null for display "
                        + mDisplayId);
            if (!mUiAutomationConnection.takeScreenshot(
                    new Rect(0, 0, displaySize.x, displaySize.y), syncScreenCapture)) {
                return null;
            }
        } catch (RemoteException re) {
@@ -1178,10 +1176,23 @@ public final class UiAutomation {
            return null;
        }

        // Optimization
        screenShot.setHasAlpha(false);
        final ScreenshotHardwareBuffer screenshotBuffer =
                syncScreenCapture.getBuffer();
        Bitmap screenShot = screenshotBuffer.asBitmap();
        if (screenShot == null) {
            Log.e(LOG_TAG, "mUiAutomationConnection.takeScreenshot() returned null for display "
                    + mDisplayId);
            return null;
        }
        Bitmap swBitmap;
        try (HardwareBuffer buffer = screenshotBuffer.getHardwareBuffer()) {
            swBitmap = screenShot.copy(Bitmap.Config.ARGB_8888, false);
        }
        screenShot.recycle();

        return screenShot;
        // Optimization
        swBitmap.setHasAlpha(false);
        return swBitmap;
    }

    /**
@@ -1218,12 +1229,27 @@ public final class UiAutomation {
        // Apply a sync transaction to ensure SurfaceFlinger is flushed before capturing a
        // screenshot.
        new SurfaceControl.Transaction().apply(true);
        ScreenCapture.SynchronousScreenCaptureListener syncScreenCapture =
                ScreenCapture.createSyncCaptureListener();
        try {
            return mUiAutomationConnection.takeSurfaceControlScreenshot(sc);
            if (!mUiAutomationConnection.takeSurfaceControlScreenshot(sc, syncScreenCapture)) {
                return null;
            }

        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while taking screenshot!", re);
            return null;
        }
        ScreenCapture.ScreenshotHardwareBuffer captureBuffer =
                syncScreenCapture.getBuffer();
        Bitmap screenShot = captureBuffer.asBitmap();
        Bitmap swBitmap;
        try (HardwareBuffer buffer = captureBuffer.getHardwareBuffer()) {
            swBitmap = screenShot.copy(Bitmap.Config.ARGB_8888, false);
        }

        screenShot.recycle();
        return swBitmap;
    }

    /**
+16 −21
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerGlobal;
@@ -51,8 +50,6 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
import android.window.ScreenCapture;
import android.window.ScreenCapture.CaptureArgs;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;
import android.window.ScreenCapture.SynchronousScreenCaptureListener;

import libcore.io.IoUtils;

@@ -224,56 +221,54 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
    }

    @Override
    public Bitmap takeScreenshot(Rect crop) {
    public boolean takeScreenshot(Rect crop, ScreenCapture.ScreenCaptureListener listener) {
        synchronized (mLock) {
            throwIfCalledByNotTrustedUidLocked();
            throwIfShutdownLocked();
            throwIfNotConnectedLocked();
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            final CaptureArgs captureArgs = new CaptureArgs.Builder<>()
                    .setSourceCrop(crop)
                    .build();
            SynchronousScreenCaptureListener syncScreenCapture =
                    ScreenCapture.createSyncCaptureListener();
            mWindowManager.captureDisplay(DEFAULT_DISPLAY, captureArgs,
                    syncScreenCapture);
            final ScreenshotHardwareBuffer screenshotBuffer =
                    syncScreenCapture.getBuffer();
            return screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
            mWindowManager.captureDisplay(DEFAULT_DISPLAY, captureArgs, listener);
        } catch (RemoteException re) {
            re.rethrowAsRuntimeException();
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
        return null;

        return true;
    }

    @Nullable
    @Override
    public Bitmap takeSurfaceControlScreenshot(@NonNull SurfaceControl surfaceControl) {
    public boolean takeSurfaceControlScreenshot(@NonNull SurfaceControl surfaceControl,
            ScreenCapture.ScreenCaptureListener listener) {
        synchronized (mLock) {
            throwIfCalledByNotTrustedUidLocked();
            throwIfShutdownLocked();
            throwIfNotConnectedLocked();
        }

        ScreenCapture.ScreenshotHardwareBuffer captureBuffer;
        final long identity = Binder.clearCallingIdentity();
        try {
            captureBuffer = ScreenCapture.captureLayers(
            ScreenCapture.LayerCaptureArgs args =
                    new ScreenCapture.LayerCaptureArgs.Builder(surfaceControl)
                    .setChildrenOnly(false)
                            .build());
                    .build();
            int status = ScreenCapture.captureLayers(args, listener);

            if (status != 0) {
                return false;
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }

        if (captureBuffer == null) {
            return null;
        }
        return captureBuffer.asBitmap();
        return true;
    }

    @Override