Fix isSubscriptionEnabledFlow crash

When INVALID_SUBSCRIPTION_ID.

Fix: 338014486
Test: unit test
Change-Id: I97b5f005fb99473c2712f9643704a35cfaeecfac
This commit is contained in:
Chaohui Wang
2024-05-10 16:54:12 +08:00
parent ee501485b8
commit 881c19480a
3 changed files with 26 additions and 10 deletions

View File

@@ -26,9 +26,11 @@ import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@@ -46,7 +48,15 @@ class SubscriptionRepository(private val context: Context) {
fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> = fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> =
context.getSelectableSubscriptionInfoList() context.getSelectableSubscriptionInfoList()
fun isSubscriptionEnabledFlow(subId: Int) = context.isSubscriptionEnabledFlow(subId) /** Flow of whether the subscription enabled for the given [subId]. */
fun isSubscriptionEnabledFlow(subId: Int): Flow<Boolean> {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
return context.subscriptionsChangedFlow()
.map { subscriptionManager.isSubscriptionEnabled(subId) }
.conflate()
.onEach { Log.d(TAG, "[$subId] isSubscriptionEnabledFlow: $it") }
.flowOn(Dispatchers.Default)
}
/** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */ /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
fun collectSubscriptionEnabled( fun collectSubscriptionEnabled(
@@ -65,11 +75,6 @@ val Context.subscriptionManager: SubscriptionManager?
fun Context.requireSubscriptionManager(): SubscriptionManager = subscriptionManager!! fun Context.requireSubscriptionManager(): SubscriptionManager = subscriptionManager!!
fun Context.isSubscriptionEnabledFlow(subId: Int) = subscriptionsChangedFlow().map {
subscriptionManager?.isSubscriptionEnabled(subId) ?: false
}.conflate().onEach { Log.d(TAG, "[$subId] isSubscriptionEnabledFlow: $it") }
.flowOn(Dispatchers.Default)
fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo) = subscriptionsChangedFlow().map { fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo) = subscriptionsChangedFlow().map {
SubscriptionUtil.getBidiFormattedPhoneNumber(this, subscriptionInfo) SubscriptionUtil.getBidiFormattedPhoneNumber(this, subscriptionInfo)
}.filterNot { it.isNullOrEmpty() }.flowOn(Dispatchers.Default) }.filterNot { it.isNullOrEmpty() }.flowOn(Dispatchers.Default)

View File

@@ -38,7 +38,7 @@ import com.android.settings.Utils
import com.android.settings.network.SubscriptionUtil import com.android.settings.network.SubscriptionUtil
import com.android.settings.network.telephony.MobileNetworkUtils import com.android.settings.network.telephony.MobileNetworkUtils
import com.android.settings.network.telephony.SubscriptionActivationRepository import com.android.settings.network.telephony.SubscriptionActivationRepository
import com.android.settings.network.telephony.isSubscriptionEnabledFlow import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settings.network.telephony.phoneNumberFlow import com.android.settings.network.telephony.phoneNumberFlow
import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -63,7 +63,7 @@ fun SimsSection(subscriptionInfoList: List<SubscriptionInfo>) {
private fun SimPreference(subInfo: SubscriptionInfo) { private fun SimPreference(subInfo: SubscriptionInfo) {
val context = LocalContext.current val context = LocalContext.current
val checked = remember(subInfo.subscriptionId) { val checked = remember(subInfo.subscriptionId) {
context.isSubscriptionEnabledFlow(subInfo.subscriptionId) SubscriptionRepository(context).isSubscriptionEnabledFlow(subInfo.subscriptionId)
}.collectAsStateWithLifecycle(initialValue = false) }.collectAsStateWithLifecycle(initialValue = false)
val phoneNumber = phoneNumber(subInfo) val phoneNumber = phoneNumber(subInfo)
val isConvertedPsim by remember(subInfo) { val isConvertedPsim by remember(subInfo) {

View File

@@ -52,13 +52,24 @@ class SubscriptionRepositoryTest {
on { subscriptionManager } doReturn mockSubscriptionManager on { subscriptionManager } doReturn mockSubscriptionManager
} }
private val repository = SubscriptionRepository(context)
@Test @Test
fun isSubscriptionEnabledFlow() = runBlocking { fun isSubscriptionEnabledFlow_invalidSubId() = runBlocking {
val isEnabled = repository
.isSubscriptionEnabledFlow(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.firstWithTimeoutOrNull()
assertThat(isEnabled).isFalse()
}
@Test
fun isSubscriptionEnabledFlow_enabled() = runBlocking {
mockSubscriptionManager.stub { mockSubscriptionManager.stub {
on { isSubscriptionEnabled(SUB_ID_1) } doReturn true on { isSubscriptionEnabled(SUB_ID_1) } doReturn true
} }
val isEnabled = context.isSubscriptionEnabledFlow(SUB_ID_1).firstWithTimeoutOrNull() val isEnabled = repository.isSubscriptionEnabledFlow(SUB_ID_1).firstWithTimeoutOrNull()
assertThat(isEnabled).isTrue() assertThat(isEnabled).isTrue()
} }