summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chavi Weingarten <chaviw@google.com> 2020-04-27 18:59:49 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-04-27 18:59:49 +0000
commit5d2781b7729b65f4d3de86dba0c27f5f7d0280a0 (patch)
tree27b9a3c608137019efc98f469245ecd9cf9b64ad
parent997d9eb8073d25529796ea1d0ce00a20498d211f (diff)
parent5ef1e9367110001abf55d54caabaea4eb7f7be43 (diff)
Merge "Added takeScreenshot API to WindowOrganizer" into rvc-dev
-rw-r--r--core/java/android/window/IWindowOrganizerController.aidl14
-rw-r--r--core/java/android/window/WindowOrganizer.java24
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java38
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);
}