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

Commit 08972cce authored by Rachel Lee's avatar Rachel Lee Committed by Android (Google) Code Review
Browse files

Merge "Add new Surface#setFrameRate API" into main

parents d788378e 5e09609e
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -52491,6 +52491,7 @@ package android.view {
    method public android.graphics.Canvas lockHardwareCanvas();
    method public void readFromParcel(android.os.Parcel);
    method public void release();
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public void setFrameRate(@NonNull android.view.Surface.FrameRateParams);
    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);
@@ -52507,6 +52508,22 @@ package android.view {
    field public static final int ROTATION_90 = 1; // 0x1
  }
  @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public static class Surface.FrameRateParams {
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public int getChangeFrameRateStrategy();
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public float getDesiredMaxRate();
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public float getDesiredMinRate();
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public float getFixedSourceRate();
    field @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public static final android.view.Surface.FrameRateParams IGNORE;
  }
  @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") public static final class Surface.FrameRateParams.Builder {
    ctor public Surface.FrameRateParams.Builder();
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams build();
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams.Builder setChangeFrameRateStrategy(int);
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams.Builder setDesiredRateRange(@FloatRange(from=0.0) float, @FloatRange(from=0.0) float);
    method @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_api") @NonNull public android.view.Surface.FrameRateParams.Builder setFixedSourceRate(@FloatRange(from=0.0) float);
  }
  public static class Surface.OutOfResourcesException extends java.lang.RuntimeException {
    ctor public Surface.OutOfResourcesException();
    ctor public Surface.OutOfResourcesException(String);
+207 −0
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package android.view;

import static android.system.OsConstants.EINVAL;

import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo.Translator;
@@ -1025,6 +1027,211 @@ public class Surface implements Parcelable {
        return mIsAutoRefreshEnabled;
    }

    /**
     * Parameter object for {@link #setFrameRate(FrameRateParams)}, describing the intended frame
     * rate for the Surface that setFrameRate is called on.
     */
    @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
    public static class FrameRateParams {
        private FrameRateParams() {}

        /**
         * A static FrameRateParams that can be passed directly into {@link
         * #setFrameRate(FrameRateParams)} to indicate the surface has no preference and any frame
         * rate is acceptable.
         */
        @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
        public static final FrameRateParams IGNORE =
                new FrameRateParams.Builder().setDesiredRateRange(0f, Float.MAX_VALUE).build();

        @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
        public static final class Builder {
            private float mDesiredMinRate;
            private float mDesiredMaxRate;
            private float mFixedSourceRate;
            private int mChangeFrameRateStrategy;

            /**
             * Sets the desired frame rate range (inclusive) values for the surface, specifying that
             * the surface prefers the device render rate to be in the range [desiredMinRate,
             * desiredMaxRate].

             * Set desiredMaxRate to FLOAT.MAX_VALUE to indicate the surface prefers any value
             * greater than or equal to desiredMinRate.
             *
             * Set desiredMinRate = desiredMaxRate to indicate the surface prefers an exact frame
             * rate. Note that this is different than specifying the fixed source frame rate with
             * {@link FrameRateParams.Builder#setFixedSourceRate}. To reiterate, this call is used
             * to specify the surface's frame rate preference to be within the desired range.
             *
             * desiredMaxRate must be greater than or equal to desiredMinRate.
             * The values should be greater than or equal to 0.
             *
             * If the surface has no preference and any frame rate is acceptable, use the constant
             * {@link FrameRateParams.IGNORE} in {@link #setFrameRate(FrameRateParams)} instead of
             * building {@link FrameRateParams.Builder}.
             *
             * @see FrameRateParams#getDesiredMinRate()
             * @see FrameRateParams#getDesiredMaxRate()
             */
            @SuppressLint("MissingGetterMatchingBuilder")
            @NonNull
            @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
            public Builder setDesiredRateRange(@FloatRange(from = 0.0) float desiredMinRate,
                    @FloatRange(from = 0.0) float desiredMaxRate) {
                if (desiredMaxRate < desiredMinRate) {
                    Log.e(TAG,
                            "Failed to set desired frame rate range. desiredMaxRate should be "
                                    + "greater than or equal to desiredMinRate");
                    return this;
                }
                mDesiredMinRate = desiredMinRate;
                mDesiredMaxRate = desiredMaxRate;
                return this;
            }

            /**
             * Sets the fixed frame rate of the surface when its content has a fixed frame rate,
             * e.g. a video with a fixed frame rate.
             *
             * When the frame rate chosen for the surface is the {@code fixedSourceRate} or a
             * multiple, the surface can render without frame pulldown, for optimal smoothness. For
             * example, a 30 fps video ({@code fixedSourceRate=30}) renders just as well on 30 fps,
             * 60 fps, 90 fps, 120 fps, and so on.
             *
             * This method to set the fixed source rate can also be used together with a desired
             * frame rate range via {@link FrameRateParams.Builder#setDesiredRateRange}. This still
             * means the surface's content has a fixed frame rate of the provided {@code
             * fixedSourceRate}, as well as it preferring to be within the desired frame rate range.
             * For example, a 30 fps video {@code fixedSourceRate=30} and desired frame rate range
             * [60,90] means the surface ideally prefers 60 fps (which is 30 fps * 2) or 90 fps (30
             * fps * 3).
             *
             * @see FrameRateParams#getFixedSourceRate()
             */
            @NonNull
            @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
            public Builder setFixedSourceRate(@FloatRange(from = 0.0) float fixedSourceRate) {
                mFixedSourceRate = fixedSourceRate;
                return this;
            }

            /**
             * Whether display refresh rate transitions caused by this surface 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. Value is
             * Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, or Surface.CHANGE_FRAME_RATE_ALWAYS
             *
             * @see FrameRateParams#getChangeFrameRateStrategy()
             */
            @NonNull
            @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
            public Builder setChangeFrameRateStrategy(
                    @ChangeFrameRateStrategy int changeFrameRateStrategy) {
                mChangeFrameRateStrategy = changeFrameRateStrategy;
                return this;
            }

            /**
             * Builds the FrameRateParams object.
             */
            @NonNull
            @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
            public FrameRateParams build() {
                FrameRateParams frameRate = new FrameRateParams();
                frameRate.mDesiredMinRate = this.mDesiredMinRate;
                frameRate.mDesiredMaxRate = this.mDesiredMaxRate;
                frameRate.mFixedSourceRate = this.mFixedSourceRate;
                frameRate.mChangeFrameRateStrategy = this.mChangeFrameRateStrategy;
                return frameRate;
            }
        }

        /**
         * Gets the minimum desired frame rate.
         * @see FrameRateParams.Builder#setDesiredRateRange()
         */
        @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
        public float getDesiredMinRate() {
            return mDesiredMinRate;
        }

        /**
         * Gets the maximum desired frame rate.
         * @see FrameRateParams.Builder#setDesiredRateRange()
         */
        @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
        public float getDesiredMaxRate() {
            return mDesiredMaxRate;
        }

        /**
         * Gets the fixed source frame rate.
         * @see FrameRateParams.Builder#setFixedSourceRate()
         */
        @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
        public float getFixedSourceRate() {
            return mFixedSourceRate;
        }

        /**
         * Gets the strategy when changing frame rate.
         * @see FrameRateParams.Builder#setChangeFrameRateStrategy
         */
        @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
        @ChangeFrameRateStrategy
        public int getChangeFrameRateStrategy() {
            return mChangeFrameRateStrategy;
        }

        float mDesiredMinRate;
        float mDesiredMaxRate;
        float mFixedSourceRate;
        int mChangeFrameRateStrategy;
    }

    /**
     * Sets the intended frame rate for this surface.
     *
     * <p>On devices that are capable of running the display at different frame 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.</p>
     *
     * <p>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.</p>
     *
     * @param frameRateParams The parameters describing the intended frame rate of this surface.
     *         Refer to {@link FrameRateParams} for details.
     * @throws IllegalArgumentException If <code>frameRateParams</code> is invalid.
     * @see #clearFrameRate()
     */
    @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_API)
    public void setFrameRate(@NonNull FrameRateParams frameRateParams) {
        synchronized (mLock) {
            checkNotReleasedLocked();
            // TODO(b/362798998): Logic currently incomplete: it uses fixed source rate over the
            // desired min/max rates. Fix when plumbing is upgraded.
            int compatibility = frameRateParams.getFixedSourceRate() == 0
                    ? FRAME_RATE_COMPATIBILITY_DEFAULT
                    : FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
            float frameRate = compatibility == FRAME_RATE_COMPATIBILITY_DEFAULT
                    ? frameRateParams.getDesiredMinRate()
                    : frameRateParams.getFixedSourceRate();
            int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility,
                    frameRateParams.getChangeFrameRateStrategy());
            if (error == -EINVAL) {
                throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");
            } else if (error != 0) {
                Log.e(TAG, "Failed to set frame rate on Surface. Native error: " + error);
            }
        }
    }

    /**
     * Sets the intended frame rate for this surface.
     *