SF: store the render frame rate in RefreshRateConfigs::Policy

Add plumbing for the render frame rate passed from DM and update the
policy accordingly.

Test: SF unit tests
Bug: 241460058
Change-Id: I86088001d6d6e5302516f42aa5c9ede4a918dae1
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9c2ce0f..9e175ec 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2375,42 +2375,22 @@
     return NAME_NOT_FOUND;
 }
 
-status_t SurfaceComposerClient::setDesiredDisplayModeSpecs(
-        const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching,
-        float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
-        float appRequestRefreshRateMax) {
+status_t SurfaceComposerClient::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                                           const gui::DisplayModeSpecs& specs) {
     binder::Status status =
-            ComposerServiceAIDL::getComposerService()
-                    ->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching,
-                                                 primaryRefreshRateMin, primaryRefreshRateMax,
-                                                 appRequestRefreshRateMin,
-                                                 appRequestRefreshRateMax);
+            ComposerServiceAIDL::getComposerService()->setDesiredDisplayModeSpecs(displayToken,
+                                                                                  specs);
     return statusTFromBinderStatus(status);
 }
 
 status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
-                                                           ui::DisplayModeId* outDefaultMode,
-                                                           bool* outAllowGroupSwitching,
-                                                           float* outPrimaryRefreshRateMin,
-                                                           float* outPrimaryRefreshRateMax,
-                                                           float* outAppRequestRefreshRateMin,
-                                                           float* outAppRequestRefreshRateMax) {
-    if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
-        !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) {
+                                                           gui::DisplayModeSpecs* outSpecs) {
+    if (!outSpecs) {
         return BAD_VALUE;
     }
-    gui::DisplayModeSpecs specs;
     binder::Status status =
             ComposerServiceAIDL::getComposerService()->getDesiredDisplayModeSpecs(displayToken,
-                                                                                  &specs);
-    if (status.isOk()) {
-        *outDefaultMode = specs.defaultMode;
-        *outAllowGroupSwitching = specs.allowGroupSwitching;
-        *outPrimaryRefreshRateMin = specs.primaryRefreshRateMin;
-        *outPrimaryRefreshRateMax = specs.primaryRefreshRateMax;
-        *outAppRequestRefreshRateMin = specs.appRequestRefreshRateMin;
-        *outAppRequestRefreshRateMax = specs.appRequestRefreshRateMax;
-    }
+                                                                                  outSpecs);
     return statusTFromBinderStatus(status);
 }
 
diff --git a/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl
index fb4fcdf..af138c7 100644
--- a/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl
+++ b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl
@@ -18,10 +18,58 @@
 
 /** @hide */
 parcelable DisplayModeSpecs {
+    /**
+     * Defines the refresh rates ranges that should be used by SF.
+     */
+    parcelable RefreshRateRanges {
+        /**
+         * Defines a range of refresh rates.
+         */
+        parcelable RefreshRateRange {
+            float min;
+            float max;
+        }
+
+        /**
+         *  The range of refresh rates that the display should run at.
+         */
+        RefreshRateRange physical;
+
+        /**
+         *  The range of refresh rates that apps should render at.
+         */
+        RefreshRateRange render;
+    }
+
+    /**
+     * Base mode ID. This is what system defaults to for all other settings, or
+     * if the refresh rate range is not available.
+     */
     int defaultMode;
+
+    /**
+     * If true this will allow switching between modes in different display configuration
+     * groups. This way the user may see visual interruptions when the display mode changes.
+     */
+
     boolean allowGroupSwitching;
-    float primaryRefreshRateMin;
-    float primaryRefreshRateMax;
-    float appRequestRefreshRateMin;
-    float appRequestRefreshRateMax;
+
+    /**
+     * The primary physical and render refresh rate ranges represent DisplayManager's general
+     * guidance on the display modes SurfaceFlinger will consider when switching refresh
+     * rates and scheduling the frame rate. Unless SurfaceFlinger has a specific reason to do
+     * otherwise, it will stay within this range.
+     */
+    RefreshRateRanges primaryRanges;
+
+    /**
+     * The app request physical and render refresh rate ranges allow SurfaceFlinger to consider
+     * more display modes when switching refresh rates. Although SurfaceFlinger will
+     * generally stay within the primary range, specific considerations, such as layer frame
+     * rate settings specified via the setFrameRate() API, may cause SurfaceFlinger to go
+     * outside the primary range. SurfaceFlinger never goes outside the app request range.
+     * The app request range will be greater than or equal to the primary refresh rate range,
+     * never smaller.
+     */
+    RefreshRateRanges appRequestRanges;
 }
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 92d9e77..40410fb 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -327,25 +327,9 @@
     /**
      * Sets the refresh rate boundaries for the display.
      *
-     * The primary refresh rate range represents display manager's general guidance on the display
-     * modes we'll consider when switching refresh rates. Unless we get an explicit signal from an
-     * app, we should stay within this range.
-     *
-     * The app request refresh rate range allows us to consider more display modes when switching
-     * refresh rates. Although we should generally stay within the primary range, specific
-     * considerations, such as layer frame rate settings specified via the setFrameRate() api, may
-     * cause us to go outside the primary range. We never go outside the app request range. The app
-     * request range will be greater than or equal to the primary refresh rate range, never smaller.
-     *
-     * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider
-     * switching between. Only modes with a mode group and resolution matching defaultMode
-     * will be considered for switching. The defaultMode corresponds to an ID of mode in the list
-     * of supported modes returned from getDynamicDisplayInfo().
+     * @see DisplayModeSpecs.aidl for details.
      */
-    void setDesiredDisplayModeSpecs(
-            IBinder displayToken, int defaultMode,
-            boolean allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax,
-            float appRequestRefreshRateMin, float appRequestRefreshRateMax);
+    void setDesiredDisplayModeSpecs(IBinder displayToken, in DisplayModeSpecs specs);
 
     DisplayModeSpecs getDesiredDisplayModeSpecs(IBinder displayToken);
 
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
index 2025170..9d1ee8f 100644
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -127,9 +127,7 @@
     MOCK_METHOD(binder::Status, removeTunnelModeEnabledListener,
                 (const sp<gui::ITunnelModeEnabledListener>&), (override));
     MOCK_METHOD(binder::Status, setDesiredDisplayModeSpecs,
-                (const sp<IBinder>&, int32_t, bool, float, float, float,
-                 float appRequestRefreshRateMax),
-                (override));
+                (const sp<IBinder>&, const gui::DisplayModeSpecs&), (override));
     MOCK_METHOD(binder::Status, getDesiredDisplayModeSpecs,
                 (const sp<IBinder>&, gui::DisplayModeSpecs*), (override));
     MOCK_METHOD(binder::Status, getDisplayBrightnessSupport, (const sp<IBinder>&, bool*),
diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
index eecbe0f..57720dd 100644
--- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
+++ b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
@@ -123,10 +123,37 @@
     sp<SurfaceControl> makeSurfaceControl();
     BlurRegion getBlurRegion();
     void fuzzOnPullAtom();
+    gui::DisplayModeSpecs getDisplayModeSpecs();
 
     FuzzedDataProvider mFdp;
 };
 
+gui::DisplayModeSpecs SurfaceComposerClientFuzzer::getDisplayModeSpecs() {
+    const auto getRefreshRateRange = [&] {
+        gui::DisplayModeSpecs::RefreshRateRanges::RefreshRateRange range;
+        range.min = mFdp.ConsumeFloatingPoint<float>();
+        range.max = mFdp.ConsumeFloatingPoint<float>();
+        return range;
+    };
+
+    const auto getRefreshRateRanges = [&] {
+        gui::DisplayModeSpecs::RefreshRateRanges ranges;
+        ranges.physical = getRefreshRateRange();
+        ranges.render = getRefreshRateRange();
+        return ranges;
+    };
+
+    String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str());
+    sp<IBinder> displayToken =
+            SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/);
+    gui::DisplayModeSpecs specs;
+    specs.defaultMode = mFdp.ConsumeIntegral<int32_t>();
+    specs.allowGroupSwitching = mFdp.ConsumeBool();
+    specs.primaryRanges = getRefreshRateRanges();
+    specs.appRequestRanges = getRefreshRateRanges();
+    return specs;
+}
+
 BlurRegion SurfaceComposerClientFuzzer::getBlurRegion() {
     int32_t left = mFdp.ConsumeIntegral<int32_t>();
     int32_t right = mFdp.ConsumeIntegral<int32_t>();
@@ -247,12 +274,7 @@
     String8 displayName((mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes)).c_str());
     sp<IBinder> displayToken =
             SurfaceComposerClient::createDisplay(displayName, mFdp.ConsumeBool() /*secure*/);
-    SurfaceComposerClient::setDesiredDisplayModeSpecs(displayToken, mFdp.ConsumeIntegral<int32_t>(),
-                                                      mFdp.ConsumeBool() /*allowGroupSwitching*/,
-                                                      mFdp.ConsumeFloatingPoint<float>(),
-                                                      mFdp.ConsumeFloatingPoint<float>(),
-                                                      mFdp.ConsumeFloatingPoint<float>(),
-                                                      mFdp.ConsumeFloatingPoint<float>());
+    SurfaceComposerClient::setDesiredDisplayModeSpecs(displayToken, getDisplayModeSpecs());
 
     ui::ColorMode colorMode = mFdp.PickValueInArray(kColormodes);
     SurfaceComposerClient::setActiveColorMode(displayToken, colorMode);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index c450e85..2038f14 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -159,18 +159,11 @@
     static status_t getActiveDisplayMode(const sp<IBinder>& display, ui::DisplayMode*);
 
     // Sets the refresh rate boundaries for the display.
-    static status_t setDesiredDisplayModeSpecs(
-            const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode,
-            bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax,
-            float appRequestRefreshRateMin, float appRequestRefreshRateMax);
+    static status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+                                               const gui::DisplayModeSpecs&);
     // Gets the refresh rate boundaries for the display.
     static status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
-                                               ui::DisplayModeId* outDefaultMode,
-                                               bool* outAllowGroupSwitching,
-                                               float* outPrimaryRefreshRateMin,
-                                               float* outPrimaryRefreshRateMax,
-                                               float* outAppRequestRefreshRateMin,
-                                               float* outAppRequestRefreshRateMax);
+                                               gui::DisplayModeSpecs*);
 
     // Get the coordinates of the display's native color primaries
     static status_t getDisplayNativePrimaries(const sp<IBinder>& display,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 346b686..67c669d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -920,16 +920,12 @@
     }
 
     binder::Status setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
-                                              int32_t /*defaultMode*/, bool /*allowGroupSwitching*/,
-                                              float /*primaryRefreshRateMin*/,
-                                              float /*primaryRefreshRateMax*/,
-                                              float /*appRequestRefreshRateMin*/,
-                                              float /*appRequestRefreshRateMax*/) override {
+                                              const gui::DisplayModeSpecs&) override {
         return binder::Status::ok();
     }
 
     binder::Status getDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
-                                              gui::DisplayModeSpecs* /*outSpecs*/) override {
+                                              gui::DisplayModeSpecs*) override {
         return binder::Status::ok();
     }