Always set cross sim calling
By CrossSimCallingViewModel, in SIMs and per SIM settings page.
To ensure the status is always right, including the case after the
onboarding set up finished.
Fix: 347882381
Fix: 348529996
Flag: EXEMPT bug fix
Test: manual - turn on / off "Automatic data switching" on SIMs
Test: manual - turn off "Automatic data switching" during onboarding
Change-Id: Icc2eacb67850fa7b3aa0fe310cd09a0e0147912b
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index fcbfdef..6d6e41f 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -38,7 +38,6 @@
import com.android.settings.flags.Flags;
import com.android.settings.network.MobileDataContentObserver;
import com.android.settings.network.SubscriptionsChangeListener;
-import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel;
/**
* Controls whether switch mobile data to the non-default SIM if the non-default SIM has better
@@ -63,8 +62,6 @@
@Nullable
private MobileDataContentObserver mMobileDataContentObserver;
@Nullable
- private CrossSimCallingViewModel mCrossSimCallingViewModel;
- @Nullable
private PreferenceScreen mScreen;
public AutoDataSwitchPreferenceController(
@@ -72,10 +69,9 @@
super(context, preferenceKey);
}
- void init(int subId, @Nullable CrossSimCallingViewModel crossSimCallingViewModel) {
+ void init(int subId) {
this.mSubId = subId;
mManager = mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
- mCrossSimCallingViewModel = crossSimCallingViewModel;
}
@OnLifecycleEvent(ON_RESUME)
@@ -122,9 +118,6 @@
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
isChecked);
}
- if (mCrossSimCallingViewModel != null) {
- mCrossSimCallingViewModel.updateCrossSimCalling();
- }
return true;
}
diff --git a/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt b/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt
index 62e7e98..829c4c0 100644
--- a/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/DataSubscriptionRepository.kt
@@ -33,6 +33,7 @@
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
class DataSubscriptionRepository(
@@ -53,6 +54,7 @@
.onStart { emit(SubscriptionManager.getDefaultDataSubscriptionId()) }
.distinctUntilChanged()
.conflate()
+ .onEach { Log.d(TAG, "defaultDataSubscriptionIdFlow: $it") }
.flowOn(Dispatchers.Default)
fun activeDataSubscriptionIdFlow(): Flow<Int> =
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index d70ef25..896eac6 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -247,9 +247,10 @@
use(CarrierSettingsVersionPreferenceController.class).init(mSubId);
use(BillingCyclePreferenceController.class).init(mSubId);
use(MmsMessagePreferenceController.class).init(mSubId);
- final var crossSimCallingViewModel =
- new ViewModelProvider(this).get(CrossSimCallingViewModel.class);
- use(AutoDataSwitchPreferenceController.class).init(mSubId, crossSimCallingViewModel);
+ // CrossSimCallingViewModel is responsible for maintaining the correct cross sim calling
+ // settings (backup calling).
+ new ViewModelProvider(this).get(CrossSimCallingViewModel.class);
+ use(AutoDataSwitchPreferenceController.class).init(mSubId);
use(DisabledSubscriptionController.class).init(mSubId);
use(DeleteSimProfilePreferenceController.class).init(mSubId);
use(DisableSimFooterPreferenceController.class).init(mSubId);
diff --git a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
index 170af54..dda147b 100644
--- a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
+++ b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
@@ -24,22 +24,22 @@
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.android.settings.R
+import com.android.settings.network.telephony.CarrierConfigRepository
+import com.android.settings.network.telephony.DataSubscriptionRepository
import com.android.settings.network.telephony.MobileDataRepository
import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
-import com.android.settings.network.telephony.safeGetConfig
-import com.android.settings.network.telephony.telephonyManager
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.plus
@OptIn(ExperimentalCoroutinesApi::class)
@@ -48,24 +48,23 @@
) : AndroidViewModel(application) {
private val subscriptionRepository = SubscriptionRepository(application)
- private val carrierConfigManager =
- application.getSystemService(CarrierConfigManager::class.java)!!
+ private val dataSubscriptionRepository = DataSubscriptionRepository(application)
+ private val mobileDataRepository = MobileDataRepository(application)
+ private val carrierConfigRepository = CarrierConfigRepository(application)
private val scope = viewModelScope + Dispatchers.Default
private val metricsFeatureProvider = featureFactory.metricsFeatureProvider
- private val updateChannel = Channel<Unit>()
- private val mobileDataRepository = MobileDataRepository(application)
init {
val resources = application.resources
if (resources.getBoolean(R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
- subscriptionRepository.activeSubscriptionIdListFlow()
- .flatMapLatest { activeSubIds ->
- merge(
- activeSubIds.anyMobileDataEnableChangedFlow(),
- updateChannel.receiveAsFlow(),
- ).map {
- activeSubIds to crossSimCallNewEnabled(activeSubIds)
- }
+ combine(
+ subscriptionRepository.activeSubscriptionIdListFlow(),
+ dataSubscriptionRepository.defaultDataSubscriptionIdFlow(),
+ ) { activeSubIds, defaultDataSubId ->
+ activeSubIds to crossSimCallNewEnabled(activeSubIds, defaultDataSubId)
+ }
+ .flatMapLatest { (activeSubIds, newEnabledFlow) ->
+ newEnabledFlow.map { newEnabled -> activeSubIds to newEnabled }
}
.distinctUntilChanged()
.onEach { (activeSubIds, newEnabled) ->
@@ -75,44 +74,36 @@
}
}
- fun updateCrossSimCalling() {
- updateChannel.trySend(Unit)
- }
-
- private fun List<Int>.anyMobileDataEnableChangedFlow() = map { subId ->
- mobileDataRepository.mobileDataEnabledChangedFlow(subId = subId, sendInitialValue = false)
- }.merge()
-
private suspend fun updateCrossSimCalling(activeSubIds: List<Int>, newEnabled: Boolean) {
metricsFeatureProvider.action(
application,
SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT,
newEnabled,
)
- activeSubIds.filter { crossSimAvailable(it) }.forEach { subId ->
- ImsMmTelRepositoryImpl(application, subId)
- .setCrossSimCallingEnabled(newEnabled)
- }
+ activeSubIds
+ .filter { subId -> crossSimAvailable(subId) }
+ .forEach { subId ->
+ ImsMmTelRepositoryImpl(application, subId).setCrossSimCallingEnabled(newEnabled)
+ }
}
private suspend fun crossSimAvailable(subId: Int): Boolean =
WifiCallingRepository(application, subId).isWifiCallingSupported() &&
- crossSimImsAvailable(subId)
+ carrierConfigRepository.getBoolean(
+ subId, CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL)
- private fun crossSimImsAvailable(subId: Int): Boolean =
- carrierConfigManager.safeGetConfig(
- keys = listOf(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL),
- subId = subId,
- ).getBoolean(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false)
-
- private fun crossSimCallNewEnabled(activeSubscriptionIdList: List<Int>): Boolean {
- val defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId()
- return SubscriptionManager.isValidSubscriptionId(defaultDataSubId) &&
- activeSubscriptionIdList.any { subId ->
- subId != defaultDataSubId &&
- application.telephonyManager(subId).isMobileDataPolicyEnabled(
- TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH
- )
- }
+ private fun crossSimCallNewEnabled(
+ activeSubscriptionIdList: List<Int>,
+ defaultDataSubId: Int,
+ ): Flow<Boolean> {
+ if (!SubscriptionManager.isValidSubscriptionId(defaultDataSubId)) return flowOf(false)
+ val isMobileDataPolicyEnabledFlows =
+ activeSubscriptionIdList
+ .filter { subId -> subId != defaultDataSubId }
+ .map { subId ->
+ mobileDataRepository.isMobileDataPolicyEnabledFlow(
+ subId, TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
+ }
+ return combine(isMobileDataPolicyEnabledFlows) { true in it }
}
}
diff --git a/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt b/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
index e7cc18f..5fbd7dc 100644
--- a/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
+++ b/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
@@ -34,7 +34,9 @@
) {
val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
val coroutineScope = rememberCoroutineScope()
- val crossSimCallingViewModel = viewModel<CrossSimCallingViewModel>() // handles backup calling
+ // CrossSimCallingViewModel is responsible for maintaining the correct cross sim calling
+ // settings (backup calling).
+ viewModel<CrossSimCallingViewModel>()
SwitchPreference(
object : SwitchPreferenceModel {
override val title = stringResource(id = R.string.primary_sim_automatic_data_title)
@@ -43,7 +45,6 @@
override val onCheckedChange: (Boolean) -> Unit = { newEnabled ->
coroutineScope.launch(Dispatchers.Default) {
setAutoDataEnabled(newEnabled)
- crossSimCallingViewModel.updateCrossSimCalling()
}
}
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
index 8db4681..29592cf 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
@@ -85,7 +85,7 @@
return true;
}
};
- mController.init(SUB_ID_1, null);
+ mController.init(SUB_ID_1);
}
@Test