Loading src/com/android/settings/network/SubscriptionInfoListViewModel.kt +5 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.app.Application 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 Loading @@ -45,7 +45,8 @@ class SubscriptionInfoListViewModel(application: Application) : AndroidViewModel * 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()) } src/com/android/settings/network/SubscriptionUtil.java +2 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ import com.android.settings.network.helper.SelectableSubscriptions; 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; Loading Loading @@ -508,7 +508,7 @@ public class SubscriptionUtil { * @return list of user selectable subscriptions. */ public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) { return SubscriptionRepositoryKt.getSelectableSubscriptionInfoList(context); return new SubscriptionRepository(context).getSelectableSubscriptionInfoList(); } /** Loading src/com/android/settings/network/telephony/SubscriptionRepository.kt +37 −34 Original line number Diff line number Diff line Loading @@ -42,13 +42,48 @@ private const val TAG = "SubscriptionRepository" 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> { Loading Loading @@ -154,38 +189,6 @@ fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo): Flow<String?> = 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) { Loading tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt +4 −4 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.simSlotIndex }) .containsExactly(SIM_SLOT_INDEX_0, SIM_SLOT_INDEX_1).inOrder() Loading @@ -141,7 +141,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.simSlotIndex }) .containsExactly(SIM_SLOT_INDEX_1, SubscriptionManager.INVALID_SIM_SLOT_INDEX).inOrder() Loading @@ -164,7 +164,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_IN_SLOT_0) } Loading @@ -184,7 +184,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_3_NOT_IN_SLOT) } Loading Loading
src/com/android/settings/network/SubscriptionInfoListViewModel.kt +5 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import android.app.Application 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 Loading @@ -45,7 +45,8 @@ class SubscriptionInfoListViewModel(application: Application) : AndroidViewModel * 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()) }
src/com/android/settings/network/SubscriptionUtil.java +2 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ import com.android.settings.network.helper.SelectableSubscriptions; 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; Loading Loading @@ -508,7 +508,7 @@ public class SubscriptionUtil { * @return list of user selectable subscriptions. */ public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) { return SubscriptionRepositoryKt.getSelectableSubscriptionInfoList(context); return new SubscriptionRepository(context).getSelectableSubscriptionInfoList(); } /** Loading
src/com/android/settings/network/telephony/SubscriptionRepository.kt +37 −34 Original line number Diff line number Diff line Loading @@ -42,13 +42,48 @@ private const val TAG = "SubscriptionRepository" 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> { Loading Loading @@ -154,38 +189,6 @@ fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo): Flow<String?> = 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) { Loading
tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt +4 −4 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.simSlotIndex }) .containsExactly(SIM_SLOT_INDEX_0, SIM_SLOT_INDEX_1).inOrder() Loading @@ -141,7 +141,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.simSlotIndex }) .containsExactly(SIM_SLOT_INDEX_1, SubscriptionManager.INVALID_SIM_SLOT_INDEX).inOrder() Loading @@ -164,7 +164,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_IN_SLOT_0) } Loading @@ -184,7 +184,7 @@ class SubscriptionRepositoryTest { ) } val subInfos = context.getSelectableSubscriptionInfoList() val subInfos = repository.getSelectableSubscriptionInfoList() assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_3_NOT_IN_SLOT) } Loading