Use old getSelectableSubscriptionInfoList

24D1-dev was using the
SubscriptionUtil.getSelectableSubscriptionInfoList().

Change I215b5a4615a3b3da6fc160f76c85c814210cc3ef cherry-pick the new
getSelectableSubscriptionInfoList from main, but not the latest version,
could produce an unexpected subscription order.

Main branch already fixed by I06b6c61304f9e6c9515b5f989294417ac3f82a60
and If7150bd2fa5c1b7d42fe34ef2e814ba540454ed8.

Fix: 341037896
Test: manual - on Mobile Settings
Merged-In: I06b6c61304f9e6c9515b5f989294417ac3f82a60
Change-Id: I5cb16b60a7bf5df5b048e539f89bfedc43aa1582
diff --git a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
index df3b8ba..1a83874 100644
--- a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
+++ b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
@@ -20,7 +20,6 @@
 import android.telephony.SubscriptionManager
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.viewModelScope
-import com.android.settings.network.telephony.getSelectableSubscriptionInfoList
 import com.android.settings.network.telephony.subscriptionsChangedFlow
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.SharingStarted
@@ -46,6 +45,6 @@
      * getAvailableSubscriptionInfoList
      */
     val selectableSubscriptionInfoListFlow = application.subscriptionsChangedFlow().map {
-        application.getSelectableSubscriptionInfoList()
+        SubscriptionUtil.getSelectableSubscriptionInfoList(application)
     }.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
 }
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index a379856..a9c4ac5 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -50,12 +50,12 @@
 import com.android.settings.network.helper.SubscriptionAnnotation;
 import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
 import com.android.settings.network.telephony.EuiccRacConnectivityDialogActivity;
-import com.android.settings.network.telephony.SubscriptionRepositoryKt;
 import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -507,7 +507,40 @@
      * @return list of user selectable subscriptions.
      */
     public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) {
-        return SubscriptionRepositoryKt.getSelectableSubscriptionInfoList(context);
+        SubscriptionManager subManager = context.getSystemService(SubscriptionManager.class);
+        List<SubscriptionInfo> availableList = subManager.getAvailableSubscriptionInfoList();
+        if (availableList == null) {
+            return null;
+        } else {
+            // Multiple subscriptions in a group should only have one representative.
+            // It should be the current active primary subscription if any, or any
+            // primary subscription.
+            List<SubscriptionInfo> selectableList = new ArrayList<>();
+            Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>();
+
+            for (SubscriptionInfo info : availableList) {
+                // Opportunistic subscriptions are considered invisible
+                // to users so they should never be returned.
+                if (!isSubscriptionVisible(subManager, context, info)) continue;
+
+                ParcelUuid groupUuid = info.getGroupUuid();
+                if (groupUuid == null) {
+                    // Doesn't belong to any group. Add in the list.
+                    selectableList.add(info);
+                } else if (!groupMap.containsKey(groupUuid)
+                        || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX
+                        && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) {
+                    // If it belongs to a group that has never been recorded or it's the current
+                    // active subscription, add it in the list.
+                    selectableList.remove(groupMap.get(groupUuid));
+                    selectableList.add(info);
+                    groupMap.put(groupUuid, info);
+                }
+
+            }
+            Log.d(TAG, "getSelectableSubscriptionInfoList: " + selectableList);
+            return selectableList;
+        }
     }
 
     /**
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
index f89a0db..4c13d98 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
+++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.kt
@@ -67,7 +67,7 @@
     }
 
     private fun Context.isVisible(): Boolean {
-        val subInfo = subscriptionRepository.getSelectableSubscriptionInfoList()
+        val subInfo = SubscriptionUtil.getAvailableSubscriptions(this)
             .firstOrNull { it.subscriptionId == subId }
             ?: return false
         // For eSIM, we always want the toggle. If telephony stack support disabling a pSIM
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index 8aee297..db5216a 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -20,9 +20,7 @@
 import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
 import android.util.Log
-import androidx.lifecycle.LifecycleOwner
 import com.android.settings.network.SubscriptionUtil
-import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.asExecutor
 import kotlinx.coroutines.channels.awaitClose
@@ -36,14 +34,6 @@
 private const val TAG = "SubscriptionRepository"
 
 class SubscriptionRepository(private val context: Context) {
-    /**
-     * Return a list of subscriptions that are available and visible to the user.
-     *
-     * @return list of user selectable subscriptions.
-     */
-    fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> =
-        context.getSelectableSubscriptionInfoList()
-
     fun isSubscriptionEnabledFlow(subId: Int) = context.isSubscriptionEnabledFlow(subId)
 }
 
@@ -77,36 +67,3 @@
 
     awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(listener) }
 }.conflate().onEach { Log.d(TAG, "subscriptions changed") }.flowOn(Dispatchers.Default)
-
-/**
- * Return a list of subscriptions that are available and visible to the user.
- *
- * @return list of user selectable subscriptions.
- */
-fun Context.getSelectableSubscriptionInfoList(): List<SubscriptionInfo> {
-    val subscriptionManager = requireSubscriptionManager()
-    val availableList = subscriptionManager.getAvailableSubscriptionInfoList() ?: return emptyList()
-    val visibleList = availableList.filter { subInfo ->
-        // Opportunistic subscriptions are considered invisible
-        // to users so they should never be returned.
-        SubscriptionUtil.isSubscriptionVisible(subscriptionManager, this, subInfo)
-    }
-    // Multiple subscriptions in a group should only have one representative.
-    // It should be the current active primary subscription if any, or any primary subscription.
-    val groupUuidToSelectedIdMap = visibleList
-        .groupBy { it.groupUuid }
-        .mapValues { (_, subInfos) ->
-            subInfos.filter { it.simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX }
-                .ifEmpty { subInfos }
-                .minOf { it.subscriptionId }
-        }
-
-    return visibleList
-        .filter { subInfo ->
-            val groupUuid = subInfo.groupUuid ?: return@filter true
-            groupUuidToSelectedIdMap[groupUuid] == subInfo.subscriptionId
-        }
-        .sortedBy { it.subscriptionId }
-        .also { Log.d(TAG, "getSelectableSubscriptionInfoList: $it") }
-}
-
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt
index e731333..77724e8 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.kt
@@ -30,8 +30,11 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settings.R
+import com.android.settings.network.SubscriptionUtil
 import com.android.settingslib.spa.testutils.waitUntilExists
 import kotlinx.coroutines.flow.flowOf
+import org.junit.After
+import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -58,7 +61,6 @@
     }
 
     private val mockSubscriptionRepository = mock<SubscriptionRepository> {
-        on { getSelectableSubscriptionInfoList() } doReturn listOf(SubInfo)
         on { isSubscriptionEnabledFlow(SUB_ID) } doReturn flowOf(false)
     }
 
@@ -68,6 +70,16 @@
         subscriptionRepository = mockSubscriptionRepository,
     ).apply { init(SUB_ID) }
 
+    @Before
+    fun setUp() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(SubInfo))
+    }
+
+    @After
+    fun tearDown() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(null)
+    }
+
     @Test
     fun isVisible_pSimAndCanDisablePhysicalSubscription_returnTrue() {
         val pSimSubInfo = SubscriptionInfo.Builder().apply {
@@ -77,9 +89,7 @@
         mockSubscriptionManager.stub {
             on { canDisablePhysicalSubscription() } doReturn true
         }
-        mockSubscriptionRepository.stub {
-            on { getSelectableSubscriptionInfoList() } doReturn listOf(pSimSubInfo)
-        }
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(pSimSubInfo))
 
         setContent()
 
@@ -96,9 +106,7 @@
         mockSubscriptionManager.stub {
             on { canDisablePhysicalSubscription() } doReturn false
         }
-        mockSubscriptionRepository.stub {
-            on { getSelectableSubscriptionInfoList() } doReturn listOf(pSimSubInfo)
-        }
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(pSimSubInfo))
 
         setContent()
 
@@ -112,9 +120,7 @@
             setId(SUB_ID)
             setEmbedded(true)
         }.build()
-        mockSubscriptionRepository.stub {
-            on { getSelectableSubscriptionInfoList() } doReturn listOf(eSimSubInfo)
-        }
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(eSimSubInfo))
 
         setContent()
 
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
index 3f69155..15ca2f0 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt
@@ -24,7 +24,6 @@
 import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
 import com.android.settingslib.spa.testutils.toListWithTimeout
 import com.google.common.truth.Truth.assertThat
-import java.util.UUID
 import kotlinx.coroutines.async
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.runBlocking
@@ -83,65 +82,6 @@
     }
 
     @Test
-    fun getSelectableSubscriptionInfoList_sortedBySubId() {
-        mockSubscriptionManager.stub {
-            on { getAvailableSubscriptionInfoList() } doReturn listOf(
-                SubscriptionInfo.Builder().apply {
-                    setId(SUB_ID_2)
-                }.build(),
-                SubscriptionInfo.Builder().apply {
-                    setId(SUB_ID_1)
-                }.build(),
-            )
-        }
-
-        val subInfos = context.getSelectableSubscriptionInfoList()
-
-        assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_1, SUB_ID_2).inOrder()
-    }
-
-    @Test
-    fun getSelectableSubscriptionInfoList_sameGroupAndOneHasSlot_returnTheOneWithSimSlotIndex() {
-        mockSubscriptionManager.stub {
-            on { getAvailableSubscriptionInfoList() } doReturn listOf(
-                SubscriptionInfo.Builder().apply {
-                    setId(SUB_ID_1)
-                    setGroupUuid(GROUP_UUID)
-                }.build(),
-                SubscriptionInfo.Builder().apply {
-                    setId(SUB_ID_2)
-                    setGroupUuid(GROUP_UUID)
-                    setSimSlotIndex(SIM_SLOT_INDEX)
-                }.build(),
-            )
-        }
-
-        val subInfos = context.getSelectableSubscriptionInfoList()
-
-        assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_2)
-    }
-
-    @Test
-    fun getSelectableSubscriptionInfoList_sameGroupAndNonHasSlot_returnTheOneWithMinimumSubId() {
-        mockSubscriptionManager.stub {
-            on { getAvailableSubscriptionInfoList() } doReturn listOf(
-                SubscriptionInfo.Builder().apply {
-                    setId(SUB_ID_2)
-                    setGroupUuid(GROUP_UUID)
-                }.build(),
-                SubscriptionInfo.Builder().apply {
-                    setId(SUB_ID_1)
-                    setGroupUuid(GROUP_UUID)
-                }.build(),
-            )
-        }
-
-        val subInfos = context.getSelectableSubscriptionInfoList()
-
-        assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_1)
-    }
-
-    @Test
     fun phoneNumberFlow() = runBlocking {
         mockSubscriptionManager.stub {
             on { getPhoneNumber(SUB_ID_1) } doReturn NUMBER_1
@@ -158,9 +98,6 @@
 
     private companion object {
         const val SUB_ID_1 = 1
-        const val SUB_ID_2 = 2
-        val GROUP_UUID = UUID.randomUUID().toString()
-        const val SIM_SLOT_INDEX = 1
         const val NUMBER_1 = "000000001"
         const val MCC = "310"
     }