Add a support for synthetic mode with hasArrSupport

BUG: 361433651
Flag: com.android.server.display.feature.flags.enable_has_arr_support
Test: atest DisplayServiceTests
Change-Id: I0a116ca3fa43bbd8101b4ec12d4267efb7faad3f
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 1d90c29..074a4d8 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -512,7 +512,7 @@
             mBaseDisplayInfo.supportedModes = Arrays.copyOf(
                     deviceInfo.supportedModes, deviceInfo.supportedModes.length);
             mBaseDisplayInfo.appsSupportedModes = syntheticModeManager.createAppSupportedModes(
-                    config, mBaseDisplayInfo.supportedModes
+                    config, mBaseDisplayInfo.supportedModes, mBaseDisplayInfo.hasArrSupport
             );
             mBaseDisplayInfo.colorMode = deviceInfo.colorMode;
             mBaseDisplayInfo.supportedColorModes = Arrays.copyOf(
diff --git a/services/core/java/com/android/server/display/mode/SyntheticModeManager.java b/services/core/java/com/android/server/display/mode/SyntheticModeManager.java
index a83b939..71b34679 100644
--- a/services/core/java/com/android/server/display/mode/SyntheticModeManager.java
+++ b/services/core/java/com/android/server/display/mode/SyntheticModeManager.java
@@ -37,17 +37,22 @@
             SYNTHETIC_MODE_REFRESH_RATE + FLOAT_TOLERANCE;
 
     private final boolean mSynthetic60HzModesEnabled;
+    private final boolean mHasArrSupportEnabled;
 
     public SyntheticModeManager(DisplayManagerFlags flags) {
         mSynthetic60HzModesEnabled = flags.isSynthetic60HzModesEnabled();
+        mHasArrSupportEnabled = flags.hasArrSupportFlag();
     }
 
     /**
      * creates display supportedModes array, exposed to applications
      */
     public Display.Mode[] createAppSupportedModes(DisplayDeviceConfig config,
-            Display.Mode[] modes) {
-        if (!config.isVrrSupportEnabled() || !mSynthetic60HzModesEnabled) {
+            Display.Mode[] modes, boolean hasArrSupport) {
+        // TODO(b/361433651) Remove config.isVrrSupportEnabled once hasArrSupport is rolled out
+        boolean isArrSupported =
+                mHasArrSupportEnabled ? hasArrSupport : config.isVrrSupportEnabled();
+        if (!isArrSupported || !mSynthetic60HzModesEnabled) {
             return modes;
         }
         List<Display.Mode> appSupportedModes = new ArrayList<>();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 1729ad5..d40f4d4 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -51,6 +51,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
@@ -207,8 +208,8 @@
         when(mResourcesMock.getIntArray(
                 com.android.internal.R.array.config_deviceStatesOnWhichToSleep))
                 .thenReturn(new int[]{0});
-        when(mSyntheticModeManagerMock.createAppSupportedModes(any(), any())).thenAnswer(
-                AdditionalAnswers.returnsSecondArg());
+        when(mSyntheticModeManagerMock.createAppSupportedModes(any(), any(), anyBoolean()))
+                .thenAnswer(AdditionalAnswers.returnsSecondArg());
 
         when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(false);
         mLooper = new TestLooper();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayTest.java
index 8936f06..b002a1f 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
@@ -87,7 +88,7 @@
         mDisplayDeviceInfo.supportedModes = new Display.Mode[] {new Display.Mode(MODE_ID,
                 DISPLAY_WIDTH, DISPLAY_HEIGHT, /* refreshRate= */ 60)};
         when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(mDisplayDeviceInfo);
-        when(mSyntheticModeManager.createAppSupportedModes(any(), any())).thenAnswer(
+        when(mSyntheticModeManager.createAppSupportedModes(any(), any(), anyBoolean())).thenAnswer(
                 AdditionalAnswers.returnsSecondArg());
 
         // Disable binder caches in this process.
@@ -582,7 +583,8 @@
         Display.Mode[] appSupportedModes = new Display.Mode[] {new Display.Mode(OTHER_MODE_ID,
                 DISPLAY_WIDTH, DISPLAY_HEIGHT, /* refreshRate= */ 45)};
         when(mSyntheticModeManager.createAppSupportedModes(
-                any(), eq(mDisplayDeviceInfo.supportedModes))).thenReturn(appSupportedModes);
+                any(), eq(mDisplayDeviceInfo.supportedModes), anyBoolean()))
+                .thenReturn(appSupportedModes);
 
         mLogicalDisplay.updateLocked(mDeviceRepo, mSyntheticModeManager);
         DisplayInfo info = mLogicalDisplay.getDisplayInfoLocked();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/SyntheticModeManagerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/SyntheticModeManagerTest.kt
index b2d83d7..9a93fba 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/SyntheticModeManagerTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/SyntheticModeManagerTest.kt
@@ -43,35 +43,42 @@
     @Test
     fun testAppSupportedModes(@TestParameter testCase: AppSupportedModesTestCase) {
         whenever(mockFlags.isSynthetic60HzModesEnabled).thenReturn(testCase.syntheticModesEnabled)
+        whenever(mockFlags.hasArrSupportFlag()).thenReturn(testCase.hasArrSupport)
         whenever(mockConfig.isVrrSupportEnabled).thenReturn(testCase.vrrSupported)
         val syntheticModeManager = SyntheticModeManager(mockFlags)
 
         val result = syntheticModeManager.createAppSupportedModes(
-            mockConfig, testCase.supportedModes)
+            mockConfig, testCase.supportedModes, testCase.hasArrSupport)
 
         assertThat(result).isEqualTo(testCase.expectedAppModes)
     }
 
+    // TODO(b/361433651) Remove vrrSupported once hasArrSupport is rolled out
     enum class AppSupportedModesTestCase(
         val syntheticModesEnabled: Boolean,
         val vrrSupported: Boolean,
+        val hasArrSupport: Boolean,
         val supportedModes: Array<Mode>,
         val expectedAppModes: Array<Mode>
     ) {
-        SYNTHETIC_MODES_NOT_SUPPORTED(false, true, DISPLAY_MODES, DISPLAY_MODES),
-        VRR_NOT_SUPPORTED(true, false, DISPLAY_MODES, DISPLAY_MODES),
-        VRR_SYNTHETIC_NOT_SUPPORTED(false, false, DISPLAY_MODES, DISPLAY_MODES),
-        SINGLE_RESOLUTION_MODES(true, true, DISPLAY_MODES, arrayOf(
+        SYNTHETIC_MODES_NOT_SUPPORTED(false, true, true, DISPLAY_MODES, DISPLAY_MODES),
+        VRR_NOT_SUPPORTED(true, false, false, DISPLAY_MODES, DISPLAY_MODES),
+        VRR_SYNTHETIC_NOT_SUPPORTED(false, false, false, DISPLAY_MODES, DISPLAY_MODES),
+        SINGLE_RESOLUTION_MODES(true, true, true, DISPLAY_MODES, arrayOf(
             Mode(2, 100, 100, 120f),
             Mode(3, 100, 100, 60f, 60f, true, floatArrayOf(), intArrayOf())
         )),
-        NO_60HZ_MODES(true, true, arrayOf(Mode(2, 100, 100, 120f)),
+        SINGLE_RESOLUTION_MODES_HASARR(true, false, true, DISPLAY_MODES, arrayOf(
+            Mode(2, 100, 100, 120f),
+            Mode(3, 100, 100, 60f, 60f, true, floatArrayOf(), intArrayOf())
+        )),
+        NO_60HZ_MODES(true, true, true, arrayOf(Mode(2, 100, 100, 120f)),
             arrayOf(
                 Mode(2, 100, 100, 120f),
                 Mode(3, 100, 100, 60f, 60f, true, floatArrayOf(), intArrayOf())
             )
         ),
-        MULTI_RESOLUTION_MODES(true, true,
+        MULTI_RESOLUTION_MODES(true, true, true,
             arrayOf(
                 Mode(1, 100, 100, 120f),
                 Mode(2, 200, 200, 60f),
@@ -86,7 +93,7 @@
                 Mode(7, 300, 300, 60f, 60f, true, floatArrayOf(), intArrayOf())
             )
         ),
-        WITH_HDR_TYPES(true, true,
+        WITH_HDR_TYPES(true, true, true,
             arrayOf(
                 Mode(1, 100, 100, 120f, 120f, false, floatArrayOf(), intArrayOf(1, 2)),
                 Mode(2, 200, 200, 60f, 120f, false, floatArrayOf(), intArrayOf(3, 4)),
@@ -99,7 +106,7 @@
                 Mode(5, 200, 200, 60f, 60f, true, floatArrayOf(), intArrayOf(5, 6)),
             )
         ),
-        UNACHIEVABLE_60HZ(true, true,
+        UNACHIEVABLE_60HZ(true, true, true,
             arrayOf(
                 Mode(1, 100, 100, 90f),
             ),
@@ -107,7 +114,7 @@
                 Mode(1, 100, 100, 90f),
             )
         ),
-        MULTI_RESOLUTION_MODES_WITH_UNACHIEVABLE_60HZ(true, true,
+        MULTI_RESOLUTION_MODES_WITH_UNACHIEVABLE_60HZ(true, true, true,
             arrayOf(
                 Mode(1, 100, 100, 120f),
                 Mode(2, 200, 200, 90f),
@@ -118,7 +125,7 @@
                 Mode(3, 100, 100, 60f, 60f, true, floatArrayOf(), intArrayOf()),
             )
         ),
-        LOWER_THAN_60HZ_MODES(true, true,
+        LOWER_THAN_60HZ_MODES(true, true, true,
             arrayOf(
                 Mode(1, 100, 100, 30f),
                 Mode(2, 100, 100, 45f),