summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/screencap/screencap.cpp3
-rw-r--r--core/java/android/view/SurfaceControl.java186
-rw-r--r--core/jni/android_view_SurfaceControl.cpp117
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
4 files changed, 71 insertions, 237 deletions
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index b11e84322dde..11029e75d46a 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -198,8 +198,7 @@ int main(int argc, char** argv)
sp<GraphicBuffer> outBuffer;
status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */,
- 0 /* reqHeight */, INT32_MIN, INT32_MAX, /* all layers */ false, captureOrientation,
- &outBuffer);
+ 0 /* reqHeight */, false, captureOrientation, &outBuffer);
if (result != NO_ERROR) {
close(fd);
return 1;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 79eafa80454a..7271a9e4616f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -70,15 +70,8 @@ public class SurfaceControl implements Parcelable {
private static native void nativeDestroy(long nativeObject);
private static native void nativeDisconnect(long nativeObject);
- private static native Bitmap nativeScreenshot(IBinder displayToken,
- Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean allLayers, boolean useIdentityTransform, int rotation);
- private static native GraphicBuffer nativeScreenshotToBuffer(IBinder displayToken,
- Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean allLayers, boolean useIdentityTransform, int rotation);
- private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
- Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean allLayers, boolean useIdentityTransform);
+ private static native GraphicBuffer nativeScreenshot(IBinder displayToken,
+ Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation);
private static native GraphicBuffer nativeCaptureLayers(IBinder layerHandleToken,
Rect sourceCrop, float frameScale);
@@ -1189,52 +1182,39 @@ public class SurfaceControl implements Parcelable {
}
/**
- * Copy the current screen contents into the provided {@link Surface}
- *
- * @param display The display to take the screenshot of.
- * @param consumer The {@link Surface} to take the screenshot into.
- * @param width The desired width of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param height The desired height of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param minLayer The lowest (bottom-most Z order) surface layer to
- * include in the screenshot.
- * @param maxLayer The highest (top-most Z order) surface layer to
- * include in the screenshot.
- * @param useIdentityTransform Replace whatever transformation (rotation,
- * scaling, translation) the surface layers are currently using with the
- * identity transformation while taking the screenshot.
+ * @see SurfaceControl#screenshot(IBinder, Surface, Rect, int, int, boolean, int)
*/
- public static void screenshot(IBinder display, Surface consumer,
- int width, int height, int minLayer, int maxLayer,
- boolean useIdentityTransform) {
- screenshot(display, consumer, new Rect(), width, height, minLayer, maxLayer,
- false, useIdentityTransform);
+ public static void screenshot(IBinder display, Surface consumer) {
+ screenshot(display, consumer, new Rect(), 0, 0, false, 0);
}
/**
* Copy the current screen contents into the provided {@link Surface}
*
- * @param display The display to take the screenshot of.
* @param consumer The {@link Surface} to take the screenshot into.
- * @param width The desired width of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param height The desired height of the returned bitmap; the raw
- * screen will be scaled down to this size.
+ * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)
*/
- public static void screenshot(IBinder display, Surface consumer,
- int width, int height) {
- screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
+ public static void screenshot(IBinder display, Surface consumer, Rect sourceCrop, int width,
+ int height, boolean useIdentityTransform, int rotation) {
+ if (consumer == null) {
+ throw new IllegalArgumentException("consumer must not be null");
+ }
+
+ final GraphicBuffer buffer = screenshotToBuffer(display, sourceCrop, width, height,
+ useIdentityTransform, rotation);
+ try {
+ consumer.attachAndQueueBuffer(buffer);
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Failed to take screenshot - " + e.getMessage());
+ }
}
/**
- * Copy the current screen contents into the provided {@link Surface}
- *
- * @param display The display to take the screenshot of.
- * @param consumer The {@link Surface} to take the screenshot into.
+ * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
*/
- public static void screenshot(IBinder display, Surface consumer) {
- screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false);
+ @UnsupportedAppUsage
+ public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
+ return screenshot(sourceCrop, width, height, false, rotation);
}
/**
@@ -1242,79 +1222,16 @@ public class SurfaceControl implements Parcelable {
* Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
* a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
*
- * CAVEAT: Versions of screenshot that return a {@link Bitmap} can
- * be extremely slow; avoid use unless absolutely necessary; prefer
- * the versions that use a {@link Surface} instead, such as
- * {@link SurfaceControl#screenshot(IBinder, Surface)}.
+ * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use
+ * unless absolutely necessary; prefer the versions that use a {@link Surface} such as
+ * {@link SurfaceControl#screenshot(IBinder, Surface)} or {@link GraphicBuffer} such as
+ * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
*
- * @param sourceCrop The portion of the screen to capture into the Bitmap;
- * caller may pass in 'new Rect()' if no cropping is desired.
- * @param width The desired width of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param height The desired height of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param minLayer The lowest (bottom-most Z order) surface layer to
- * include in the screenshot.
- * @param maxLayer The highest (top-most Z order) surface layer to
- * include in the screenshot.
- * @param useIdentityTransform Replace whatever transformation (rotation,
- * scaling, translation) the surface layers are currently using with the
- * identity transformation while taking the screenshot.
- * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
- * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
- * screenshots in its native portrait orientation by default, so this is
- * useful for returning screenshots that are independent of device
- * orientation.
- * @return Returns a hardware Bitmap containing the screen contents, or null
- * if an error occurs. Make sure to call Bitmap.recycle() as soon as
- * possible, once its content is not needed anymore.
+ * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
*/
@UnsupportedAppUsage
public static Bitmap screenshot(Rect sourceCrop, int width, int height,
- int minLayer, int maxLayer, boolean useIdentityTransform,
- int rotation) {
- // TODO: should take the display as a parameter
- IBinder displayToken = SurfaceControl.getBuiltInDisplay(
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
- return nativeScreenshot(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, false, useIdentityTransform, rotation);
- }
-
- /**
- * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)}
- * but returns a GraphicBuffer.
- */
- public static GraphicBuffer screenshotToBuffer(Rect sourceCrop, int width, int height,
- int minLayer, int maxLayer, boolean useIdentityTransform,
- int rotation) {
- IBinder displayToken = SurfaceControl.getBuiltInDisplay(
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
- return nativeScreenshotToBuffer(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, false, useIdentityTransform, rotation);
- }
-
- /**
- * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)} but
- * includes all Surfaces in the screenshot. This will also update the orientation so it
- * sends the correct coordinates to SF based on the rotation value.
- *
- * @param sourceCrop The portion of the screen to capture into the Bitmap;
- * caller may pass in 'new Rect()' if no cropping is desired.
- * @param width The desired width of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param height The desired height of the returned bitmap; the raw
- * screen will be scaled down to this size.
- * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
- * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
- * screenshots in its native portrait orientation by default, so this is
- * useful for returning screenshots that are independent of device
- * orientation.
- * @return Returns a Bitmap containing the screen contents, or null
- * if an error occurs. Make sure to call Bitmap.recycle() as soon as
- * possible, once its content is not needed anymore.
- */
- @UnsupportedAppUsage
- public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
+ boolean useIdentityTransform, int rotation) {
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
@@ -1323,22 +1240,45 @@ public class SurfaceControl implements Parcelable {
}
SurfaceControl.rotateCropForSF(sourceCrop, rotation);
- return nativeScreenshot(displayToken, sourceCrop, width, height, 0, 0, true,
- false, rotation);
+ final GraphicBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width, height,
+ useIdentityTransform, rotation);
+
+ if (buffer == null) {
+ Log.w(TAG, "Failed to take screenshot");
+ return null;
+ }
+ return Bitmap.createHardwareBitmap(buffer);
}
- @UnsupportedAppUsage
- private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
- int width, int height, int minLayer, int maxLayer, boolean allLayers,
- boolean useIdentityTransform) {
+ /**
+ * Captures all the surfaces in a display and returns a {@link GraphicBuffer} with the content.
+ *
+ * @param display The display to take the screenshot of.
+ * @param sourceCrop The portion of the screen to capture into the Bitmap; caller may
+ * pass in 'new Rect()' if no cropping is desired.
+ * @param width The desired width of the returned bitmap; the raw screen will be
+ * scaled down to this size; caller may pass in 0 if no scaling is
+ * desired.
+ * @param height The desired height of the returned bitmap; the raw screen will
+ * be scaled down to this size; caller may pass in 0 if no scaling
+ * is desired.
+ * @param useIdentityTransform Replace whatever transformation (rotation, scaling, translation)
+ * the surface layers are currently using with the identity
+ * transformation while taking the screenshot.
+ * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
+ * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take
+ * screenshots in its native portrait orientation by default, so
+ * this is useful for returning screenshots that are independent of
+ * device orientation.
+ * @return Returns a GraphicBuffer that contains the captured content.
+ */
+ public static GraphicBuffer screenshotToBuffer(IBinder display, Rect sourceCrop, int width,
+ int height, boolean useIdentityTransform, int rotation) {
if (display == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
- if (consumer == null) {
- throw new IllegalArgumentException("consumer must not be null");
- }
- nativeScreenshot(display, consumer, sourceCrop, width, height,
- minLayer, maxLayer, allLayers, useIdentityTransform);
+
+ return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation);
}
private static void rotateCropForSF(Rect crop, int rot) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 743b9f6e471d..b70177ffab9a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -157,23 +157,17 @@ static Rect rectFromObj(JNIEnv* env, jobject rectObj) {
return Rect(left, top, right, bottom);
}
-static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz,
+static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
- int rotation) {
+ bool useIdentityTransform, int rotation) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken == NULL) {
return NULL;
}
Rect sourceCrop = rectFromObj(env, sourceCropObj);
- if (allLayers) {
- minLayer = INT32_MIN;
- maxLayer = INT32_MAX;
- }
sp<GraphicBuffer> buffer;
- status_t res = ScreenshotClient::capture(displayToken,
- sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform,
- rotation, &buffer);
+ status_t res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
+ useIdentityTransform, rotation, &buffer);
if (res != NO_ERROR) {
return NULL;
}
@@ -187,100 +181,6 @@ static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz,
(jlong)buffer.get());
}
-static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
- jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
- int rotation) {
- sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
- if (displayToken == NULL) {
- return NULL;
- }
-
- Rect sourceCrop = rectFromObj(env, sourceCropObj);
-
- std::unique_ptr<ScreenshotClient> screenshot(new ScreenshotClient());
- status_t res;
- if (allLayers) {
- minLayer = INT32_MIN;
- maxLayer = INT32_MAX;
- }
-
- sp<GraphicBuffer> buffer;
- res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation), &buffer);
- if (res != NO_ERROR) {
- return NULL;
- }
-
- SkColorType colorType;
- SkAlphaType alphaType;
-
- PixelFormat format = buffer->getPixelFormat();
- switch (format) {
- case PIXEL_FORMAT_RGBX_8888: {
- colorType = kRGBA_8888_SkColorType;
- alphaType = kOpaque_SkAlphaType;
- break;
- }
- case PIXEL_FORMAT_RGBA_8888: {
- colorType = kRGBA_8888_SkColorType;
- alphaType = kPremul_SkAlphaType;
- break;
- }
- case PIXEL_FORMAT_RGBA_FP16: {
- colorType = kRGBA_F16_SkColorType;
- alphaType = kPremul_SkAlphaType;
- break;
- }
- case PIXEL_FORMAT_RGB_565: {
- colorType = kRGB_565_SkColorType;
- alphaType = kOpaque_SkAlphaType;
- break;
- }
- default: {
- return NULL;
- }
- }
-
- SkImageInfo info = SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
- colorType, alphaType,
- SkColorSpace::MakeSRGB());
-
- auto bitmap = sk_sp<Bitmap>(new Bitmap(buffer.get(), info));
- return bitmap::createBitmap(env, bitmap.release(),
- android::bitmap::kBitmapCreateFlag_Premultiplied, NULL);
-}
-
-static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
- jobject surfaceObj, jobject sourceCropObj, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
- sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
- if (displayToken == NULL) {
- return;
- }
-
- sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
- if (consumer == NULL) {
- return;
- }
-
- Rect sourceCrop;
- if (sourceCropObj != NULL) {
- sourceCrop = rectFromObj(env, sourceCropObj);
- }
-
- if (allLayers) {
- minLayer = INT32_MIN;
- maxLayer = INT32_MAX;
- }
-
- sp<GraphicBuffer> buffer;
- ScreenshotClient::capture(displayToken, sourceCrop, width, height, minLayer, maxLayer,
- useIdentityTransform, 0, &buffer);
-
- Surface::attachAndQueueBuffer(consumer.get(), buffer);
-}
-
static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
jobject sourceCropObj, jfloat frameScale) {
@@ -919,10 +819,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeDestroy },
{"nativeDisconnect", "(J)V",
(void*)nativeDisconnect },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
- (void*)nativeScreenshotBitmap },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
- (void*)nativeScreenshot },
{"nativeCreateTransaction", "()J",
(void*)nativeCreateTransaction },
{"nativeApplyTransaction", "(JZ)V",
@@ -1013,9 +909,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeDestroyInTransaction },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
(void*)nativeGetHandle },
- {"nativeScreenshotToBuffer",
- "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;",
- (void*)nativeScreenshotToBuffer },
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIZI)Landroid/graphics/GraphicBuffer;",
+ (void*)nativeScreenshot },
{"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
(void*)nativeCaptureLayers },
};
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ac6582634bf8..03a4d8ea0659 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3252,7 +3252,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// TODO(b/68392460): We should screenshot Task controls directly
// but it's difficult at the moment as the Task doesn't have the
// correct size set.
- final Bitmap bitmap = SurfaceControl.screenshot(frame, dw, dh, 0, 1, inRotation, rot);
+ final Bitmap bitmap = SurfaceControl.screenshot(frame, dw, dh, inRotation, rot);
if (bitmap == null) {
Slog.w(TAG_WM, "Failed to take screenshot");
return null;