Merge "Remove minLayer and maxLayer from display screenshot."
This commit is contained in:
committed by
Android (Google) Code Review
commit
3623c39cd3
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static void screenshot(IBinder display, Surface consumer,
|
||||
int width, int height) {
|
||||
screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(IBinder, Surface, Rect, int, int, boolean, int)
|
||||
*/
|
||||
public static void screenshot(IBinder display, Surface consumer) {
|
||||
screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false);
|
||||
screenshot(display, consumer, new Rect(), 0, 0, false, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the current screen contents into the provided {@link Surface}
|
||||
*
|
||||
* @param consumer The {@link Surface} to take the screenshot into.
|
||||
* @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)
|
||||
*/
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
|
||||
*/
|
||||
@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) {
|
||||
|
||||
@@ -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 },
|
||||
};
|
||||
|
||||
@@ -3251,7 +3251,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;
|
||||
|
||||
Reference in New Issue
Block a user