diff --git a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt index c5d1200a1d4..e8912048f58 100644 --- a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt +++ b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt @@ -27,6 +27,7 @@ import android.telephony.ims.ImsStateCallback import android.telephony.ims.RegistrationManager import android.telephony.ims.feature.MmTelFeature import android.util.Log +import androidx.annotation.VisibleForTesting import kotlin.coroutines.resume import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor @@ -53,11 +54,6 @@ interface ImsMmTelRepository { @AccessNetworkConstants.TransportType transportType: Int, ): Flow - suspend fun isSupported( - @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int, - @AccessNetworkConstants.TransportType transportType: Int, - ): Boolean - suspend fun setCrossSimCallingEnabled(enabled: Boolean) } @@ -143,7 +139,8 @@ class ImsMmTelRepositoryImpl( override fun isSupportedFlow(capability: Int, transportType: Int): Flow = imsReadyFlow().map { imsReady -> imsReady && isSupported(capability, transportType) } - override suspend fun isSupported( + @VisibleForTesting + suspend fun isSupported( @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int, @AccessNetworkConstants.TransportType transportType: Int, ): Boolean = withContext(Dispatchers.Default) { diff --git a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt index dda147b549e..cab27caa2b8 100644 --- a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt +++ b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt @@ -21,6 +21,7 @@ import android.app.settings.SettingsEnums import android.telephony.CarrierConfigManager import android.telephony.SubscriptionManager import android.telephony.TelephonyManager +import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.android.settings.R @@ -34,6 +35,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf @@ -43,9 +45,8 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.plus @OptIn(ExperimentalCoroutinesApi::class) -class CrossSimCallingViewModel( - private val application: Application, -) : AndroidViewModel(application) { +class CrossSimCallingViewModel(private val application: Application) : + AndroidViewModel(application) { private val subscriptionRepository = SubscriptionRepository(application) private val dataSubscriptionRepository = DataSubscriptionRepository(application) @@ -61,38 +62,45 @@ class CrossSimCallingViewModel( subscriptionRepository.activeSubscriptionIdListFlow(), dataSubscriptionRepository.defaultDataSubscriptionIdFlow(), ) { activeSubIds, defaultDataSubId -> - activeSubIds to crossSimCallNewEnabled(activeSubIds, defaultDataSubId) + updatableSubIdsFlow(activeSubIds) to + crossSimCallNewEnabledFlow(activeSubIds, defaultDataSubId) } - .flatMapLatest { (activeSubIds, newEnabledFlow) -> - newEnabledFlow.map { newEnabled -> activeSubIds to newEnabled } + .flatMapLatest { (updatableSubIdsFlow, crossSimCallNewEnabledFlow) -> + combine(updatableSubIdsFlow, crossSimCallNewEnabledFlow) { + updatableSubIds, + newEnabled -> + updatableSubIds to newEnabled + } } .distinctUntilChanged() - .onEach { (activeSubIds, newEnabled) -> - updateCrossSimCalling(activeSubIds, newEnabled) + .conflate() + .onEach { (updatableSubIds, newEnabled) -> + Log.d(TAG, "updatableSubIds: $updatableSubIds newEnabled: $newEnabled") + updateCrossSimCalling(updatableSubIds, newEnabled) } .launchIn(scope) } } - private suspend fun updateCrossSimCalling(activeSubIds: List, newEnabled: Boolean) { - metricsFeatureProvider.action( - application, - SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT, - newEnabled, - ) - activeSubIds - .filter { subId -> crossSimAvailable(subId) } - .forEach { subId -> - ImsMmTelRepositoryImpl(application, subId).setCrossSimCallingEnabled(newEnabled) + private fun updatableSubIdsFlow(activeSubIds: List): Flow> { + val updatableSubIdFlows = + activeSubIds.map { subId -> + WifiCallingRepository(application, subId).wifiCallingReadyFlow().map { isReady -> + subId.takeIf { isReady && isCrossSimImsAvailable(subId) } + } } + return combine(updatableSubIdFlows) { subIds -> subIds.filterNotNull() } + .distinctUntilChanged() + .conflate() } - private suspend fun crossSimAvailable(subId: Int): Boolean = - WifiCallingRepository(application, subId).isWifiCallingSupported() && - carrierConfigRepository.getBoolean( - subId, CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL) + private fun isCrossSimImsAvailable(subId: Int) = + carrierConfigRepository.getBoolean( + subId, + CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, + ) - private fun crossSimCallNewEnabled( + private fun crossSimCallNewEnabledFlow( activeSubscriptionIdList: List, defaultDataSubId: Int, ): Flow { @@ -102,8 +110,27 @@ class CrossSimCallingViewModel( .filter { subId -> subId != defaultDataSubId } .map { subId -> mobileDataRepository.isMobileDataPolicyEnabledFlow( - subId, TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) + subId, + TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, + ) } return combine(isMobileDataPolicyEnabledFlows) { true in it } + .distinctUntilChanged() + .conflate() + } + + private suspend fun updateCrossSimCalling(subIds: List, newEnabled: Boolean) { + metricsFeatureProvider.action( + application, + SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT, + newEnabled, + ) + for (subId in subIds) { + ImsMmTelRepositoryImpl(application, subId).setCrossSimCallingEnabled(newEnabled) + } + } + + companion object { + private const val TAG = "CrossSimCallingVM" } } diff --git a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt index 6af0559adb1..a6a47fadb34 100644 --- a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt +++ b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt @@ -29,9 +29,7 @@ import com.android.settings.network.telephony.ims.ImsMmTelRepository import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl import com.android.settings.network.telephony.telephonyManager import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.withContext interface IWifiCallingRepository { /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */ @@ -75,11 +73,4 @@ constructor( tech = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN, ) - - suspend fun isWifiCallingSupported(): Boolean = withContext(Dispatchers.Default) { - imsMmTelRepository.isSupported( - capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, - transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN, - ) - } } diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt index f0a23eb92c9..9b71465a4db 100644 --- a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt @@ -102,22 +102,6 @@ class WifiCallingRepositoryTest { assertThat(wiFiCallingMode).isEqualTo(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED) } - @Test - fun isWifiCallingSupported() = runBlocking { - mockImsMmTelRepository.stub { - onBlocking { - isSupported( - capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, - transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN, - ) - } doReturn true - } - - val isSupported = repository.isWifiCallingSupported() - - assertThat(isSupported).isTrue() - } - private fun mockUseWfcHomeModeForRoaming(config: Boolean) { mockCarrierConfigManager.stub { on {