diff options
5 files changed, 43 insertions, 29 deletions
diff --git a/core/java/android/window/ScreenCapture.java b/core/java/android/window/ScreenCapture.java index 95451a966055..fa7f577dadb8 100644 --- a/core/java/android/window/ScreenCapture.java +++ b/core/java/android/window/ScreenCapture.java @@ -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() { @@ -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; @@ -284,6 +288,7 @@ public class ScreenCapture { mUid = builder.mUid; mGrayscale = builder.mGrayscale; mExcludeLayers = builder.mExcludeLayers; + mHintForSeamlessTransition = builder.mHintForSeamlessTransition; } private CaptureArgs(Parcel in) { @@ -305,6 +310,7 @@ public class ScreenCapture { } else { mExcludeLayers = null; } + mHintForSeamlessTransition = in.readBoolean(); } /** Release any layers if set using {@link Builder#setExcludeLayers(SurfaceControl[])}. */ @@ -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 @@ -449,6 +456,21 @@ public class ScreenCapture { } /** + * 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 */ T getThis() { @@ -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) { @@ -480,6 +501,7 @@ public class ScreenCapture { } else { dest.writeInt(0); } + dest.writeBoolean(mHintForSeamlessTransition); } public static final Parcelable.Creator<CaptureArgs> CREATOR = @@ -627,6 +649,7 @@ public class ScreenCapture { setUid(args.mUid); setGrayscale(args.mGrayscale); setExcludeLayers(args.mExcludeLayers); + setHintForSeamlessTransition(args.mHintForSeamlessTransition); } public Builder(SurfaceControl layer) { diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp index 1b67a0da57e1..986dbe9a204c 100644 --- a/core/jni/android_window_ScreenCapture.cpp +++ b/core/jni/android_window_ScreenCapture.cpp @@ -46,6 +46,7 @@ static struct { jfieldID uid; jfieldID grayscale; jmethodID getNativeExcludeLayers; + jfieldID hintForSeamlessTransition; } gCaptureArgsClassInfo; static struct { @@ -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); @@ -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"); @@ -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, @@ -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"); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java index d25318df6b6a..9ce22094d56b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java @@ -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); diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index b5df3e0937ec..bbb85636f1ee 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -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 { @@ -202,6 +203,7 @@ class ScreenRotationAnimation { .setCaptureSecureLayers(true) .setAllowProtected(true) .setSourceCrop(new Rect(0, 0, width, height)) + .setHintForSeamlessTransition(true) .build(); screenshotBuffer = ScreenCapture.captureLayers(captureArgs); } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 54dfdd93b26c..2d4b772e654f 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -2924,11 +2924,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); @@ -2939,8 +2942,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() |