Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6cf051ef authored by Steven Thomas's avatar Steven Thomas
Browse files

Add setFrameRate() api

setFrameRate() is a new api in Android 11 that will enable apps to
specify their intended frame rate.

Bug: 143912624
Bug: 137287430

Test: Added a new CTS test - android.graphics.cts.SetFrameRateTest.

Change-Id: I922573c0d704e2e0ce4cfc2a462f14dce8cb7a79
parent 9f22c535
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52446,6 +52446,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);
@@ -52489,6 +52490,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);
+31 −0
Original line number Diff line number Diff line
@@ -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
@@ -840,6 +843,34 @@ public class Surface implements Parcelable {
        return mIsAutoRefreshEnabled;
    }

    /**
     * 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.
+30 −0
Original line number Diff line number Diff line
@@ -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;
    /**
@@ -2786,6 +2789,33 @@ public final class SurfaceControl implements Parcelable {
            return this;
        }

        /**
         * 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.
+7 −0
Original line number Diff line number Diff line
@@ -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)
+10 −0
Original line number Diff line number Diff line
@@ -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;",
Loading