From 511f9145bac4c52ba444935738e5bcd2c1bd8bad Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Tue, 16 Mar 2021 18:03:30 +0100 Subject: setFrameRate: Make shouldBeSeamless an enum Change the shouldBeSeamless parameter to an enum in order to make the API easier to understand. This changes - SurfaceControl.setFrameRate - Surface.setFrameRate - ANativeWindow_setFrameRateWithChangeStrategy - ASurfaceTransaction_setFrameRateWithChangeStrategy Bug: 179116474 Test: atest SetFrameRateTest Change-Id: I55265399238e2c95fbb90fd33a4c2513d1fc5cec --- core/api/current.txt | 6 +++-- core/java/android/view/Surface.java | 42 +++++++++++++++++++++--------- core/java/android/view/SurfaceControl.java | 27 ++++++++----------- core/jni/android_view_Surface.cpp | 6 ++--- core/jni/android_view_SurfaceControl.cpp | 6 ++--- native/android/libandroid.map.txt | 2 +- native/android/surface_control.cpp | 19 +++++++------- 7 files changed, 61 insertions(+), 47 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 4aa38d64ecf9..5d05f4f39497 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -47801,11 +47801,13 @@ package android.view { method public android.graphics.Canvas lockHardwareCanvas(); method public void readFromParcel(android.os.Parcel); method public void release(); - method public void setFrameRate(@FloatRange(from=0.0) float, int, boolean); + method public void setFrameRate(@FloatRange(from=0.0) float, int, int); method public void setFrameRate(@FloatRange(from=0.0) float, int); method @Deprecated public void unlockCanvas(android.graphics.Canvas); method public void unlockCanvasAndPost(android.graphics.Canvas); method public void writeToParcel(android.os.Parcel, int); + field public static final int CHANGE_FRAME_RATE_ALWAYS = 1; // 0x1 + field public static final int CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS = 0; // 0x0 field @NonNull public static final android.os.Parcelable.Creator CREATOR; field public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; // 0x0 field public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; // 0x1 @@ -47849,7 +47851,7 @@ package android.view { method @NonNull public android.view.SurfaceControl.Transaction setAlpha(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0, to=1.0) float); method @NonNull public android.view.SurfaceControl.Transaction setBufferSize(@NonNull android.view.SurfaceControl, @IntRange(from=0) int, @IntRange(from=0) int); method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int); - method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int, boolean); + method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int, int); method @NonNull public android.view.SurfaceControl.Transaction setGeometry(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, int); method @NonNull public android.view.SurfaceControl.Transaction setLayer(@NonNull android.view.SurfaceControl, @IntRange(from=java.lang.Integer.MIN_VALUE, to=java.lang.Integer.MAX_VALUE) int); method @NonNull public android.view.SurfaceControl.Transaction setVisibility(@NonNull android.view.SurfaceControl, boolean); diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index f8c4d1587f22..aa3c9d6e14f9 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -97,7 +97,7 @@ public class Surface implements Parcelable { private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled); private static native int nativeSetFrameRate( - long nativeObject, float frameRate, int compatibility, boolean shouldBeSeamless); + long nativeObject, float frameRate, int compatibility, int changeFrameRateStrategy); public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -226,6 +226,26 @@ public class Surface implements Parcelable { */ public static final int FRAME_RATE_COMPATIBILITY_EXACT = 100; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CHANGE_FRAME_RATE_"}, + value = {CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, CHANGE_FRAME_RATE_ALWAYS}) + public @interface ChangeFrameRateStrategy {} + + /** + * Change the frame rate only if the transition is going to be seamless. + */ + public static final int CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS = 0; + + /** + * Change the frame rate even if the transition is going to be non-seamless, i.e. with visual + * interruptions for the user. Non-seamless switches might be used when the benefit of matching + * the content's frame rate outweighs the cost of the transition, for example when + * displaying long-running video content. + */ + public static final int CHANGE_FRAME_RATE_ALWAYS = 1; + /** * Create an empty surface, which will later be filled in by readFromParcel(). * @hide @@ -921,25 +941,21 @@ public class Surface implements Parcelable { * the display at 60fps. * * @param compatibility The frame rate compatibility of this surface. The - * compatibility value may influence the system's choice of display frame rate. See - * the FRAME_RATE_COMPATIBILITY_* values for more info. + * compatibility value may influence the system's choice of display frame rate. * - * @param shouldBeSeamless Whether display refresh rate transitions should be seamless. A + * @param changeFrameRateStrategy Whether display refresh rate transitions should be seamless. A * seamless transition is one that doesn't have any visual interruptions, such as a black - * screen for a second or two. True indicates that any frame rate changes caused by this - * request should be seamless. False indicates that non-seamless refresh rates are also - * acceptable. Non-seamless switches might be used when the benefit of matching the content's - * frame rate outweighs the cost of the transition, for example when displaying - * long-running video content. + * screen for a second or two. * * @throws IllegalArgumentException If frameRate or compatibility are invalid. */ public void setFrameRate(@FloatRange(from = 0.0) float frameRate, - @FrameRateCompatibility int compatibility, boolean shouldBeSeamless) { + @FrameRateCompatibility int compatibility, + @ChangeFrameRateStrategy int changeFrameRateStrategy) { synchronized (mLock) { checkNotReleasedLocked(); int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility, - shouldBeSeamless); + changeFrameRateStrategy); if (error == -EINVAL) { throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()"); } else if (error != 0) { @@ -952,11 +968,11 @@ public class Surface implements Parcelable { * Sets the intended frame rate for this surface. Any switching of refresh rates is * most probably going to be seamless. * - * @see #setFrameRate(float, int, boolean) + * @see #setFrameRate(float, int, int) */ public void setFrameRate( @FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) { - setFrameRate(frameRate, compatibility, /* shouldBeSeamless = */ true); + setFrameRate(frameRate, compatibility, CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); } /** diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 03dd10050724..dd470e50cf63 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -209,7 +209,7 @@ public final class SurfaceControl implements Parcelable { @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius); private static native void nativeSetFrameRate(long transactionObj, long nativeObject, - float frameRate, int compatibility, boolean shouldBeSeamless); + float frameRate, int compatibility, int changeFrameRateStrategy); private static native long nativeGetHandle(long nativeObject); private static native long nativeAcquireFrameRateFlexibilityToken(); @@ -3229,13 +3229,14 @@ public final class SurfaceControl implements Parcelable { * Sets the intended frame rate for this surface. Any switching of refresh rates is * most probably going to be seamless. * - * @see #setFrameRate(SurfaceControl, float, int, boolean) + * @see #setFrameRate(SurfaceControl, float, int, int) */ @NonNull public Transaction setFrameRate(@NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate, @Surface.FrameRateCompatibility int compatibility) { - return setFrameRate(sc, frameRate, compatibility, /*shouldBeSeamless*/ true); + return setFrameRate(sc, frameRate, compatibility, + Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); } /** @@ -3256,27 +3257,21 @@ public final class SurfaceControl implements Parcelable { * refresh rate for this device's display - e.g., it's fine to pass 30fps * to a device that can only run the display at 60fps. * @param compatibility The frame rate compatibility of this surface. The compatibility - * value may influence the system's choice of display frame rate. See - * the Surface.FRAME_RATE_COMPATIBILITY_* values for more info. - * @param shouldBeSeamless Whether display refresh rate transitions should be seamless. A - * seamless transition is one that doesn't have any visual - * interruptions, such as a black screen for a second or two. True - * indicates that any frame rate changes caused by this request - * should be seamless. False indicates that non-seamless refresh - * rates are also acceptable. Non-seamless switches might be - * used when the benefit of matching the content's frame rate - * outweighs the cost of the transition, for example when - * displaying long-running video content. + * value may influence the system's choice of display frame rate. + * @param changeFrameRateStrategy Whether display refresh rate transitions should be + * seamless. A seamless transition is one that doesn't have + * any visual interruptions, such as a black screen for a + * second or two. * @return This transaction object. */ @NonNull public Transaction setFrameRate(@NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate, @Surface.FrameRateCompatibility int compatibility, - boolean shouldBeSeamless) { + @Surface.ChangeFrameRateStrategy int changeFrameRateStrategy) { checkPreconditions(sc); nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate, compatibility, - shouldBeSeamless); + changeFrameRateStrategy); return this; } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 5b29f0bb8932..0957067de603 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -438,7 +438,7 @@ static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeO } static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate, - jint compatibility, jboolean shouldBeSeamless) { + jint compatibility, jint changeFrameRateStrategy) { Surface* surface = reinterpret_cast(nativeObject); ANativeWindow* anw = static_cast(surface); // Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and @@ -446,7 +446,7 @@ static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jf // ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The values are identical // though, so no need to explicitly convert. return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, double(frameRate), compatibility, - int(shouldBeSeamless)); + int(changeFrameRateStrategy)); } // ---------------------------------------------------------------------------- @@ -475,7 +475,7 @@ static const JNINativeMethod gSurfaceMethods[] = { (void*)nativeAttachAndQueueBufferWithColorSpace}, {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, - {"nativeSetFrameRate", "(JFIZ)I", (void*)nativeSetFrameRate}, + {"nativeSetFrameRate", "(JFII)I", (void*)nativeSetFrameRate}, {"nativeGetFromBlastBufferQueue", "(JJ)J", (void*)nativeGetFromBlastBufferQueue}, }; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 31cc77f74c44..b10c80a10786 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -782,7 +782,7 @@ static void nativeSetShadowRadius(JNIEnv* env, jclass clazz, jlong transactionOb } static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, - jfloat frameRate, jint compatibility, jboolean shouldBeSeamless) { + jfloat frameRate, jint compatibility, jint changeFrameRateStrategy) { auto transaction = reinterpret_cast(transactionObj); const auto ctrl = reinterpret_cast(nativeObject); @@ -790,7 +790,7 @@ static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, // Transaction::setFrameRate() takes an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The // values are identical though, so no need to convert anything. transaction->setFrameRate(ctrl, frameRate, static_cast(compatibility), - bool(shouldBeSeamless)); + static_cast(changeFrameRateStrategy)); } static jlong nativeAcquireFrameRateFlexibilityToken(JNIEnv* env, jclass clazz) { @@ -1775,7 +1775,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*) nativeSetStretchEffect }, {"nativeSetShadowRadius", "(JJF)V", (void*)nativeSetShadowRadius }, - {"nativeSetFrameRate", "(JJFIZ)V", + {"nativeSetFrameRate", "(JJFII)V", (void*)nativeSetFrameRate }, {"nativeAcquireFrameRateFlexibilityToken", "()J", (void*)nativeAcquireFrameRateFlexibilityToken }, diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index b01878b3070b..1de62211998d 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -253,7 +253,7 @@ LIBANDROID { ASurfaceTransaction_setDamageRegion; # introduced=29 ASurfaceTransaction_setDesiredPresentTime; # introduced=29 ASurfaceTransaction_setFrameRate; # introduced=30 - ASurfaceTransaction_setFrameRateWithSeamlessness; # introduced=31 + ASurfaceTransaction_setFrameRateWithChangeStrategy; # introduced=31 ASurfaceTransaction_setGeometry; # introduced=29 ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29 ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29 diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index e8cf63f64572..6c12c438554f 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -596,24 +596,25 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, color.g = g; color.b = b; - transaction->setBackgroundColor(surfaceControl, color, alpha, static_cast(dataspace)); + transaction->setBackgroundColor(surfaceControl, color, alpha, + static_cast(dataspace)); } void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, float frameRate, int8_t compatibility) { - ASurfaceTransaction_setFrameRateWithSeamlessness(aSurfaceTransaction, aSurfaceControl, - frameRate, compatibility, - /*shouldBeSeamless*/ true); + ASurfaceTransaction_setFrameRateWithChangeStrategy( + aSurfaceTransaction, aSurfaceControl, frameRate, compatibility, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); } -void ASurfaceTransaction_setFrameRateWithSeamlessness(ASurfaceTransaction* aSurfaceTransaction, - ASurfaceControl* aSurfaceControl, - float frameRate, int8_t compatibility, - bool shouldBeSeamless) { +void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + float frameRate, int8_t compatibility, + int8_t changeFrameRateStrategy) { CHECK_NOT_NULL(aSurfaceTransaction); CHECK_NOT_NULL(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); sp surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); - transaction->setFrameRate(surfaceControl, frameRate, compatibility, shouldBeSeamless); + transaction->setFrameRate(surfaceControl, frameRate, compatibility, changeFrameRateStrategy); } -- cgit v1.2.3-59-g8ed1b