Loading core/java/android/window/IWindowOrganizerController.aidl +14 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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); } core/java/android/window/WindowOrganizer.java +24 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +38 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } Loading Loading
core/java/android/window/IWindowOrganizerController.aidl +14 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading Loading @@ -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); }
core/java/android/window/WindowOrganizer.java +24 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +38 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } Loading