summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Thomas <steventhomas@google.com>2020-01-23 19:40:20 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-01-23 19:40:20 +0000
commit8c9f31b8b0cfff3d45a690609ee05fdb96e54bb9 (patch)
treec06779d8a8c0b1ef5bf63a5d2615a241843516e7
parentffd216dfa2acd763f9768b99820b304e59668f69 (diff)
parent6cf051ef8909be67f3fa7d6212a510d58e63df35 (diff)
Merge "Add setFrameRate() api"
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/view/Surface.java31
-rw-r--r--core/java/android/view/SurfaceControl.java30
-rw-r--r--core/jni/android_view_Surface.cpp7
-rw-r--r--core/jni/android_view_SurfaceControl.cpp10
-rw-r--r--native/android/libandroid.map.txt1
-rw-r--r--native/android/surface_control.cpp15
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);
+}