Merge "Create selectableSubscriptionInfoListFlow" into main
diff --git a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
index df3b8ba..fe50522 100644
--- a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
+++ b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
@@ -20,7 +20,7 @@
 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.SubscriptionRepository
 import com.android.settings.network.telephony.subscriptionsChangedFlow
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.SharingStarted
@@ -45,7 +45,8 @@
      * Getting the Selectable SubscriptionInfo List from the SubscriptionRepository's
      * getAvailableSubscriptionInfoList
      */
-    val selectableSubscriptionInfoListFlow = application.subscriptionsChangedFlow().map {
-        application.getSelectableSubscriptionInfoList()
-    }.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
+    val selectableSubscriptionInfoListFlow =
+        SubscriptionRepository(application)
+            .selectableSubscriptionInfoListFlow()
+            .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 fcf1599..aca2fc3 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -52,7 +52,7 @@
 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.SubscriptionRepository;
 import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
 
 import java.util.ArrayList;
@@ -508,7 +508,7 @@
      * @return list of user selectable subscriptions.
      */
     public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) {
-        return SubscriptionRepositoryKt.getSelectableSubscriptionInfoList(context);
+        return new SubscriptionRepository(context).getSelectableSubscriptionInfoList();
     }
 
     /**
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index 26ea9b3..6b5b4cb 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -42,13 +42,48 @@
 class SubscriptionRepository(private val context: Context) {
     private val subscriptionManager = context.requireSubscriptionManager()
 
+    /** A cold flow of a list of subscriptions that are available and visible to the user. */
+    fun selectableSubscriptionInfoListFlow(): Flow<List<SubscriptionInfo>> =
+        context
+            .subscriptionsChangedFlow()
+            .map { getSelectableSubscriptionInfoList() }
+            .conflate()
+            .flowOn(Dispatchers.Default)
+
     /**
      * 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 getSelectableSubscriptionInfoList(): List<SubscriptionInfo> {
+        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, context, subInfo)
+            }
+        return visibleList
+            .groupBy { it.groupUuid }
+            .flatMap { (groupUuid, subInfos) ->
+                if (groupUuid == null) {
+                    subInfos
+                } else {
+                    // Multiple subscriptions in a group should only have one representative.
+                    // It should be the current active primary subscription if any, or the primary
+                    // subscription with minimum subscription id.
+                    subInfos
+                        .filter { it.simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX }
+                        .ifEmpty { subInfos.sortedBy { it.subscriptionId } }
+                        .take(1)
+                }
+            }
+            // Matching the sorting order in
+            // SubscriptionManagerService.getAvailableSubscriptionInfoList
+            .sortedWith(compareBy({ it.sortableSimSlotIndex }, { it.subscriptionId }))
+            .also { Log.d(TAG, "getSelectableSubscriptionInfoList: $it") }
+    }
 
     /** Flow of whether the subscription visible for the given [subId]. */
     fun isSubscriptionVisibleFlow(subId: Int): Flow<Boolean> {
@@ -154,38 +189,6 @@
 fun Context.subscriptionsChangedFlow(): Flow<Unit> =
     SubscriptionRepository(this).subscriptionsChangedFlow()
 
-/**
- * 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)
-    }
-    return visibleList
-        .groupBy { it.groupUuid }
-        .flatMap { (groupUuid, subInfos) ->
-            if (groupUuid == null) {
-                subInfos
-            } else {
-                // Multiple subscriptions in a group should only have one representative.
-                // It should be the current active primary subscription if any, or the primary
-                // subscription with minimum subscription id.
-                subInfos.filter { it.simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX }
-                    .ifEmpty { subInfos.sortedBy { it.subscriptionId } }
-                    .take(1)
-            }
-        }
-        // Matching the sorting order in SubscriptionManagerService.getAvailableSubscriptionInfoList
-        .sortedWith(compareBy({ it.sortableSimSlotIndex }, { it.subscriptionId }))
-        .also { Log.d(TAG, "getSelectableSubscriptionInfoList: $it") }
-}
-
 /** Subscription with invalid sim slot index has lowest sort order. */
 private val SubscriptionInfo.sortableSimSlotIndex: Int
     get() = if (simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
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 5dbc534..5052f57 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
@@ -120,7 +120,7 @@
             )
         }
 
-        val subInfos = context.getSelectableSubscriptionInfoList()
+        val subInfos = repository.getSelectableSubscriptionInfoList()
 
         assertThat(subInfos.map { it.simSlotIndex })
             .containsExactly(SIM_SLOT_INDEX_0, SIM_SLOT_INDEX_1).inOrder()
@@ -141,7 +141,7 @@
             )
         }
 
-        val subInfos = context.getSelectableSubscriptionInfoList()
+        val subInfos = repository.getSelectableSubscriptionInfoList()
 
         assertThat(subInfos.map { it.simSlotIndex })
             .containsExactly(SIM_SLOT_INDEX_1, SubscriptionManager.INVALID_SIM_SLOT_INDEX).inOrder()
@@ -164,7 +164,7 @@
             )
         }
 
-        val subInfos = context.getSelectableSubscriptionInfoList()
+        val subInfos = repository.getSelectableSubscriptionInfoList()
 
         assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_IN_SLOT_0)
     }
@@ -184,7 +184,7 @@
             )
         }
 
-        val subInfos = context.getSelectableSubscriptionInfoList()
+        val subInfos = repository.getSelectableSubscriptionInfoList()
 
         assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_3_NOT_IN_SLOT)
     }