Add Surface.clearFrameRate API

This API is same as using setFrameRate with 0 as frame-rate value. But
this causes confusion, as the remaining two arguments are ignored, when
frame-rate is 0.

Bug: 241096917
Test: android.graphics.cts.SetFrameRateTest#testClearFrameRate
Change-Id: I1324c64ac75dacb78a733df2b91d7a5b46fc7455
diff --git a/core/api/current.txt b/core/api/current.txt
index 317f8eb..fa30d02 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -49421,6 +49421,7 @@
   public class Surface implements android.os.Parcelable {
     ctor public Surface(@NonNull android.view.SurfaceControl);
     ctor public Surface(android.graphics.SurfaceTexture);
+    method public void clearFrameRate();
     method public int describeContents();
     method public boolean isValid();
     method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
@@ -49478,6 +49479,7 @@
     ctor public SurfaceControl.Transaction();
     method @NonNull public android.view.SurfaceControl.Transaction addTransactionCommittedListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.SurfaceControl.TransactionCommittedListener);
     method public void apply();
+    method @NonNull public android.view.SurfaceControl.Transaction clearFrameRate(@NonNull android.view.SurfaceControl);
     method public void close();
     method public int describeContents();
     method @NonNull public android.view.SurfaceControl.Transaction merge(@NonNull android.view.SurfaceControl.Transaction);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6b21bed..2208f89 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -985,6 +985,8 @@
      *
      * @throws IllegalArgumentException If <code>frameRate</code>, <code>compatibility</code> or
      * <code>changeFrameRateStrategy</code> are invalid.
+     *
+     * @see #clearFrameRate()
      */
     public void setFrameRate(@FloatRange(from = 0.0) float frameRate,
             @FrameRateCompatibility int compatibility,
@@ -996,7 +998,33 @@
             if (error == -EINVAL) {
                 throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");
             } else if (error != 0) {
-                throw new RuntimeException("Failed to set frame rate on Surface");
+                throw new RuntimeException("Failed to set frame rate on Surface. Native error: "
+                        + error);
+            }
+        }
+    }
+
+    /**
+     * Clears the frame rate which was set for this surface.
+     *
+     * <p>This is equivalent to calling {@link #setFrameRate(float, int, int)} using {@code 0} for
+     * {@code frameRate}.
+     * <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>
+     *
+     * @see #setFrameRate(float, int, int)
+     */
+    public void clearFrameRate() {
+        synchronized (mLock) {
+            checkNotReleasedLocked();
+            // The values FRAME_RATE_COMPATIBILITY_DEFAULT and CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
+            // are ignored because the value of frameRate is 0
+            int error = nativeSetFrameRate(mNativeObject, 0,
+                    FRAME_RATE_COMPATIBILITY_DEFAULT, CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+            if (error != 0) {
+                throw new RuntimeException("Failed to clear the frame rate on Surface. Native error"
+                        + ": " + error);
             }
         }
     }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index e0f02d6..385cc17 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -3612,6 +3612,8 @@
          *                                black screen for a second or two. This parameter is
          *                                ignored when <code>frameRate</code> is 0.
          * @return This transaction object.
+         *
+         * @see #clearFrameRate(SurfaceControl)
          */
         @NonNull
         public Transaction setFrameRate(@NonNull SurfaceControl sc,
@@ -3625,6 +3627,30 @@
         }
 
         /**
+         * Clears the frame rate which was set for the surface {@link SurfaceControl}.
+         *
+         * <p>This is equivalent to calling {@link #setFrameRate(SurfaceControl, float, int, int)}
+         * using {@code 0} for {@code frameRate}.
+         * <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.
+         *
+         * @param sc The SurfaceControl to clear the frame rate of.
+         * @return This transaction object.
+         *
+         * @see #setFrameRate(SurfaceControl, float, int)
+         */
+        @NonNull
+        public Transaction clearFrameRate(@NonNull SurfaceControl sc) {
+            checkPreconditions(sc);
+            nativeSetFrameRate(mNativeObject, sc.mNativeObject, 0.0f,
+                    Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+                    Surface.CHANGE_FRAME_RATE_ALWAYS);
+            return this;
+        }
+
+        /**
          * Sets the default frame rate compatibility for the surface {@link SurfaceControl}
          *
          * @param sc The SurfaceControl to specify the frame rate of.
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 4aa5bbf..1f96617 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -266,6 +266,7 @@
     ASurfaceTransaction_setEnableBackPressure; # introduced=31
     ASurfaceTransaction_setFrameRate; # introduced=30
     ASurfaceTransaction_setFrameRateWithChangeStrategy; # introduced=31
+    ASurfaceTransaction_clearFrameRate; # introduced=34
     ASurfaceTransaction_setFrameTimeline; # introduced=Tiramisu
     ASurfaceTransaction_setGeometry; # introduced=29
     ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index c2afc60..42f4406 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -619,6 +619,16 @@
     transaction->setFrameRate(surfaceControl, frameRate, compatibility, changeFrameRateStrategy);
 }
 
+void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* aSurfaceTransaction,
+                                        ASurfaceControl* aSurfaceControl) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    transaction->setFrameRate(surfaceControl, 0, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
+                              ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+}
+
 void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* aSurfaceTransaction,
                                                ASurfaceControl* aSurfaceControl,
                                                bool enableBackpressure) {