Add new ANativeWindow_setFrameRateParams API

The new overload uses same plumbing and same logic as the other
setFrameRate-like functions. This plumbing and logic will be upgraded to
accommodate new parameters in a future CL.

Bug: 362798998
Test: atest SetFrameRateTest
Flag: EXEMPT NDK
Change-Id: If29c32a92b48c36fe06c70db5505f73cea482637
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index f97eed5..ac3a832 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -263,6 +263,16 @@
     return native_window_set_frame_rate(window, frameRate, compatibility, changeFrameRateStrategy);
 }
 
+int32_t ANativeWindow_setFrameRateParams(
+        ANativeWindow* window, float desiredMinRate, float desiredMaxRate, float fixedSourceRate,
+        ANativeWindow_ChangeFrameRateStrategy changeFrameRateStrategy) {
+    if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) {
+        return -EINVAL;
+    }
+    return native_window_set_frame_rate_params(window, desiredMinRate, desiredMaxRate,
+                                               fixedSourceRate, changeFrameRateStrategy);
+}
+
 /**************************************************************************************************
  * vndk-stable
  **************************************************************************************************/
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index be6623e..c53d11e 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -33,8 +33,8 @@
 #ifndef ANDROID_NATIVE_WINDOW_H
 #define ANDROID_NATIVE_WINDOW_H
 
-#include <stdint.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <sys/cdefs.h>
 
 #include <android/data_space.h>
@@ -282,7 +282,7 @@
 void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) __INTRODUCED_IN(30);
 
 /** Change frame rate strategy value for ANativeWindow_setFrameRate. */
-enum ANativeWindow_ChangeFrameRateStrategy {
+typedef enum ANativeWindow_ChangeFrameRateStrategy : int8_t {
     /**
      * Change the frame rate only if the transition is going to be seamless.
      */
@@ -292,7 +292,7 @@
      * i.e. with visual interruptions for the user.
      */
     ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS = 1
-} __INTRODUCED_IN(31);
+} ANativeWindow_ChangeFrameRateStrategy __INTRODUCED_IN(31);
 
 /**
  * Sets the intended frame rate for this window.
@@ -345,6 +345,76 @@
         __INTRODUCED_IN(31);
 
 /**
+ * Sets the intended frame rate for this window.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You can register for changes in the refresh rate using
+ * \a AChoreographer_registerRefreshRateCallback.
+ *
+ * See ANativeWindow_clearFrameRate().
+ *
+ * Available since API level 36.
+ *
+ * \param window pointer to an ANativeWindow object.
+ *
+ * \param desiredMinRate The desired minimum frame rate (inclusive) for the window, specifying that
+ * the surface prefers the device render rate to be at least `desiredMinRate`.
+ *
+ * <p>Set `desiredMinRate` = `desiredMaxRate` to indicate the surface prefers an exact frame rate.
+ *
+ * <p>Set `desiredMinRate` = 0 to indicate the window has no preference
+ * and any frame rate is acceptable.
+ *
+ * <p>The value should be greater than or equal to 0.
+ *
+ * \param desiredMaxRate The desired maximum frame rate (inclusive) for the window, specifying that
+ * the surface prefers the device render rate to be at most `desiredMaxRate`.
+ *
+ * <p>Set `desiredMaxRate` = `desiredMinRate` to indicate the surface prefers an exact frame rate.
+ *
+ * <p>Set `desiredMaxRate` = positive infinity to indicate the window has no preference
+ * and any frame rate is acceptable.
+ *
+ * <p>The value should be greater than or equal to `desiredMinRate`.
+ *
+ * \param fixedSourceRate The "fixed source" frame rate of the window if the content has an
+ * inherently fixed frame rate, e.g. a video that has a specific frame rate.
+ *
+ * <p>When the frame rate chosen for the surface is the `fixedSourceRate` or a
+ * multiple, the surface can render without frame pulldown, for optimal smoothness. For
+ * example, a 30 fps video (`fixedSourceRate`=30) renders just as smoothly on 30 fps,
+ * 60 fps, 90 fps, 120 fps, and so on.
+ *
+ * <p>Setting the fixed source rate can also be used together with a desired
+ * frame rate min and max via setting `desiredMinRate` and `desiredMaxRate`. This still
+ * means the window's content has a fixed frame rate of `fixedSourceRate`, but additionally
+ * specifies the preference to be in the range [`desiredMinRate`, `desiredMaxRate`]. For example, an
+ * app might want to specify there is 30 fps video (`fixedSourceRate`=30) as well as a smooth
+ * animation on the same window which looks good when drawing within a frame rate range such as
+ * [`desiredMinRate`, `desiredMaxRate`] = [60,120].
+ *
+ * \param changeFrameRateStrategy 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.
+ *
+ * \return 0 for success, -EINVAL if the arguments are invalid.
+ */
+int32_t ANativeWindow_setFrameRateParams(
+        ANativeWindow* window, float desiredMinRate, float desiredMaxRate, float fixedSourceRate,
+        ANativeWindow_ChangeFrameRateStrategy changeFrameRateStrategy) __INTRODUCED_IN(36);
+
+/**
  * Clears the frame rate which is set for this window.
  *
  * This is equivalent to calling
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 33c303a..05f49ad 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1156,6 +1156,23 @@
                            (int)compatibility, (int)changeFrameRateStrategy);
 }
 
+static inline int native_window_set_frame_rate_params(struct ANativeWindow* window,
+                                                      float desiredMinRate, float desiredMaxRate,
+                                                      float fixedSourceRate,
+                                                      int8_t changeFrameRateStrategy) {
+    // TODO(b/362798998): Fix plumbing to send whole params
+    int compatibility = fixedSourceRate == 0 ? ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT
+                                             : ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
+    double frameRate = compatibility == ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
+            ? fixedSourceRate
+            : desiredMinRate;
+    if (desiredMaxRate < desiredMinRate) {
+        return -EINVAL;
+    }
+    return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, frameRate, compatibility,
+                           changeFrameRateStrategy);
+}
+
 struct ANativeWindowFrameTimelineInfo {
     // Frame Id received from ANativeWindow_getNextFrameId.
     uint64_t frameNumber;
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index e29d5a6..071e354 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -53,6 +53,7 @@
     ANativeWindow_setBuffersTransform;
     ANativeWindow_setDequeueTimeout; # systemapi introduced=30
     ANativeWindow_setFrameRate; # introduced=30
+    ANativeWindow_setFrameRateParams; # introduced=36
     ANativeWindow_setFrameRateWithChangeStrategy; # introduced=31
     ANativeWindow_setSharedBufferMode; # llndk
     ANativeWindow_setSwapInterval; # llndk