Merge "Fix screenshot buffer leaks" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3a4bf0e510
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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());
|
||||
.setChildrenOnly(false)
|
||||
.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
|
||||
|
||||
Reference in New Issue
Block a user