From 355ee0a1ee65686391d62a984f357196ae476994 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Mon, 2 Sep 2024 17:54:41 +0800 Subject: [PATCH] Refine CrossSimCalling updating Currently, this setting depends on whether wifi calling is supported, since wifi calling could takes some time to provision after sim is turned on, this state could be wrong when set cross sim calling. Use wifiCallingReadyFlow() to retrieve the latest state, and update setting when state changes. Fix: 352736998 Fix: 348529996 Flag: EXEMPT bug fix Test: manual - by turn on / off sim Change-Id: Id4b099e0c5d7cf47b007f37e6f278d1c46e58659 --- .../telephony/ims/ImsMmTelRepository.kt | 9 +-- .../wificalling/CrossSimCallingViewModel.kt | 75 +++++++++++++------ .../wificalling/WifiCallingRepository.kt | 9 --- .../wificalling/WifiCallingRepositoryTest.kt | 16 ---- 4 files changed, 54 insertions(+), 55 deletions(-) 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 {