Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1b3c2b9 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

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
parent f9a571dd
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ 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.subscriptionsChangedFlow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
@@ -46,6 +45,6 @@ class SubscriptionInfoListViewModel(application: Application) : AndroidViewModel
     * getAvailableSubscriptionInfoList
     */
    val selectableSubscriptionInfoListFlow = application.subscriptionsChangedFlow().map {
        application.getSelectableSubscriptionInfoList()
        SubscriptionUtil.getSelectableSubscriptionInfoList(application)
    }.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
}
+35 −2
Original line number Diff line number Diff line
@@ -50,12 +50,12 @@ 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.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 @@ public class SubscriptionUtil {
     * @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;
        }
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ class MobileNetworkSwitchController @JvmOverloads constructor(
    }

    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
+0 −43
Original line number Diff line number Diff line
@@ -20,9 +20,7 @@ import android.content.Context
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 @@ import kotlinx.coroutines.flow.onEach
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 @@ fun Context.subscriptionsChangedFlow() = callbackFlow {

    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") }
}
+16 −10
Original line number Diff line number Diff line
@@ -30,8 +30,11 @@ import androidx.compose.ui.test.onNodeWithText
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 @@ class MobileNetworkSwitchControllerTest {
    }

    private val mockSubscriptionRepository = mock<SubscriptionRepository> {
        on { getSelectableSubscriptionInfoList() } doReturn listOf(SubInfo)
        on { isSubscriptionEnabledFlow(SUB_ID) } doReturn flowOf(false)
    }

@@ -68,6 +70,16 @@ class MobileNetworkSwitchControllerTest {
        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 @@ class MobileNetworkSwitchControllerTest {
        mockSubscriptionManager.stub {
            on { canDisablePhysicalSubscription() } doReturn true
        }
        mockSubscriptionRepository.stub {
            on { getSelectableSubscriptionInfoList() } doReturn listOf(pSimSubInfo)
        }
        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(pSimSubInfo))

        setContent()

@@ -96,9 +106,7 @@ class MobileNetworkSwitchControllerTest {
        mockSubscriptionManager.stub {
            on { canDisablePhysicalSubscription() } doReturn false
        }
        mockSubscriptionRepository.stub {
            on { getSelectableSubscriptionInfoList() } doReturn listOf(pSimSubInfo)
        }
        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(pSimSubInfo))

        setContent()

@@ -112,9 +120,7 @@ class MobileNetworkSwitchControllerTest {
            setId(SUB_ID)
            setEmbedded(true)
        }.build()
        mockSubscriptionRepository.stub {
            on { getSelectableSubscriptionInfoList() } doReturn listOf(eSimSubInfo)
        }
        SubscriptionUtil.setAvailableSubscriptionsForTesting(listOf(eSimSubInfo))

        setContent()

Loading