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
This commit is contained in:
@@ -38,7 +38,6 @@ import com.android.settings.datausage.DataUsageUtils;
|
||||
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 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
|
||||
@Nullable
|
||||
private MobileDataContentObserver mMobileDataContentObserver;
|
||||
@Nullable
|
||||
private CrossSimCallingViewModel mCrossSimCallingViewModel;
|
||||
@Nullable
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
public AutoDataSwitchPreferenceController(
|
||||
@@ -72,10 +69,9 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
|
||||
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 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
|
||||
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
|
||||
isChecked);
|
||||
}
|
||||
if (mCrossSimCallingViewModel != null) {
|
||||
mCrossSimCallingViewModel.updateCrossSimCalling();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.conflate
|
||||
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 @@ class DataSubscriptionRepository(
|
||||
.onStart { emit(SubscriptionManager.getDefaultDataSubscriptionId()) }
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
.onEach { Log.d(TAG, "defaultDataSubscriptionIdFlow: $it") }
|
||||
.flowOn(Dispatchers.Default)
|
||||
|
||||
fun activeDataSubscriptionIdFlow(): Flow<Int> =
|
||||
|
@@ -247,9 +247,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
|
||||
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);
|
||||
|
@@ -24,22 +24,22 @@ import android.telephony.TelephonyManager
|
||||
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 @@ class CrossSimCallingViewModel(
|
||||
) : 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 @@ class CrossSimCallingViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,9 @@ fun AutomaticDataSwitchingPreference(
|
||||
) {
|
||||
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 @@ fun AutomaticDataSwitchingPreference(
|
||||
override val onCheckedChange: (Boolean) -> Unit = { newEnabled ->
|
||||
coroutineScope.launch(Dispatchers.Default) {
|
||||
setAutoDataEnabled(newEnabled)
|
||||
crossSimCallingViewModel.updateCrossSimCalling()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -85,7 +85,7 @@ public class AutoDataSwitchPreferenceControllerTest {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
mController.init(SUB_ID_1, null);
|
||||
mController.init(SUB_ID_1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Reference in New Issue
Block a user