diff options
| author | 2024-10-22 18:31:11 +0000 | |
|---|---|---|
| committer | 2024-10-22 18:31:11 +0000 | |
| commit | 08972cceb00553aee7245e7bfc996675f11bd55d (patch) | |
| tree | d77f81eb2176d9b26ba3ce5e02e9e8e4425e546a | |
| parent | d788378eca2fa15f9f33199d056dbc29b46511d4 (diff) | |
| parent | 5e09609eda2919ddd40d1b6175518cbe0a3d3936 (diff) | |
Merge "Add new Surface#setFrameRate API" into main
| -rw-r--r-- | core/api/current.txt | 17 | ||||
| -rw-r--r-- | core/java/android/view/Surface.java | 207 |
2 files changed, 224 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index a8b9e331de2a..09fef2530ec9 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -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); diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 396be7b62b4d..03f9d9814b43 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -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; @@ -1026,6 +1028,211 @@ public class Surface implements Parcelable { } /** + * 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. * * <p>On devices that are capable of running the display at different refresh rates, |