Follow config overlay's order of aspect ratio options

Fix flaky UserAspectRatioAppsPageProviderTest by using advanceUntilIdle
to make sure all coroutines are finished before asserting.

Bug: 325911424
Test: atest UserAspectRatioDetailsTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:32815ad699448c5c5b1f38df6d2d2a881d4251c1)
Merged-In: I83e9a7f31536c1a006789722b0310f3364d14337
Change-Id: I83e9a7f31536c1a006789722b0310f3364d14337
diff --git a/res/xml/user_aspect_ratio_details.xml b/res/xml/user_aspect_ratio_details.xml
index 44a7589..24c3271 100644
--- a/res/xml/user_aspect_ratio_details.xml
+++ b/res/xml/user_aspect_ratio_details.xml
@@ -28,7 +28,8 @@
         settings:searchable="false"/>
 
     <com.android.settingslib.widget.ActionButtonsPreference
-        android:key="header_view" />
+        android:key="header_view"
+        android:order="-999"/>
 
     <com.android.settings.applications.appcompat.RadioWithImagePreference
         android:key="app_default_pref"
diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java b/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java
index ef054df..cbc5a7b 100644
--- a/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java
+++ b/src/com/android/settings/applications/appcompat/UserAspectRatioDetails.java
@@ -66,7 +66,8 @@
     private static final String TAG = UserAspectRatioDetails.class.getSimpleName();
 
     private static final String KEY_HEADER_SUMMARY = "app_aspect_ratio_summary";
-    private static final String KEY_HEADER_BUTTONS = "header_view";
+    @VisibleForTesting
+    static final String KEY_HEADER_BUTTONS = "header_view";
 
     private static final String KEY_PREF_HALF_SCREEN = "half_screen_pref";
     private static final String KEY_PREF_DISPLAY_SIZE = "display_size_pref";
@@ -237,6 +238,7 @@
             return;
         }
         pref.setTitle(mUserAspectRatioManager.getAccessibleEntry(aspectRatio, mPackageName));
+        pref.setOrder(getAspectRatioManager().getUserMinAspectRatioOrder(aspectRatio));
         pref.setOnClickListener(this);
         mKeyToAspectRatioMap.put(key, aspectRatio);
         mAspectRatioPreferences.add(pref);
diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
index 3bf6109..0550a9a 100644
--- a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
+++ b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
@@ -44,6 +44,7 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
+import android.util.SparseIntArray;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -76,6 +77,7 @@
     /** Apps that have launcher entry defined in manifest */
     private final Map<Integer, String> mUserAspectRatioMap;
     private final Map<Integer, CharSequence> mUserAspectRatioA11yMap;
+    private final SparseIntArray mUserAspectRatioOrder;
 
     public UserAspectRatioManager(@NonNull Context context) {
         this(context, AppGlobals.getPackageManager());
@@ -86,6 +88,7 @@
         mContext = context;
         mIPm = pm;
         mUserAspectRatioA11yMap = new ArrayMap<>();
+        mUserAspectRatioOrder = new SparseIntArray();
         mUserAspectRatioMap = getUserMinAspectRatioMapping();
     }
 
@@ -153,6 +156,14 @@
     }
 
     /**
+     * @return the order of the aspect ratio option corresponding to
+     * config_userAspectRatioOverrideValues
+     */
+    int getUserMinAspectRatioOrder(@PackageManager.UserMinAspectRatio int option) {
+        return mUserAspectRatioOrder.get(option);
+    }
+
+    /**
      * Whether user aspect ratio option is specified in
      * {@link R.array.config_userAspectRatioOverrideValues}
      * and is enabled by device config
@@ -224,7 +235,6 @@
                 && isFullscreenCompatChangeEnabled(pkgName, userId);
     }
 
-    @VisibleForTesting
     boolean isFullscreenCompatChangeEnabled(String pkgName, int userId) {
         return CompatChanges.isChangeEnabled(
                 OVERRIDE_ANY_ORIENTATION_TO_USER, pkgName, UserHandle.of(userId));
@@ -281,6 +291,7 @@
                         mUserAspectRatioA11yMap.put(aspectRatioVal, accessibleSequence);
                     }
                     userMinAspectRatioMap.put(aspectRatioVal, aspectRatioString);
+                    mUserAspectRatioOrder.put(aspectRatioVal, i);
             }
         }
         if (!userMinAspectRatioMap.containsKey(USER_MIN_ASPECT_RATIO_UNSET)) {
@@ -290,6 +301,8 @@
         if (mIsUserMinAspectRatioAppDefaultFlagEnabled) {
             userMinAspectRatioMap.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
                     userMinAspectRatioMap.get(USER_MIN_ASPECT_RATIO_UNSET));
+            mUserAspectRatioOrder.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
+                    mUserAspectRatioOrder.get(USER_MIN_ASPECT_RATIO_UNSET));
             if (mUserAspectRatioA11yMap.containsKey(USER_MIN_ASPECT_RATIO_UNSET)) {
                 mUserAspectRatioA11yMap.put(USER_MIN_ASPECT_RATIO_APP_DEFAULT,
                         mUserAspectRatioA11yMap.get(USER_MIN_ASPECT_RATIO_UNSET));
diff --git a/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt b/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt
index 15cd1ba..3241d71 100644
--- a/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt
+++ b/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProvider.kt
@@ -62,6 +62,7 @@
 import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.android.settingslib.spaprivileged.template.app.AppListPage
 import com.google.common.annotations.VisibleForTesting
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
@@ -130,8 +131,10 @@
     val canDisplay: Boolean,
 ) : AppRecord
 
-class UserAspectRatioAppListModel(private val context: Context)
-    : AppListModel<UserAspectRatioAppListItemModel> {
+class UserAspectRatioAppListModel(
+    private val context: Context,
+    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
+) : AppListModel<UserAspectRatioAppListItemModel> {
 
     private val packageManager = context.packageManager
     private val userAspectRatioManager = UserAspectRatioManager(context)
@@ -203,7 +206,7 @@
             flow {
                 emit(userAspectRatioManager.getUserMinAspectRatioEntry(record.userOverride,
                     record.app.packageName, record.app.userId))
-            }.flowOn(Dispatchers.IO)
+            }.flowOn(ioDispatcher)
         }.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder))
         return { summary }
     }
diff --git a/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java
index f3b105b..ce03a6d 100644
--- a/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appcompat/UserAspectRatioDetailsTest.java
@@ -16,16 +16,19 @@
 
 package com.android.settings.applications.appcompat;
 
+import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
 import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT;
 import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_FULLSCREEN;
 import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_UNSET;
 
 import static com.android.settings.applications.AppInfoBase.ARG_PACKAGE_NAME;
+import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_HEADER_BUTTONS;
 import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_3_2;
 import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_DEFAULT;
 import static com.android.settings.applications.appcompat.UserAspectRatioDetails.KEY_PREF_FULLSCREEN;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -99,6 +102,31 @@
     }
 
     @Test
+    public void testOrderOfOptionsFollowsConfig() {
+        doReturn(true).when(mUserAspectRatioManager)
+                .hasAspectRatioOption(anyInt(), anyString());
+        doReturn(0).when(mUserAspectRatioManager)
+                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_3_2);
+        doReturn(1).when(mUserAspectRatioManager)
+                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_FULLSCREEN);
+        doReturn(2).when(mUserAspectRatioManager)
+                .getUserMinAspectRatioOrder(USER_MIN_ASPECT_RATIO_UNSET);
+        rule.getScenario().onActivity(a -> doReturn(a).when(mFragment).getActivity());
+        final Bundle args = new Bundle();
+        args.putString(ARG_PACKAGE_NAME, anyString());
+        mFragment.setArguments(args);
+        mFragment.onCreate(Bundle.EMPTY);
+
+        final int topOfList = mFragment.findPreference(KEY_HEADER_BUTTONS).getOrder();
+
+        assertTrue(topOfList < mFragment.findPreference(KEY_PREF_3_2).getOrder());
+        assertTrue(mFragment.findPreference(KEY_PREF_3_2).getOrder()
+                < mFragment.findPreference(KEY_PREF_FULLSCREEN).getOrder());
+        assertTrue(mFragment.findPreference(KEY_PREF_FULLSCREEN).getOrder()
+                < mFragment.findPreference(KEY_PREF_DEFAULT).getOrder());
+    }
+
+    @Test
     public void onRadioButtonClicked_prefChange_shouldStopActivity() throws RemoteException {
         doReturn(USER_MIN_ASPECT_RATIO_UNSET).when(mFragment)
                 .getSelectedUserMinAspectRatio(anyString());
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt
index dfacca8..b859df4 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppsPageProviderTest.kt
@@ -32,7 +32,11 @@
 import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
 import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
 import kotlinx.coroutines.test.runTest
 import org.junit.Rule
 import org.junit.Test
@@ -45,6 +49,8 @@
 class UserAspectRatioAppsPageProviderTest {
     @get:Rule
     val composeTestRule = createComposeRule()
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
 
     private val context: Context = ApplicationProvider.getApplicationContext()
     private val fakeNavControllerWrapper = FakeNavControllerWrapper()
@@ -137,33 +143,37 @@
         }
     }
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
-    fun aspectRatioAppListModel_getSummaryDefault() {
-        val summary = getSummary(USER_MIN_ASPECT_RATIO_UNSET)
+    fun aspectRatioAppListModel_getSummaryDefault() = testScope.runTest {
+        val summary = setSummary(USER_MIN_ASPECT_RATIO_UNSET)
+        advanceUntilIdle()
 
-        assertThat(summary).isEqualTo(context.getString(R.string.user_aspect_ratio_app_default))
+        assertThat(summary()).isEqualTo(context.getString(R.string.user_aspect_ratio_app_default))
     }
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     @Test
-    fun aspectRatioAppListModel_getSummaryWhenSplitScreen() {
-        val summary = getSummary(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN)
+    fun aspectRatioAppListModel_getSummaryWhenSplitScreen() = testScope.runTest {
+        val summary = setSummary(USER_MIN_ASPECT_RATIO_SPLIT_SCREEN)
+        advanceUntilIdle()
 
-        assertThat(summary).isEqualTo(context.getString(R.string.user_aspect_ratio_half_screen))
+        assertThat(summary()).isEqualTo(context.getString(R.string.user_aspect_ratio_half_screen))
     }
 
-    private fun getSummary(userOverride: Int): String {
-        val listModel = UserAspectRatioAppListModel(context)
+    private fun setSummary(userOverride: Int): () -> String {
+        val listModel = UserAspectRatioAppListModel(context, testDispatcher)
+        val record = UserAspectRatioAppListItemModel(
+            app = APP,
+            userOverride = userOverride,
+            suggested = false,
+            canDisplay = true,
+        )
         lateinit var summary: () -> String
         composeTestRule.setContent {
-            summary = listModel.getSummary(option = 0,
-                record = UserAspectRatioAppListItemModel(
-                    app = APP,
-                    userOverride = userOverride,
-                    suggested = false,
-                    canDisplay = true,
-                ))
+            summary =  listModel.getSummary(option = 0, record = record)
         }
-        return summary()
+        return summary
     }