Loading core/java/android/window/ScreenCapture.java +29 −6 Original line number Diff line number Diff line Loading @@ -198,17 +198,21 @@ public class ScreenCapture { * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object. * * @param hardwareBuffer The existing HardwareBuffer object * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named} * @param dataspace Dataspace describing the content. * {@see android.hardware.DataSpace} * @param containsSecureLayers Indicates whether this graphic buffer contains captured * contents of secure layers, in which case the screenshot * should not be persisted. * @param containsHdrLayers Indicates whether this graphic buffer contains HDR content. */ private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer, int namedColorSpace, boolean containsSecureLayers, boolean containsHdrLayers) { ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.values()[namedColorSpace]); int dataspace, boolean containsSecureLayers, boolean containsHdrLayers) { ColorSpace colorSpace = ColorSpace.getFromDataSpace(dataspace); return new ScreenshotHardwareBuffer( hardwareBuffer, colorSpace, containsSecureLayers, containsHdrLayers); hardwareBuffer, colorSpace != null ? colorSpace : ColorSpace.get(ColorSpace.Named.SRGB), containsSecureLayers, containsHdrLayers); } public ColorSpace getColorSpace() { Loading Loading @@ -271,8 +275,8 @@ public class ScreenCapture { public final boolean mAllowProtected; public final long mUid; public final boolean mGrayscale; final SurfaceControl[] mExcludeLayers; public final boolean mHintForSeamlessTransition; private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) { mPixelFormat = builder.mPixelFormat; Loading @@ -284,6 +288,7 @@ public class ScreenCapture { mUid = builder.mUid; mGrayscale = builder.mGrayscale; mExcludeLayers = builder.mExcludeLayers; mHintForSeamlessTransition = builder.mHintForSeamlessTransition; } private CaptureArgs(Parcel in) { Loading @@ -305,6 +310,7 @@ public class ScreenCapture { } else { mExcludeLayers = null; } mHintForSeamlessTransition = in.readBoolean(); } /** Release any layers if set using {@link Builder#setExcludeLayers(SurfaceControl[])}. */ Loading Loading @@ -352,6 +358,7 @@ public class ScreenCapture { private long mUid = -1; private boolean mGrayscale; private SurfaceControl[] mExcludeLayers; private boolean mHintForSeamlessTransition; /** * Construct a new {@link CaptureArgs} with the set parameters. The builder remains Loading Loading @@ -448,6 +455,21 @@ public class ScreenCapture { return getThis(); } /** * Set whether the screenshot will be used in a system animation. * This hint is used for picking the "best" colorspace for the screenshot, in particular * for mixing HDR and SDR content. * E.g., hintForSeamlessTransition is false, then a colorspace suitable for file * encoding, such as BT2100, may be chosen. Otherwise, then the display's color space * would be chosen, with the possibility of having an extended brightness range. This * is important for screenshots that are directly re-routed to a SurfaceControl in * order to preserve accurate colors. */ public T setHintForSeamlessTransition(boolean hintForSeamlessTransition) { mHintForSeamlessTransition = hintForSeamlessTransition; return getThis(); } /** * Each sub class should return itself to allow the builder to chain properly */ Loading @@ -471,7 +493,6 @@ public class ScreenCapture { dest.writeBoolean(mAllowProtected); dest.writeLong(mUid); dest.writeBoolean(mGrayscale); if (mExcludeLayers != null) { dest.writeInt(mExcludeLayers.length); for (SurfaceControl excludeLayer : mExcludeLayers) { Loading @@ -480,6 +501,7 @@ public class ScreenCapture { } else { dest.writeInt(0); } dest.writeBoolean(mHintForSeamlessTransition); } public static final Parcelable.Creator<CaptureArgs> CREATOR = Loading Loading @@ -627,6 +649,7 @@ public class ScreenCapture { setUid(args.mUid); setGrayscale(args.mGrayscale); setExcludeLayers(args.mExcludeLayers); setHintForSeamlessTransition(args.mHintForSeamlessTransition); } public Builder(SurfaceControl layer) { Loading core/jni/android_window_ScreenCapture.cpp +8 −21 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ static struct { jfieldID uid; jfieldID grayscale; jmethodID getNativeExcludeLayers; jfieldID hintForSeamlessTransition; } gCaptureArgsClassInfo; static struct { Loading @@ -69,23 +70,6 @@ static struct { jmethodID builder; } gScreenshotHardwareBufferClassInfo; enum JNamedColorSpace : jint { // ColorSpace.Named.SRGB.ordinal() = 0; SRGB = 0, // ColorSpace.Named.DISPLAY_P3.ordinal() = 7; DISPLAY_P3 = 7, }; constexpr jint fromDataspaceToNamedColorSpaceValue(const ui::Dataspace dataspace) { switch (dataspace) { case ui::Dataspace::DISPLAY_P3: return JNamedColorSpace::DISPLAY_P3; default: return JNamedColorSpace::SRGB; } } static void checkAndClearException(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { ALOGE("An exception was thrown by callback '%s'.", methodName); Loading Loading @@ -119,12 +103,11 @@ public: captureResults.fenceResult.value()->waitForever(LOG_TAG); jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( env, captureResults.buffer->toAHardwareBuffer()); const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); jobject screenshotHardwareBuffer = env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, namedColorSpace, jhardwareBuffer, static_cast<jint>(captureResults.capturedDataspace), captureResults.capturedSecureLayers, captureResults.capturedHdrLayers); checkAndClearException(env, "builder"); Loading Loading @@ -185,6 +168,9 @@ static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs.excludeHandles.emplace(excludeObject->getHandle()); } } captureArgs.hintForSeamlessTransition = env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.hintForSeamlessTransition); } static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, Loading Loading @@ -318,9 +304,10 @@ int register_android_window_ScreenCapture(JNIEnv* env) { GetFieldIDOrDie(env, captureArgsClazz, "mAllowProtected", "Z"); gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J"); gCaptureArgsClassInfo.grayscale = GetFieldIDOrDie(env, captureArgsClazz, "mGrayscale", "Z"); gCaptureArgsClassInfo.getNativeExcludeLayers = GetMethodIDOrDie(env, captureArgsClazz, "getNativeExcludeLayers", "()[J"); gCaptureArgsClassInfo.hintForSeamlessTransition = GetFieldIDOrDie(env, captureArgsClazz, "mHintForSeamlessTransition", "Z"); jclass displayCaptureArgsClazz = FindClassOrDie(env, "android/window/ScreenCapture$DisplayCaptureArgs"); Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +1 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ class ScreenRotationAnimation { .setCaptureSecureLayers(true) .setAllowProtected(true) .setSourceCrop(new Rect(0, 0, mStartWidth, mStartHeight)) .setHintForSeamlessTransition(true) .build(); ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer = ScreenCapture.captureLayers(args); Loading services/core/java/com/android/server/wm/ScreenRotationAnimation.java +2 −0 Original line number Diff line number Diff line Loading @@ -193,6 +193,7 @@ class ScreenRotationAnimation { .setSourceCrop(new Rect(0, 0, width, height)) .setAllowProtected(true) .setCaptureSecureLayers(true) .setHintForSeamlessTransition(true) .build(); screenshotBuffer = ScreenCapture.captureDisplay(captureArgs); } else { Loading @@ -202,6 +203,7 @@ class ScreenRotationAnimation { .setCaptureSecureLayers(true) .setAllowProtected(true) .setSourceCrop(new Rect(0, 0, width, height)) .setHintForSeamlessTransition(true) .build(); screenshotBuffer = ScreenCapture.captureLayers(captureArgs); } Loading services/core/java/com/android/server/wm/Transition.java +3 −2 Original line number Diff line number Diff line Loading @@ -2999,11 +2999,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { Rect cropBounds = new Rect(bounds); cropBounds.offsetTo(0, 0); final boolean isDisplayRotation = wc.asDisplayContent() != null && wc.asDisplayContent().isRotationChanging(); ScreenCapture.LayerCaptureArgs captureArgs = new ScreenCapture.LayerCaptureArgs.Builder(wc.getSurfaceControl()) .setSourceCrop(cropBounds) .setCaptureSecureLayers(true) .setAllowProtected(true) .setHintForSeamlessTransition(isDisplayRotation) .build(); ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer = ScreenCapture.captureLayers(captureArgs); Loading @@ -3014,8 +3017,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { Slog.w(TAG, "Failed to capture screenshot for " + wc); return false; } final boolean isDisplayRotation = wc.asDisplayContent() != null && wc.asDisplayContent().isRotationChanging(); // Some tests may check the name "RotationLayer" to detect display rotation. final String name = isDisplayRotation ? "RotationLayer" : "transition snapshot: " + wc; SurfaceControl snapshotSurface = wc.makeAnimationLeash() Loading Loading
core/java/android/window/ScreenCapture.java +29 −6 Original line number Diff line number Diff line Loading @@ -198,17 +198,21 @@ public class ScreenCapture { * Create ScreenshotHardwareBuffer from an existing HardwareBuffer object. * * @param hardwareBuffer The existing HardwareBuffer object * @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named} * @param dataspace Dataspace describing the content. * {@see android.hardware.DataSpace} * @param containsSecureLayers Indicates whether this graphic buffer contains captured * contents of secure layers, in which case the screenshot * should not be persisted. * @param containsHdrLayers Indicates whether this graphic buffer contains HDR content. */ private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer, int namedColorSpace, boolean containsSecureLayers, boolean containsHdrLayers) { ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.values()[namedColorSpace]); int dataspace, boolean containsSecureLayers, boolean containsHdrLayers) { ColorSpace colorSpace = ColorSpace.getFromDataSpace(dataspace); return new ScreenshotHardwareBuffer( hardwareBuffer, colorSpace, containsSecureLayers, containsHdrLayers); hardwareBuffer, colorSpace != null ? colorSpace : ColorSpace.get(ColorSpace.Named.SRGB), containsSecureLayers, containsHdrLayers); } public ColorSpace getColorSpace() { Loading Loading @@ -271,8 +275,8 @@ public class ScreenCapture { public final boolean mAllowProtected; public final long mUid; public final boolean mGrayscale; final SurfaceControl[] mExcludeLayers; public final boolean mHintForSeamlessTransition; private CaptureArgs(CaptureArgs.Builder<? extends CaptureArgs.Builder<?>> builder) { mPixelFormat = builder.mPixelFormat; Loading @@ -284,6 +288,7 @@ public class ScreenCapture { mUid = builder.mUid; mGrayscale = builder.mGrayscale; mExcludeLayers = builder.mExcludeLayers; mHintForSeamlessTransition = builder.mHintForSeamlessTransition; } private CaptureArgs(Parcel in) { Loading @@ -305,6 +310,7 @@ public class ScreenCapture { } else { mExcludeLayers = null; } mHintForSeamlessTransition = in.readBoolean(); } /** Release any layers if set using {@link Builder#setExcludeLayers(SurfaceControl[])}. */ Loading Loading @@ -352,6 +358,7 @@ public class ScreenCapture { private long mUid = -1; private boolean mGrayscale; private SurfaceControl[] mExcludeLayers; private boolean mHintForSeamlessTransition; /** * Construct a new {@link CaptureArgs} with the set parameters. The builder remains Loading Loading @@ -448,6 +455,21 @@ public class ScreenCapture { return getThis(); } /** * Set whether the screenshot will be used in a system animation. * This hint is used for picking the "best" colorspace for the screenshot, in particular * for mixing HDR and SDR content. * E.g., hintForSeamlessTransition is false, then a colorspace suitable for file * encoding, such as BT2100, may be chosen. Otherwise, then the display's color space * would be chosen, with the possibility of having an extended brightness range. This * is important for screenshots that are directly re-routed to a SurfaceControl in * order to preserve accurate colors. */ public T setHintForSeamlessTransition(boolean hintForSeamlessTransition) { mHintForSeamlessTransition = hintForSeamlessTransition; return getThis(); } /** * Each sub class should return itself to allow the builder to chain properly */ Loading @@ -471,7 +493,6 @@ public class ScreenCapture { dest.writeBoolean(mAllowProtected); dest.writeLong(mUid); dest.writeBoolean(mGrayscale); if (mExcludeLayers != null) { dest.writeInt(mExcludeLayers.length); for (SurfaceControl excludeLayer : mExcludeLayers) { Loading @@ -480,6 +501,7 @@ public class ScreenCapture { } else { dest.writeInt(0); } dest.writeBoolean(mHintForSeamlessTransition); } public static final Parcelable.Creator<CaptureArgs> CREATOR = Loading Loading @@ -627,6 +649,7 @@ public class ScreenCapture { setUid(args.mUid); setGrayscale(args.mGrayscale); setExcludeLayers(args.mExcludeLayers); setHintForSeamlessTransition(args.mHintForSeamlessTransition); } public Builder(SurfaceControl layer) { Loading
core/jni/android_window_ScreenCapture.cpp +8 −21 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ static struct { jfieldID uid; jfieldID grayscale; jmethodID getNativeExcludeLayers; jfieldID hintForSeamlessTransition; } gCaptureArgsClassInfo; static struct { Loading @@ -69,23 +70,6 @@ static struct { jmethodID builder; } gScreenshotHardwareBufferClassInfo; enum JNamedColorSpace : jint { // ColorSpace.Named.SRGB.ordinal() = 0; SRGB = 0, // ColorSpace.Named.DISPLAY_P3.ordinal() = 7; DISPLAY_P3 = 7, }; constexpr jint fromDataspaceToNamedColorSpaceValue(const ui::Dataspace dataspace) { switch (dataspace) { case ui::Dataspace::DISPLAY_P3: return JNamedColorSpace::DISPLAY_P3; default: return JNamedColorSpace::SRGB; } } static void checkAndClearException(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { ALOGE("An exception was thrown by callback '%s'.", methodName); Loading Loading @@ -119,12 +103,11 @@ public: captureResults.fenceResult.value()->waitForever(LOG_TAG); jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( env, captureResults.buffer->toAHardwareBuffer()); const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); jobject screenshotHardwareBuffer = env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, namedColorSpace, jhardwareBuffer, static_cast<jint>(captureResults.capturedDataspace), captureResults.capturedSecureLayers, captureResults.capturedHdrLayers); checkAndClearException(env, "builder"); Loading Loading @@ -185,6 +168,9 @@ static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs.excludeHandles.emplace(excludeObject->getHandle()); } } captureArgs.hintForSeamlessTransition = env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.hintForSeamlessTransition); } static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, Loading Loading @@ -318,9 +304,10 @@ int register_android_window_ScreenCapture(JNIEnv* env) { GetFieldIDOrDie(env, captureArgsClazz, "mAllowProtected", "Z"); gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J"); gCaptureArgsClassInfo.grayscale = GetFieldIDOrDie(env, captureArgsClazz, "mGrayscale", "Z"); gCaptureArgsClassInfo.getNativeExcludeLayers = GetMethodIDOrDie(env, captureArgsClazz, "getNativeExcludeLayers", "()[J"); gCaptureArgsClassInfo.hintForSeamlessTransition = GetFieldIDOrDie(env, captureArgsClazz, "mHintForSeamlessTransition", "Z"); jclass displayCaptureArgsClazz = FindClassOrDie(env, "android/window/ScreenCapture$DisplayCaptureArgs"); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +1 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ class ScreenRotationAnimation { .setCaptureSecureLayers(true) .setAllowProtected(true) .setSourceCrop(new Rect(0, 0, mStartWidth, mStartHeight)) .setHintForSeamlessTransition(true) .build(); ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer = ScreenCapture.captureLayers(args); Loading
services/core/java/com/android/server/wm/ScreenRotationAnimation.java +2 −0 Original line number Diff line number Diff line Loading @@ -193,6 +193,7 @@ class ScreenRotationAnimation { .setSourceCrop(new Rect(0, 0, width, height)) .setAllowProtected(true) .setCaptureSecureLayers(true) .setHintForSeamlessTransition(true) .build(); screenshotBuffer = ScreenCapture.captureDisplay(captureArgs); } else { Loading @@ -202,6 +203,7 @@ class ScreenRotationAnimation { .setCaptureSecureLayers(true) .setAllowProtected(true) .setSourceCrop(new Rect(0, 0, width, height)) .setHintForSeamlessTransition(true) .build(); screenshotBuffer = ScreenCapture.captureLayers(captureArgs); } Loading
services/core/java/com/android/server/wm/Transition.java +3 −2 Original line number Diff line number Diff line Loading @@ -2999,11 +2999,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { Rect cropBounds = new Rect(bounds); cropBounds.offsetTo(0, 0); final boolean isDisplayRotation = wc.asDisplayContent() != null && wc.asDisplayContent().isRotationChanging(); ScreenCapture.LayerCaptureArgs captureArgs = new ScreenCapture.LayerCaptureArgs.Builder(wc.getSurfaceControl()) .setSourceCrop(cropBounds) .setCaptureSecureLayers(true) .setAllowProtected(true) .setHintForSeamlessTransition(isDisplayRotation) .build(); ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer = ScreenCapture.captureLayers(captureArgs); Loading @@ -3014,8 +3017,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { Slog.w(TAG, "Failed to capture screenshot for " + wc); return false; } final boolean isDisplayRotation = wc.asDisplayContent() != null && wc.asDisplayContent().isRotationChanging(); // Some tests may check the name "RotationLayer" to detect display rotation. final String name = isDisplayRotation ? "RotationLayer" : "transition snapshot: " + wc; SurfaceControl snapshotSurface = wc.makeAnimationLeash() Loading