diff options
| -rw-r--r-- | api/current.txt | 6 | ||||
| -rw-r--r-- | core/java/android/view/Surface.java | 47 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 12 | ||||
| -rw-r--r-- | core/jni/android_view_Surface.cpp | 11 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 9 | ||||
| -rw-r--r-- | native/android/surface_control.cpp | 13 |
6 files changed, 72 insertions, 26 deletions
diff --git a/api/current.txt b/api/current.txt index a0b38cd52ced..51ae4a85baa5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -53240,11 +53240,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); + 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 @NonNull public static final android.os.Parcelable.Creator<android.view.Surface> CREATOR; + field public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; // 0x0 + field public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; // 0x1 field public static final int ROTATION_0 = 0; // 0x0 field public static final int ROTATION_180 = 2; // 0x2 field public static final int ROTATION_270 = 3; // 0x3 @@ -53284,7 +53286,7 @@ package android.view { method @NonNull public android.view.SurfaceControl.Transaction reparent(@NonNull android.view.SurfaceControl, @Nullable android.view.SurfaceControl); 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); + 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 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 4ac6a666a21b..13d6dd67bb19 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -16,6 +16,8 @@ package android.view; +import static android.system.OsConstants.EINVAL; + import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; @@ -89,7 +91,8 @@ public class Surface implements Parcelable { private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled); private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled); - private static native int nativeSetFrameRate(long nativeObject, float frameRate); + private static native int nativeSetFrameRate( + long nativeObject, float frameRate, int compatibility); public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR = new Parcelable.Creator<Surface>() { @@ -184,6 +187,28 @@ public class Surface implements Parcelable { */ public static final int ROTATION_270 = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"FRAME_RATE_COMPATIBILITY_"}, + value = {FRAME_RATE_COMPATIBILITY_DEFAULT, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE}) + public @interface FrameRateCompatibility {} + + // From native_window.h. Keep these in sync. + /** + * There are no inherent restrictions on the frame rate of this surface. + */ + public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; + + /** + * This surface is being used to display content with an inherently fixed frame rate, + * e.g. a video that has a specific frame rate. When the system selects a frame rate + * other than what the app requested, the app will need to do pull down or use some + * other technique to adapt to the system's frame rate. The user experience is likely + * to be worse (e.g. more frame stuttering) than it would be if the system had chosen + * the app's requested frame rate. + */ + public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; + /** * Create an empty surface, which will later be filled in by readFromParcel(). * @hide @@ -864,11 +889,23 @@ public class Surface implements Parcelable { * called. The frameRate param does *not* need to be a valid 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 FRAME_RATE_COMPATIBILITY_* values for more info. + * + * @throws IllegalArgumentException If frameRate or compatibility are invalid. */ - public void setFrameRate(@FloatRange(from = 0.0) float frameRate) { - int error = nativeSetFrameRate(mNativeObject, frameRate); - if (error != 0) { - throw new RuntimeException("Failed to set frame rate on Surface"); + public void setFrameRate( + @FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) { + synchronized (mLock) { + checkNotReleasedLocked(); + int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility); + if (error == -EINVAL) { + throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()"); + } else if (error != 0) { + throw new RuntimeException("Failed to set frame rate on Surface"); + } } } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 29371b049b3c..0816e8433e66 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -214,7 +214,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); + long transactionObj, long nativeObject, float frameRate, int compatibility); private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; @@ -2738,13 +2738,17 @@ public final class SurfaceControl implements Parcelable { * isn't called. The frameRate param does *not* need to be a valid 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. * @return This transaction object. */ @NonNull - public Transaction setFrameRate( - @NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate) { + public Transaction setFrameRate(@NonNull SurfaceControl sc, + @FloatRange(from = 0.0) float frameRate, + @Surface.FrameRateCompatibility int compatibility) { checkPreconditions(sc); - nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate); + nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate, compatibility); return this; } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index b01083bba643..8a53bd0db8af 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -413,10 +413,15 @@ static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeO return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled)); } -static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate) { +static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate, + jint compatibility) { Surface* surface = reinterpret_cast<Surface*>(nativeObject); ANativeWindow* anw = static_cast<ANativeWindow*>(surface); - return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, float(frameRate)); + // Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and + // NATIVE_WINDOW_SET_FRAME_RATE takes an + // 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, float(frameRate), compatibility); } // ---------------------------------------------------------------------------- @@ -453,7 +458,7 @@ static const JNINativeMethod gSurfaceMethods[] = { (void*)nativeAttachAndQueueBufferWithColorSpace}, {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, - {"nativeSetFrameRate", "(JF)I", (void*)nativeSetFrameRate}, + {"nativeSetFrameRate", "(JFI)I", (void*)nativeSetFrameRate}, }; int register_android_view_Surface(JNIEnv* env) diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 741ce8291e57..a9ef257359c2 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -613,11 +613,14 @@ static void nativeSetShadowRadius(JNIEnv* env, jclass clazz, jlong transactionOb } static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, - jfloat frameRate) { + jfloat frameRate, jint compatibility) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); - transaction->setFrameRate(ctrl, frameRate); + // Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and + // 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<int8_t>(compatibility)); } static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) { @@ -1467,7 +1470,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetLayerStack }, {"nativeSetShadowRadius", "(JJF)V", (void*)nativeSetShadowRadius }, - {"nativeSetFrameRate", "(JJF)V", + {"nativeSetFrameRate", "(JJFI)V", (void*)nativeSetFrameRate }, {"nativeGetPhysicalDisplayIds", "()[J", (void*)nativeGetPhysicalDisplayIds }, diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index ba793e83f1fb..0af6cbf3cb40 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -547,16 +547,11 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, } void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction, - ASurfaceControl* aSurfaceControl, float frameRate) { + ASurfaceControl* aSurfaceControl, float frameRate, + int8_t compatibility) { CHECK_NOT_NULL(aSurfaceTransaction); CHECK_NOT_NULL(aSurfaceControl); - - sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); - if (frameRate < 0) { - ALOGE("Failed to set frame ate - invalid frame rate"); - return; - } - Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); - transaction->setFrameRate(surfaceControl, frameRate); + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + transaction->setFrameRate(surfaceControl, frameRate, compatibility); } |