diff options
| -rw-r--r-- | core/java/android/app/IUiAutomationConnection.aidl | 6 | ||||
| -rw-r--r-- | core/java/android/app/UiAutomation.java | 52 | ||||
| -rw-r--r-- | core/java/android/app/UiAutomationConnection.java | 37 |
3 files changed, 59 insertions, 36 deletions
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index fbb0748fc01f..63cae63e1e50 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl @@ -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(); diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 247d5bc77ffb..c3d26d49c93a 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -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; } /** diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 34f0964cf823..52949d6d1fbd 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -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 |