diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 21f75d419a5e0..2c81e8986ac6b 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -35,6 +35,7 @@ import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Bitmap; import android.graphics.ColorSpace; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; @@ -188,6 +189,10 @@ public final class SurfaceControl implements Parcelable { IBinder displayToken, int mode); private static native void nativeReparent(long transactionObj, long nativeObject, long newParentNativeObject); + private static native void nativeSetBuffer(long transactionObj, long nativeObject, + GraphicBuffer buffer); + private static native void nativeSetColorSpace(long transactionObj, long nativeObject, + int colorSpace); private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes); @@ -3362,6 +3367,31 @@ public final class SurfaceControl implements Parcelable { return this; } + /** + * Set a buffer for a SurfaceControl. This can only be used for SurfaceControls that were + * created as type {@link #FX_SURFACE_BLAST} + * + * @hide + */ + public Transaction setBuffer(SurfaceControl sc, GraphicBuffer buffer) { + checkPreconditions(sc); + nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer); + return this; + } + + /** + * Set the color space for the SurfaceControl. The supported color spaces are SRGB + * and Display P3, other color spaces will be treated as SRGB. This can only be used for + * SurfaceControls that were created as type {@link #FX_SURFACE_BLAST} + * + * @hide + */ + public Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) { + checkPreconditions(sc); + nativeSetColorSpace(mNativeObject, sc.mNativeObject, colorSpace.getId()); + return this; + } + /** * Merge the other transaction into this transaction, clearing the * other transaction as if it had been applied. diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index ffba628f73ab9..4194acbfe015c 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -253,6 +254,15 @@ constexpr jint fromDataspaceToNamedColorSpaceValue(const ui::Dataspace dataspace } } +constexpr ui::Dataspace fromNamedColorSpaceValueToDataspace(const jint colorSpace) { + switch (colorSpace) { + case JNamedColorSpace::DISPLAY_P3: + return ui::Dataspace::DISPLAY_P3; + default: + return ui::Dataspace::V0_SRGB; + } +} + constexpr ui::Dataspace pickDataspaceFromColorMode(const ui::ColorMode colorMode) { switch (colorMode) { case ui::ColorMode::DISPLAY_P3: @@ -553,6 +563,23 @@ static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, j transaction->setGeometry(ctrl, source, dst, orientation); } +static void nativeSetBuffer(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, + jobject bufferObject) { + auto transaction = reinterpret_cast(transactionObj); + SurfaceControl* const ctrl = reinterpret_cast(nativeObject); + sp buffer( + android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env, bufferObject)); + transaction->setBuffer(ctrl, buffer); +} + +static void nativeSetColorSpace(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, + jint colorSpace) { + auto transaction = reinterpret_cast(transactionObj); + SurfaceControl* const ctrl = reinterpret_cast(nativeObject); + ui::Dataspace dataspace = fromNamedColorSpaceValueToDataspace(colorSpace); + transaction->setDataspace(ctrl, dataspace); +} + static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jobjectArray regions, jint regionsLength) { auto transaction = reinterpret_cast(transactionObj); @@ -1877,6 +1904,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetDisplayedContentSample }, {"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V", (void*)nativeSetGeometry }, + {"nativeSetBuffer", "(JJLandroid/graphics/GraphicBuffer;)V", + (void*)nativeSetBuffer }, + {"nativeSetColorSpace", "(JJI)V", + (void*)nativeSetColorSpace }, {"nativeSyncInputWindows", "(J)V", (void*)nativeSyncInputWindows }, {"nativeGetDisplayBrightnessSupport", "(Landroid/os/IBinder;)Z", diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 95a4f69edd575..fb66c04930251 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -36,9 +36,11 @@ import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER; import android.animation.ArgbEvaluator; import android.content.Context; import android.graphics.Color; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; +import android.hardware.HardwareBuffer; import android.os.Trace; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -210,9 +212,9 @@ class ScreenRotationAnimation { String name = "RotationLayer"; mScreenshotLayer = displayContent.makeOverlay() .setName(name) - .setBufferSize(mWidth, mHeight) .setSecure(isSecure) .setCallsite("ScreenRotationAnimation") + .setBLASTLayer() .build(); // This is the way to tell the input system to exclude this surface from occlusion // detection since we don't have a window for it. We do this because this window is @@ -225,32 +227,29 @@ class ScreenRotationAnimation { .setCallsite("ScreenRotationAnimation") .build(); - final Surface surface = mService.mSurfaceFactory.get(); - // In case display bounds change, screenshot buffer and surface may mismatch so - // set a scaling mode. - surface.copyFrom(mScreenshotLayer); - surface.setScalingMode(Surface.SCALING_MODE_SCALE_TO_WINDOW); - + HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ScreenRotationAnimation#getMedianBorderLuma"); - mStartLuma = RotationAnimationUtils.getMedianBorderLuma( - screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace()); + mStartLuma = RotationAnimationUtils.getMedianBorderLuma(hardwareBuffer, + screenshotBuffer.getColorSpace()); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - try { - surface.attachAndQueueBufferWithColorSpace(screenshotBuffer.getHardwareBuffer(), - screenshotBuffer.getColorSpace()); - } catch (RuntimeException e) { - Slog.w(TAG, "Failed to attach screenshot - " + e.getMessage()); - } + + GraphicBuffer buffer = GraphicBuffer.createFromHardwareBuffer( + screenshotBuffer.getHardwareBuffer()); + // Scale the layer to the display size. + float dsdx = (float) mWidth / hardwareBuffer.getWidth(); + float dsdy = (float) mHeight / hardwareBuffer.getHeight(); t.setLayer(mScreenshotLayer, SCREEN_FREEZE_LAYER_BASE); t.reparent(mBackColorSurface, displayContent.getSurfaceControl()); t.setLayer(mBackColorSurface, -1); t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma}); t.setAlpha(mBackColorSurface, 1); + t.setBuffer(mScreenshotLayer, buffer); + t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace()); + t.setMatrix(mScreenshotLayer, dsdx, 0, 0, dsdy); t.show(mScreenshotLayer); t.show(mBackColorSurface); - surface.destroy(); } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate freeze surface", e); diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java index 6f434e05c8001..e0a791e118bb0 100644 --- a/services/core/java/com/android/server/wm/SurfaceFreezer.java +++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java @@ -22,6 +22,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATI import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.GraphicBuffer; import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.HardwareBuffer; @@ -153,29 +154,24 @@ class SurfaceFreezer { */ Snapshot(Supplier surfaceFactory, SurfaceControl.Transaction t, SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer, SurfaceControl parent) { - Surface drawSurface = surfaceFactory.get(); // We can't use a delegating constructor since we need to // reference this::onAnimationFinished - HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer(); - final int width = hardwareBuffer.getWidth(); - final int height = hardwareBuffer.getHeight(); + GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer( + screenshotBuffer.getHardwareBuffer()); mSurfaceControl = mAnimatable.makeAnimationLeash() .setName("snapshot anim: " + mAnimatable.toString()) - .setBufferSize(width, height) .setFormat(PixelFormat.TRANSLUCENT) .setParent(parent) .setSecure(screenshotBuffer.containsSecureLayers()) .setCallsite("SurfaceFreezer.Snapshot") + .setBLASTLayer() .build(); ProtoLog.i(WM_SHOW_TRANSACTIONS, " THUMBNAIL %s: CREATE", mSurfaceControl); - // Transfer the thumbnail to the surface - drawSurface.copyFrom(mSurfaceControl); - drawSurface.attachAndQueueBufferWithColorSpace(hardwareBuffer, - screenshotBuffer.getColorSpace()); - drawSurface.release(); + t.setBuffer(mSurfaceControl, graphicBuffer); + t.setColorSpace(mSurfaceControl, screenshotBuffer.getColorSpace()); t.show(mSurfaceControl); // We parent the thumbnail to the container, and just place it on top of anything else diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 2e37fee1fb1ca..9382b8eed0b8f 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -36,6 +36,7 @@ import android.annotation.Nullable; import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.graphics.GraphicBuffer; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Binder; @@ -45,7 +46,6 @@ import android.os.Parcel; import android.os.RemoteException; import android.util.ArraySet; import android.util.Slog; -import android.view.Surface; import android.view.SurfaceControl; import android.window.IDisplayAreaOrganizerController; import android.window.ITaskOrganizerController; @@ -766,18 +766,21 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return false; } + GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer( + buffer.getHardwareBuffer()); SurfaceControl screenshot = mService.mWindowManager.mSurfaceControlFactory.apply(null) .setName(wc.getName() + " - Organizer Screenshot") - .setBufferSize(bounds.width(), bounds.height()) .setFormat(PixelFormat.TRANSLUCENT) .setParent(wc.getParentSurfaceControl()) + .setSecure(buffer.containsSecureLayers()) .setCallsite("WindowOrganizerController.takeScreenshot") + .setBLASTLayer() .build(); - Surface surface = new Surface(); - surface.copyFrom(screenshot); - surface.attachAndQueueBufferWithColorSpace(buffer.getHardwareBuffer(), null); - surface.release(); + SurfaceControl.Transaction transaction = mService.mWindowManager.mTransactionFactory.get(); + transaction.setBuffer(screenshot, graphicBuffer); + transaction.setColorSpace(screenshot, buffer.getColorSpace()); + transaction.apply(); outSurfaceControl.copyFrom(screenshot, "WindowOrganizerController.takeScreenshot"); return true; diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java index f3616da6c102b..619aee6eb919d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java +++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java @@ -17,6 +17,8 @@ package com.android.server.wm; import android.annotation.NonNull; +import android.graphics.ColorSpace; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.Region; @@ -253,4 +255,14 @@ public class StubTransaction extends SurfaceControl.Transaction { public SurfaceControl.Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) { return this; } + + @Override + public SurfaceControl.Transaction setBuffer(SurfaceControl sc, GraphicBuffer buffer) { + return this; + } + + @Override + public SurfaceControl.Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) { + return this; + } }