diff options
| author | 2020-04-27 18:59:49 +0000 | |
|---|---|---|
| committer | 2020-04-27 18:59:49 +0000 | |
| commit | 5d2781b7729b65f4d3de86dba0c27f5f7d0280a0 (patch) | |
| tree | 27b9a3c608137019efc98f469245ecd9cf9b64ad | |
| parent | 997d9eb8073d25529796ea1d0ce00a20498d211f (diff) | |
| parent | 5ef1e9367110001abf55d54caabaea4eb7f7be43 (diff) | |
Merge "Added takeScreenshot API to WindowOrganizer" into rvc-dev
3 files changed, 76 insertions, 0 deletions
diff --git a/core/java/android/window/IWindowOrganizerController.aidl b/core/java/android/window/IWindowOrganizerController.aidl index 7f4b26dba479..7e9c783c83c6 100644 --- a/core/java/android/window/IWindowOrganizerController.aidl +++ b/core/java/android/window/IWindowOrganizerController.aidl @@ -16,9 +16,12 @@ package android.window; +import android.view.SurfaceControl; + import android.window.IDisplayAreaOrganizerController; import android.window.ITaskOrganizerController; import android.window.IWindowContainerTransactionCallback; +import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; /** @hide */ @@ -47,4 +50,15 @@ interface IWindowOrganizerController { /** @return An interface enabling the management of display area organizers. */ IDisplayAreaOrganizerController getDisplayAreaOrganizerController(); + + /** + * Take a screenshot of the requested Window token and place the content of the screenshot into + * outSurfaceControl. The SurfaceControl will be a child of the token's parent, so it will be + * a sibling of the token's window + * @param token The token for the WindowContainer that should get a screenshot taken. + * @param outSurfaceControl The SurfaceControl where the screenshot will be attached. + * + * @return true if the screenshot was successful, false otherwise. + */ + boolean takeScreenshot(in WindowContainerToken token, out SurfaceControl outSurfaceControl); } diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java index 457827117f86..ff40ddac134e 100644 --- a/core/java/android/window/WindowOrganizer.java +++ b/core/java/android/window/WindowOrganizer.java @@ -17,11 +17,13 @@ package android.window; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.app.ActivityTaskManager; import android.os.RemoteException; import android.util.Singleton; +import android.view.SurfaceControl; /** * Base class for organizing specific types of windows like Tasks and DisplayAreas @@ -63,6 +65,28 @@ public class WindowOrganizer { } } + /** + * Take a screenshot for a specified Window + * @param token The token for the WindowContainer that should get a screenshot taken. + * @return A SurfaceControl where the screenshot will be attached, or null if failed. + * + * @hide + */ + @Nullable + @RequiresPermission(android.Manifest.permission.READ_FRAME_BUFFER) + public static SurfaceControl takeScreenshot(@NonNull WindowContainerToken token) { + try { + SurfaceControl surfaceControl = new SurfaceControl(); + if (getWindowOrganizerController().takeScreenshot(token, surfaceControl)) { + return surfaceControl; + } else { + return null; + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) static IWindowOrganizerController getWindowOrganizerController() { return IWindowOrganizerControllerSingleton.get(); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 1784e2186aa5..c4cb4b5091d8 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; +import static android.Manifest.permission.READ_FRAME_BUFFER; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED; @@ -27,17 +28,20 @@ import static com.android.server.wm.WindowContainer.POSITION_TOP; import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.ArraySet; import android.util.Slog; +import android.view.Surface; import android.view.SurfaceControl; import android.window.IDisplayAreaOrganizerController; import android.window.ITaskOrganizerController; import android.window.IWindowContainerTransactionCallback; import android.window.IWindowOrganizerController; +import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.internal.util.function.pooled.PooledConsumer; @@ -377,6 +381,40 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub mTransactionCallbacksByPendingSyncId.remove(mSyncId); } + @Override + public boolean takeScreenshot(WindowContainerToken token, SurfaceControl outSurfaceControl) { + mService.mAmInternal.enforceCallingPermission(READ_FRAME_BUFFER, "takeScreenshot()"); + final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); + if (wc == null) { + throw new RuntimeException("Invalid token in screenshot transaction"); + } + + final Rect bounds = new Rect(); + wc.getBounds(bounds); + bounds.offsetTo(0, 0); + SurfaceControl.ScreenshotGraphicBuffer buffer = SurfaceControl.captureLayers( + wc.getSurfaceControl(), bounds, 1); + + if (buffer == null || buffer.getGraphicBuffer() == null) { + return false; + } + + SurfaceControl screenshot = mService.mWindowManager.mSurfaceControlFactory.apply(null) + .setName(wc.getName() + " - Organizer Screenshot") + .setBufferSize(bounds.width(), bounds.height()) + .setFormat(PixelFormat.TRANSLUCENT) + .setParent(wc.getParentSurfaceControl()) + .build(); + + Surface surface = new Surface(); + surface.copyFrom(screenshot); + surface.attachAndQueueBufferWithColorSpace(buffer.getGraphicBuffer(), null); + surface.release(); + + outSurfaceControl.copyFrom(screenshot); + return true; + } + private void enforceStackPermission(String func) { mService.mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, func); } |