Merge "Create SubscriptionRepository.phoneNumberFlow" into main

This commit is contained in:
Chaohui Wang
2024-07-30 04:41:02 +00:00
committed by Android (Google) Code Review
5 changed files with 100 additions and 141 deletions

View File

@@ -17,49 +17,37 @@
package com.android.settings.network.telephony
import android.content.Context
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settings.network.SubscriptionInfoListViewModel
import com.android.settings.network.SubscriptionUtil
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/**
* Preference controller for "Phone number"
*/
class MobileNetworkPhoneNumberPreferenceController(context: Context, key: String) :
TelephonyBasePreferenceController(context, key) {
/** Preference controller for "Phone number" */
class MobileNetworkPhoneNumberPreferenceController
@JvmOverloads
constructor(
context: Context,
key: String,
private val subscriptionRepository: SubscriptionRepository = SubscriptionRepository(context),
) : TelephonyBasePreferenceController(context, key) {
private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
private lateinit var preference: Preference
private var phoneNumber = String()
fun init(fragment: Fragment, subId: Int) {
lazyViewModel = fragment.viewModels()
fun init(subId: Int) {
mSubId = subId
}
override fun getAvailabilityStatus(subId: Int): Int = when {
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
SubscriptionManager.isValidSubscriptionId(subId)
&& SubscriptionUtil.isSimHardwareVisible(mContext) -> AVAILABLE
else -> CONDITIONALLY_UNAVAILABLE
}
override fun getAvailabilityStatus(subId: Int): Int =
when {
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
SubscriptionManager.isValidSubscriptionId(subId) &&
SubscriptionUtil.isSimHardwareVisible(mContext) -> AVAILABLE
else -> CONDITIONALLY_UNAVAILABLE
}
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
@@ -67,51 +55,10 @@ class MobileNetworkPhoneNumberPreferenceController(context: Context, key: String
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
if (!this::lazyViewModel.isInitialized) {
Log.e(
this.javaClass.simpleName,
"lateinit property lazyViewModel has not been initialized"
)
return
}
val viewModel by lazyViewModel
val coroutineScope = viewLifecycleOwner.lifecycleScope
viewModel.subscriptionInfoListFlow
.map { subscriptionInfoList ->
subscriptionInfoList
.firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
subscriptionRepository.phoneNumberFlow(mSubId).collectLatestWithLifecycle(
viewLifecycleOwner) { phoneNumber ->
preference.summary = phoneNumber ?: getStringUnknown()
}
.flowOn(Dispatchers.Default)
.collectLatestWithLifecycle(viewLifecycleOwner) {
it?.let {
coroutineScope.launch {
refreshData(it)
}
}
}
}
@VisibleForTesting
suspend fun refreshData(subscriptionInfo: SubscriptionInfo){
withContext(Dispatchers.Default) {
phoneNumber = getFormattedPhoneNumber(subscriptionInfo)
}
refreshUi()
}
private fun refreshUi(){
preference.summary = phoneNumber
}
private fun getFormattedPhoneNumber(subscriptionInfo: SubscriptionInfo?): String {
val phoneNumber = SubscriptionUtil.getBidiFormattedPhoneNumber(
mContext,
subscriptionInfo
)
return phoneNumber
?.let { return it.ifEmpty { getStringUnknown() } }
?: getStringUnknown()
}
private fun getStringUnknown(): String {

View File

@@ -257,7 +257,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
use(NrDisabledInDsdsFooterPreferenceController.class).init(mSubId);
use(MobileNetworkSpnPreferenceController.class).init(this, mSubId);
use(MobileNetworkPhoneNumberPreferenceController.class).init(this, mSubId);
use(MobileNetworkPhoneNumberPreferenceController.class).init(mSubId);
use(MobileNetworkImeiPreferenceController.class).init(this, mSubId);
final MobileDataPreferenceController mobileDataPreferenceController =

View File

@@ -24,13 +24,14 @@ 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.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
@@ -52,7 +53,7 @@ class SubscriptionRepository(private val context: Context) {
/** 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()
return subscriptionsChangedFlow()
.map { subscriptionManager.isSubscriptionEnabled(subId) }
.conflate()
.onEach { Log.d(TAG, "[$subId] isSubscriptionEnabledFlow: $it") }
@@ -87,12 +88,30 @@ class SubscriptionRepository(private val context: Context) {
}.conflate().onEach { Log.d(TAG, "subscriptions changed") }.flowOn(Dispatchers.Default)
/** Flow of active subscription ids. */
fun activeSubscriptionIdListFlow(): Flow<List<Int>> = context.subscriptionsChangedFlow()
.map { subscriptionManager.activeSubscriptionIdList.sorted() }
.distinctUntilChanged()
.conflate()
.onEach { Log.d(TAG, "activeSubscriptionIdList: $it") }
.flowOn(Dispatchers.Default)
fun activeSubscriptionIdListFlow(): Flow<List<Int>> =
subscriptionsChangedFlow()
.map { subscriptionManager.activeSubscriptionIdList.sorted() }
.distinctUntilChanged()
.conflate()
.onEach { Log.d(TAG, "activeSubscriptionIdList: $it") }
.flowOn(Dispatchers.Default)
fun activeSubscriptionInfoFlow(subId: Int): Flow<SubscriptionInfo?> =
subscriptionsChangedFlow()
.map { subscriptionManager.getActiveSubscriptionInfo(subId) }
.distinctUntilChanged()
.conflate()
.flowOn(Dispatchers.Default)
@OptIn(ExperimentalCoroutinesApi::class)
fun phoneNumberFlow(subId: Int): Flow<String?> =
activeSubscriptionInfoFlow(subId).flatMapLatest { subInfo ->
if (subInfo != null) {
context.phoneNumberFlow(subInfo)
} else {
flowOf(null)
}
}
}
val Context.subscriptionManager: SubscriptionManager?
@@ -100,9 +119,12 @@ val Context.subscriptionManager: SubscriptionManager?
fun Context.requireSubscriptionManager(): SubscriptionManager = subscriptionManager!!
fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo) = subscriptionsChangedFlow().map {
SubscriptionUtil.getBidiFormattedPhoneNumber(this, subscriptionInfo)
}.filterNot { it.isNullOrEmpty() }.flowOn(Dispatchers.Default)
fun Context.phoneNumberFlow(subscriptionInfo: SubscriptionInfo): Flow<String?> =
subscriptionsChangedFlow()
.map { SubscriptionUtil.getBidiFormattedPhoneNumber(this, subscriptionInfo) }
.distinctUntilChanged()
.conflate()
.flowOn(Dispatchers.Default)
fun Context.subscriptionsChangedFlow(): Flow<Unit> =
SubscriptionRepository(this).subscriptionsChangedFlow()