Loading core/java/android/app/IUiAutomationConnection.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading core/java/android/app/UiAutomation.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading core/java/android/app/UiAutomationConnection.java +10 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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); } Loading core/java/android/view/SurfaceControl.java +29 −138 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } /** Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable { mWidth = builder.mWidth; mHeight = builder.mHeight; mUseIdentityTransform = builder.mUseIdentityTransform; mRotation = builder.mRotation; } /** Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -2221,129 +2226,15 @@ public final class SurfaceControl implements Parcelable { } /** * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)} * @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(); 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. * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with * the content. * * @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(); public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) { 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. * Loading core/jni/android_view_SurfaceControl.cpp +0 −5 Original line number Diff line number Diff line Loading @@ -116,7 +116,6 @@ static struct { jfieldID width; jfieldID height; jfieldID useIdentityTransform; jfieldID rotation; } gDisplayCaptureArgsClassInfo; static struct { Loading Loading @@ -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; } Loading Loading @@ -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"); Loading Loading
core/java/android/app/IUiAutomationConnection.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading
core/java/android/app/UiAutomation.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading
core/java/android/app/UiAutomationConnection.java +10 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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); } Loading
core/java/android/view/SurfaceControl.java +29 −138 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } /** Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable { mWidth = builder.mWidth; mHeight = builder.mHeight; mUseIdentityTransform = builder.mUseIdentityTransform; mRotation = builder.mRotation; } /** Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -2221,129 +2226,15 @@ public final class SurfaceControl implements Parcelable { } /** * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)} * @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(); 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. * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with * the content. * * @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(); public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) { 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. * Loading
core/jni/android_view_SurfaceControl.cpp +0 −5 Original line number Diff line number Diff line Loading @@ -116,7 +116,6 @@ static struct { jfieldID width; jfieldID height; jfieldID useIdentityTransform; jfieldID rotation; } gDisplayCaptureArgsClassInfo; static struct { Loading Loading @@ -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; } Loading Loading @@ -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"); Loading