diff options
-rw-r--r-- | api/current.txt | 2 | ||||
-rw-r--r-- | core/java/android/view/Surface.java | 31 | ||||
-rw-r--r-- | core/java/android/view/SurfaceControl.java | 30 | ||||
-rw-r--r-- | core/jni/android_view_Surface.cpp | 7 | ||||
-rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 10 | ||||
-rw-r--r-- | native/android/libandroid.map.txt | 1 | ||||
-rw-r--r-- | native/android/surface_control.cpp | 15 |
7 files changed, 96 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index 16dee4b58da6..6eb65824c5ab 100644 --- a/api/current.txt +++ b/api/current.txt @@ -52617,6 +52617,7 @@ 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 @Deprecated public void unlockCanvas(android.graphics.Canvas); method public void unlockCanvasAndPost(android.graphics.Canvas); method public void writeToParcel(android.os.Parcel, int); @@ -52660,6 +52661,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 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 7707ad163b85..a6b7c33de3d9 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -16,6 +16,7 @@ package android.view; +import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; @@ -88,6 +89,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); + public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR = new Parcelable.Creator<Surface>() { @Override @@ -841,6 +844,34 @@ public class Surface implements Parcelable { } /** + * Sets the intended frame rate for this surface. + * + * On devices that are capable of running the display at different refresh rates, the + * system may choose a display refresh rate to better match this surface's frame + * rate. Usage of this API won't introduce frame rate throttling, or affect other + * aspects of the application's frame production pipeline. However, because the system + * may change the display refresh rate, calls to this function may result in changes + * to Choreographer callback timings, and changes to the time interval at which the + * system releases buffers back to the application. + * + * Note that this only has an effect for surfaces presented on the display. If this + * surface is consumed by something other than the system compositor, e.g. a media + * codec, this call has no effect. + * + * @param frameRate The intended frame rate of this surface. 0 is a special value that + * indicates the app will accept the system's choice for the display frame rate, which + * is the default behavior if this function 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. + */ + 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"); + } + } + + /** * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or * when a SurfaceTexture could not successfully be allocated. */ diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index bcc9e41b8ab0..f7b87cce7338 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -211,6 +211,9 @@ public final class SurfaceControl implements Parcelable { private static native void nativeSetGlobalShadowSettings(@Size(4) float[] ambientColor, @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius); + private static native void nativeSetFrameRate( + long transactionObj, long nativeObject, float frameRate); + private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; /** @@ -2787,6 +2790,33 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets the intended frame rate for the surface {@link SurfaceControl}. + * + * On devices that are capable of running the display at different refresh rates, the system + * may choose a display refresh rate to better match this surface's frame rate. Usage of + * this API won't directly affect the application's frame production pipeline. However, + * because the system may change the display refresh rate, calls to this function may result + * in changes to Choreographer callback timings, and changes to the time interval at which + * the system releases buffers back to the application. + * + * @param sc The SurfaceControl to specify the frame rate of. + * @param frameRate The intended frame rate for this surface. 0 is a special value that + * indicates the app will accept the system's choice for the display frame + * rate, which is the default behavior if this function 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. + * @return This transaction object. + */ + @NonNull + public Transaction setFrameRate( + @NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate) { + checkPreconditions(sc); + nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate); + 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_Surface.cpp b/core/jni/android_view_Surface.cpp index 01b5920755fa..b01083bba643 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -413,6 +413,12 @@ 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) { + Surface* surface = reinterpret_cast<Surface*>(nativeObject); + ANativeWindow* anw = static_cast<ANativeWindow*>(surface); + return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, float(frameRate)); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gSurfaceMethods[] = { @@ -447,6 +453,7 @@ static const JNINativeMethod gSurfaceMethods[] = { (void*)nativeAttachAndQueueBufferWithColorSpace}, {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, + {"nativeSetFrameRate", "(JF)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 e0f9571472da..2b9d45431582 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -584,6 +584,14 @@ static void nativeSetShadowRadius(JNIEnv* env, jclass clazz, jlong transactionOb transaction->setShadowRadius(ctrl, shadowRadius); } +static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, + jfloat frameRate) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + + const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject); + transaction->setFrameRate(ctrl, frameRate); +} + static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) { const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds(); jlongArray array = env->NewLongArray(displayIds.size()); @@ -1383,6 +1391,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetLayerStack }, {"nativeSetShadowRadius", "(JJF)V", (void*)nativeSetShadowRadius }, + {"nativeSetFrameRate", "(JJF)V", + (void*)nativeSetFrameRate }, {"nativeGetPhysicalDisplayIds", "()[J", (void*)nativeGetPhysicalDisplayIds }, {"nativeGetPhysicalDisplayToken", "(J)Landroid/os/IBinder;", diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index 203adfc749d2..97b861b390ad 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -240,6 +240,7 @@ LIBANDROID { ASurfaceTransaction_setColor; # introduced=29 ASurfaceTransaction_setDamageRegion; # introduced=29 ASurfaceTransaction_setDesiredPresentTime; # introduced=29 + ASurfaceTransaction_setFrameRate; # introduced=30 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 b34b31ac8439..392c9f6404ba 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -545,3 +545,18 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, transaction->setBackgroundColor(surfaceControl, color, alpha, static_cast<ui::Dataspace>(dataspace)); } + +void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, float frameRate) { + 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); +} |