Merge "Remove rotation and use flag useIdentityTransform for screenshots."
This commit is contained in:
committed by
Android (Google) Code Review
commit
2da90f7972
@@ -39,7 +39,7 @@ interface IUiAutomationConnection {
|
||||
boolean injectInputEvent(in InputEvent event, boolean sync);
|
||||
void syncInputTransactions();
|
||||
boolean setRotation(int rotation);
|
||||
Bitmap takeScreenshot(in Rect crop, int rotation);
|
||||
Bitmap takeScreenshot(in Rect crop);
|
||||
boolean clearWindowContentFrameStats(int windowId);
|
||||
WindowContentFrameStats getWindowContentFrameStats(int windowId);
|
||||
void clearWindowAnimationFrameStats();
|
||||
|
||||
@@ -903,7 +903,7 @@ public final class UiAutomation {
|
||||
try {
|
||||
// Calling out without a lock held.
|
||||
screenShot = mUiAutomationConnection.takeScreenshot(
|
||||
new Rect(0, 0, displaySize.x, displaySize.y), rotation);
|
||||
new Rect(0, 0, displaySize.x, displaySize.y));
|
||||
if (screenShot == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap takeScreenshot(Rect crop, int rotation) {
|
||||
public Bitmap takeScreenshot(Rect crop) {
|
||||
synchronized (mLock) {
|
||||
throwIfCalledByNotTrustedUidLocked();
|
||||
throwIfShutdownLocked();
|
||||
@@ -190,7 +190,15 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
|
||||
try {
|
||||
int width = crop.width();
|
||||
int height = crop.height();
|
||||
return SurfaceControl.screenshot(crop, width, height, rotation);
|
||||
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
|
||||
final SurfaceControl.DisplayCaptureArgs captureArgs =
|
||||
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
|
||||
.setSourceCrop(crop)
|
||||
.setSize(width, height)
|
||||
.build();
|
||||
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
|
||||
SurfaceControl.captureDisplay(captureArgs);
|
||||
return screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import static android.graphics.Matrix.MSKEW_X;
|
||||
import static android.graphics.Matrix.MSKEW_Y;
|
||||
import static android.graphics.Matrix.MTRANS_X;
|
||||
import static android.graphics.Matrix.MTRANS_Y;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
import static android.view.SurfaceControlProto.HASH_CODE;
|
||||
import static android.view.SurfaceControlProto.NAME;
|
||||
|
||||
@@ -590,6 +588,26 @@ public final class SurfaceControl implements Parcelable {
|
||||
public boolean containsSecureLayers() {
|
||||
return mContainsSecureLayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy content of ScreenshotHardwareBuffer into a hardware bitmap and return it.
|
||||
* 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: This can be extremely slow; avoid use unless absolutely necessary; prefer to
|
||||
* directly
|
||||
* use the {@link HardwareBuffer} directly.
|
||||
*
|
||||
* @return Bitmap generated from the {@link HardwareBuffer}
|
||||
*/
|
||||
public Bitmap asBitmap() {
|
||||
if (mHardwareBuffer == null) {
|
||||
Log.w(TAG, "Failed to take screenshot. Null screenshot object");
|
||||
return null;
|
||||
}
|
||||
return Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -597,7 +615,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
* are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
|
||||
* @hide
|
||||
*/
|
||||
public abstract static class CaptureArgs {
|
||||
private abstract static class CaptureArgs {
|
||||
private final int mPixelFormat;
|
||||
private final Rect mSourceCrop = new Rect();
|
||||
private final float mFrameScale;
|
||||
@@ -615,7 +633,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
*
|
||||
* @param <T> A builder that extends {@link Builder}
|
||||
*/
|
||||
public abstract static class Builder<T extends Builder<T>> {
|
||||
abstract static class Builder<T extends Builder<T>> {
|
||||
private int mPixelFormat = PixelFormat.RGBA_8888;
|
||||
private final Rect mSourceCrop = new Rect();
|
||||
private float mFrameScale = 1;
|
||||
@@ -675,7 +693,6 @@ public final class SurfaceControl implements Parcelable {
|
||||
private final int mWidth;
|
||||
private final int mHeight;
|
||||
private final boolean mUseIdentityTransform;
|
||||
private final int mRotation;
|
||||
|
||||
private DisplayCaptureArgs(Builder builder) {
|
||||
super(builder);
|
||||
@@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable {
|
||||
mWidth = builder.mWidth;
|
||||
mHeight = builder.mHeight;
|
||||
mUseIdentityTransform = builder.mUseIdentityTransform;
|
||||
mRotation = builder.mRotation;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -694,7 +710,6 @@ public final class SurfaceControl implements Parcelable {
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private boolean mUseIdentityTransform;
|
||||
private @Surface.Rotation int mRotation = Surface.ROTATION_0;
|
||||
|
||||
/**
|
||||
* Construct a new {@link LayerCaptureArgs} with the set parameters. The builder
|
||||
@@ -736,26 +751,16 @@ public final class SurfaceControl implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace whatever transformation (rotation, scaling, translation) the surface
|
||||
* layers are currently using with the identity transformation while taking the
|
||||
* screenshot.
|
||||
* Replace the rotation transform of the display with the identity transformation while
|
||||
* taking the screenshot. This ensures the screenshot is taken in the ROTATION_0
|
||||
* orientation. Set this value to false if the screenshot should be taken in the
|
||||
* current screen orientation.
|
||||
*/
|
||||
public Builder setUseIdentityTransform(boolean useIdentityTransform) {
|
||||
mUseIdentityTransform = useIdentityTransform;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public Builder setRotation(@Surface.Rotation int rotation) {
|
||||
mRotation = rotation;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
Builder getThis() {
|
||||
return this;
|
||||
@@ -2221,129 +2226,15 @@ public final class SurfaceControl implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
|
||||
* Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with
|
||||
* the content.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
|
||||
return screenshot(sourceCrop, width, height, false, rotation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the current screen contents into a hardware bitmap and return it.
|
||||
* 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 HardwareBuffer} such as
|
||||
* {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
|
||||
*
|
||||
* @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public static Bitmap screenshot(Rect sourceCrop, int width, int height,
|
||||
boolean useIdentityTransform, int rotation) {
|
||||
// TODO: should take the display as a parameter
|
||||
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
|
||||
if (displayToken == null) {
|
||||
Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (rotation == ROTATION_90 || rotation == ROTATION_270) {
|
||||
rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
|
||||
}
|
||||
|
||||
SurfaceControl.rotateCropForSF(sourceCrop, rotation);
|
||||
final ScreenshotHardwareBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width,
|
||||
height, useIdentityTransform, rotation);
|
||||
|
||||
if (buffer == null) {
|
||||
Log.w(TAG, "Failed to take screenshot");
|
||||
return null;
|
||||
}
|
||||
return Bitmap.wrapHardwareBuffer(buffer.getHardwareBuffer(), buffer.getColorSpace());
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures all the surfaces in a display and returns a {@link HardwareBuffer} 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 HardwareBuffer that contains the captured content.
|
||||
* @hide
|
||||
*/
|
||||
public static ScreenshotHardwareBuffer screenshotToBuffer(IBinder display, Rect sourceCrop,
|
||||
int width, int height, boolean useIdentityTransform, int rotation) {
|
||||
if (display == null) {
|
||||
throw new IllegalArgumentException("displayToken must not be null");
|
||||
}
|
||||
|
||||
DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
|
||||
.setSourceCrop(sourceCrop)
|
||||
.setSize(width, height)
|
||||
.setUseIdentityTransform(useIdentityTransform)
|
||||
.setRotation(rotation)
|
||||
.build();
|
||||
|
||||
public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) {
|
||||
return nativeCaptureDisplay(captureArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like screenshotToBuffer, but if the caller is AID_SYSTEM, allows
|
||||
* for the capture of secure layers. This is used for the screen rotation
|
||||
* animation where the system server takes screenshots but does
|
||||
* not persist them or allow them to leave the server. However in other
|
||||
* cases in the system server, we mostly want to omit secure layers
|
||||
* like when we take a screenshot on behalf of the assistant.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static ScreenshotHardwareBuffer screenshotToBufferWithSecureLayersUnsafe(IBinder display,
|
||||
Rect sourceCrop, int width, int height, boolean useIdentityTransform,
|
||||
int rotation) {
|
||||
if (display == null) {
|
||||
throw new IllegalArgumentException("displayToken must not be null");
|
||||
}
|
||||
|
||||
DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
|
||||
.setSourceCrop(sourceCrop)
|
||||
.setSize(width, height)
|
||||
.setUseIdentityTransform(useIdentityTransform)
|
||||
.setRotation(rotation)
|
||||
.setCaptureSecureLayers(true)
|
||||
.build();
|
||||
|
||||
return nativeCaptureDisplay(captureArgs);
|
||||
}
|
||||
|
||||
private static void rotateCropForSF(Rect crop, int rot) {
|
||||
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
|
||||
int tmp = crop.top;
|
||||
crop.top = crop.left;
|
||||
crop.left = tmp;
|
||||
tmp = crop.right;
|
||||
crop.right = crop.bottom;
|
||||
crop.bottom = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
|
||||
*
|
||||
|
||||
@@ -116,7 +116,6 @@ static struct {
|
||||
jfieldID width;
|
||||
jfieldID height;
|
||||
jfieldID useIdentityTransform;
|
||||
jfieldID rotation;
|
||||
} gDisplayCaptureArgsClassInfo;
|
||||
|
||||
static struct {
|
||||
@@ -325,8 +324,6 @@ static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
|
||||
captureArgs.useIdentityTransform =
|
||||
env->GetBooleanField(displayCaptureArgsObject,
|
||||
gDisplayCaptureArgsClassInfo.useIdentityTransform);
|
||||
captureArgs.rotation = ui::toRotation(
|
||||
env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation));
|
||||
return captureArgs;
|
||||
}
|
||||
|
||||
@@ -1849,8 +1846,6 @@ int register_android_view_SurfaceControl(JNIEnv* env)
|
||||
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I");
|
||||
gDisplayCaptureArgsClassInfo.useIdentityTransform =
|
||||
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z");
|
||||
gDisplayCaptureArgsClassInfo.rotation =
|
||||
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I");
|
||||
|
||||
jclass layerCaptureArgsClazz =
|
||||
FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs");
|
||||
|
||||
@@ -17,11 +17,8 @@
|
||||
package com.android.shell;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.DisplayManagerGlobal;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
/**
|
||||
@@ -40,22 +37,17 @@ final class Screenshooter {
|
||||
* @return The screenshot bitmap on success, null otherwise.
|
||||
*/
|
||||
static Bitmap takeScreenshot() {
|
||||
Display display = DisplayManagerGlobal.getInstance()
|
||||
.getRealDisplay(Display.DEFAULT_DISPLAY);
|
||||
Point displaySize = new Point();
|
||||
display.getRealSize(displaySize);
|
||||
final int displayWidth = displaySize.x;
|
||||
final int displayHeight = displaySize.y;
|
||||
|
||||
int rotation = display.getRotation();
|
||||
Rect crop = new Rect(0, 0, displayWidth, displayHeight);
|
||||
Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight);
|
||||
Log.d(TAG, "Taking fullscreen screenshot");
|
||||
// Take the screenshot
|
||||
Bitmap screenShot =
|
||||
SurfaceControl.screenshot(crop, displayWidth, displayHeight, rotation);
|
||||
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
|
||||
final SurfaceControl.DisplayCaptureArgs captureArgs =
|
||||
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
|
||||
.build();
|
||||
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
|
||||
SurfaceControl.captureDisplay(captureArgs);
|
||||
final Bitmap screenShot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
|
||||
if (screenShot == null) {
|
||||
Log.e(TAG, "Failed to take screenshot of dimensions " + displayWidth + " x "
|
||||
+ displayHeight);
|
||||
Log.e(TAG, "Failed to take fullscreen screenshot");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.graphics.drawable.LayerDrawable;
|
||||
import android.media.MediaActionSound;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
@@ -556,11 +557,18 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
|
||||
private void takeScreenshotInternal(Consumer<Uri> finisher, Rect crop) {
|
||||
// copy the input Rect, since SurfaceControl.screenshot can mutate it
|
||||
Rect screenRect = new Rect(crop);
|
||||
int rot = mDisplay.getRotation();
|
||||
int width = crop.width();
|
||||
int height = crop.height();
|
||||
saveScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect,
|
||||
Insets.NONE, true);
|
||||
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
|
||||
final SurfaceControl.DisplayCaptureArgs captureArgs =
|
||||
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
|
||||
.setSourceCrop(crop)
|
||||
.setSize(width, height)
|
||||
.build();
|
||||
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
|
||||
SurfaceControl.captureDisplay(captureArgs);
|
||||
final Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
|
||||
saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true);
|
||||
}
|
||||
|
||||
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
|
||||
|
||||
@@ -30,8 +30,6 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUST
|
||||
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
|
||||
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
|
||||
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
@@ -46,7 +44,6 @@ import android.content.res.TypedArray;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.ColorSpace;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.display.AmbientBrightnessDayStats;
|
||||
import android.hardware.display.BrightnessChangeEvent;
|
||||
@@ -104,7 +101,6 @@ import com.android.server.AnimationThread;
|
||||
import com.android.server.DisplayThread;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.SystemService.TargetUser;
|
||||
import com.android.server.UiThread;
|
||||
import com.android.server.wm.SurfaceAnimationThread;
|
||||
import com.android.server.wm.WindowManagerInternal;
|
||||
@@ -1394,9 +1390,13 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
|
||||
return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(),
|
||||
displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
|
||||
false /* useIdentityTransform */, 0 /* rotation */);
|
||||
final SurfaceControl.DisplayCaptureArgs captureArgs =
|
||||
new SurfaceControl.DisplayCaptureArgs.Builder(token)
|
||||
.setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
|
||||
.setUseIdentityTransform(true)
|
||||
.setCaptureSecureLayers(true)
|
||||
.build();
|
||||
return SurfaceControl.captureDisplay(captureArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1406,30 +1406,11 @@ public final class DisplayManagerService extends SystemService {
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
final LogicalDisplay logicalDisplay = mLogicalDisplays.get(displayId);
|
||||
if (logicalDisplay == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
|
||||
// Takes screenshot based on current device orientation.
|
||||
final Display display = DisplayManagerGlobal.getInstance()
|
||||
.getRealDisplay(displayId);
|
||||
if (display == null) {
|
||||
return null;
|
||||
}
|
||||
final Point displaySize = new Point();
|
||||
display.getRealSize(displaySize);
|
||||
|
||||
int rotation = displayInfo.rotation;
|
||||
// TODO (b/153382624) : This workaround solution would be removed after
|
||||
// SurfaceFlinger fixes the inconsistency with rotation direction issue.
|
||||
if (rotation == ROTATION_90 || rotation == ROTATION_270) {
|
||||
rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
|
||||
}
|
||||
|
||||
return SurfaceControl.screenshotToBuffer(token, new Rect(), displaySize.x,
|
||||
displaySize.y, false /* useIdentityTransform */, rotation /* rotation */);
|
||||
final SurfaceControl.DisplayCaptureArgs captureArgs =
|
||||
new SurfaceControl.DisplayCaptureArgs.Builder(token)
|
||||
.build();
|
||||
return SurfaceControl.captureDisplay(captureArgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4063,9 +4063,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
|
||||
|
||||
// Send invalid rect and no width and height since it will screenshot the entire display.
|
||||
Rect frame = new Rect(0, 0, -1, -1);
|
||||
final Bitmap bitmap = SurfaceControl.screenshot(frame, 0, 0, inRotation,
|
||||
mDisplay.getRotation());
|
||||
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
|
||||
final SurfaceControl.DisplayCaptureArgs captureArgs =
|
||||
new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
|
||||
.setUseIdentityTransform(inRotation)
|
||||
.build();
|
||||
final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
|
||||
SurfaceControl.captureDisplay(captureArgs);
|
||||
final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
|
||||
if (bitmap == null) {
|
||||
Slog.w(TAG_WM, "Failed to take screenshot");
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user