Merge "Create selectableSubscriptionInfoListFlow" into main
This commit is contained in:
@@ -20,7 +20,7 @@ import android.app.Application
|
|||||||
import android.telephony.SubscriptionManager
|
import android.telephony.SubscriptionManager
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
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 com.android.settings.network.telephony.subscriptionsChangedFlow
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
@@ -45,7 +45,8 @@ class SubscriptionInfoListViewModel(application: Application) : AndroidViewModel
|
|||||||
* Getting the Selectable SubscriptionInfo List from the SubscriptionRepository's
|
* Getting the Selectable SubscriptionInfo List from the SubscriptionRepository's
|
||||||
* getAvailableSubscriptionInfoList
|
* getAvailableSubscriptionInfoList
|
||||||
*/
|
*/
|
||||||
val selectableSubscriptionInfoListFlow = application.subscriptionsChangedFlow().map {
|
val selectableSubscriptionInfoListFlow =
|
||||||
application.getSelectableSubscriptionInfoList()
|
SubscriptionRepository(application)
|
||||||
}.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
|
.selectableSubscriptionInfoListFlow()
|
||||||
|
.stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
|
||||||
}
|
}
|
||||||
|
@@ -52,7 +52,7 @@ import com.android.settings.network.helper.SelectableSubscriptions;
|
|||||||
import com.android.settings.network.helper.SubscriptionAnnotation;
|
import com.android.settings.network.helper.SubscriptionAnnotation;
|
||||||
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
|
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
|
||||||
import com.android.settings.network.telephony.EuiccRacConnectivityDialogActivity;
|
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 com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -508,7 +508,7 @@ public class SubscriptionUtil {
|
|||||||
* @return list of user selectable subscriptions.
|
* @return list of user selectable subscriptions.
|
||||||
*/
|
*/
|
||||||
public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) {
|
public static List<SubscriptionInfo> getSelectableSubscriptionInfoList(Context context) {
|
||||||
return SubscriptionRepositoryKt.getSelectableSubscriptionInfoList(context);
|
return new SubscriptionRepository(context).getSelectableSubscriptionInfoList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -42,13 +42,48 @@ private const val TAG = "SubscriptionRepository"
|
|||||||
class SubscriptionRepository(private val context: Context) {
|
class SubscriptionRepository(private val context: Context) {
|
||||||
private val subscriptionManager = context.requireSubscriptionManager()
|
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 a list of subscriptions that are available and visible to the user.
|
||||||
*
|
*
|
||||||
* @return list of user selectable subscriptions.
|
* @return list of user selectable subscriptions.
|
||||||
*/
|
*/
|
||||||
fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> =
|
fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> {
|
||||||
context.getSelectableSubscriptionInfoList()
|
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]. */
|
/** Flow of whether the subscription visible for the given [subId]. */
|
||||||
fun isSubscriptionVisibleFlow(subId: Int): Flow<Boolean> {
|
fun isSubscriptionVisibleFlow(subId: Int): Flow<Boolean> {
|
||||||
@@ -154,38 +189,6 @@ fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo): Flow<String?> =
|
|||||||
fun Context.subscriptionsChangedFlow(): Flow<Unit> =
|
fun Context.subscriptionsChangedFlow(): Flow<Unit> =
|
||||||
SubscriptionRepository(this).subscriptionsChangedFlow()
|
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. */
|
/** Subscription with invalid sim slot index has lowest sort order. */
|
||||||
private val SubscriptionInfo.sortableSimSlotIndex: Int
|
private val SubscriptionInfo.sortableSimSlotIndex: Int
|
||||||
get() = if (simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
|
get() = if (simSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
|
||||||
|
@@ -120,7 +120,7 @@ class SubscriptionRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val subInfos = context.getSelectableSubscriptionInfoList()
|
val subInfos = repository.getSelectableSubscriptionInfoList()
|
||||||
|
|
||||||
assertThat(subInfos.map { it.simSlotIndex })
|
assertThat(subInfos.map { it.simSlotIndex })
|
||||||
.containsExactly(SIM_SLOT_INDEX_0, SIM_SLOT_INDEX_1).inOrder()
|
.containsExactly(SIM_SLOT_INDEX_0, SIM_SLOT_INDEX_1).inOrder()
|
||||||
@@ -141,7 +141,7 @@ class SubscriptionRepositoryTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val subInfos = context.getSelectableSubscriptionInfoList()
|
val subInfos = repository.getSelectableSubscriptionInfoList()
|
||||||
|
|
||||||
assertThat(subInfos.map { it.simSlotIndex })
|
assertThat(subInfos.map { it.simSlotIndex })
|
||||||
.containsExactly(SIM_SLOT_INDEX_1, SubscriptionManager.INVALID_SIM_SLOT_INDEX).inOrder()
|
.containsExactly(SIM_SLOT_INDEX_1, SubscriptionManager.INVALID_SIM_SLOT_INDEX).inOrder()
|
||||||
@@ -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)
|
assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_IN_SLOT_0)
|
||||||
}
|
}
|
||||||
@@ -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)
|
assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_3_NOT_IN_SLOT)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user