Loading src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java +1 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -63,8 +62,6 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc @Nullable private MobileDataContentObserver mMobileDataContentObserver; @Nullable private CrossSimCallingViewModel mCrossSimCallingViewModel; @Nullable private PreferenceScreen mScreen; public AutoDataSwitchPreferenceController( Loading @@ -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) Loading Loading @@ -122,9 +118,6 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, isChecked); } if (mCrossSimCallingViewModel != null) { mCrossSimCallingViewModel.updateCrossSimCalling(); } return true; } Loading src/com/android/settings/network/telephony/DataSubscriptionRepository.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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( Loading @@ -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> = Loading src/com/android/settings/network/telephony/MobileNetworkSettings.java +4 −3 Original line number Diff line number Diff line Loading @@ -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 = // CrossSimCallingViewModel is responsible for maintaining the correct cross sim calling // settings (backup calling). new ViewModelProvider(this).get(CrossSimCallingViewModel.class); use(AutoDataSwitchPreferenceController.class).init(mSubId, crossSimCallingViewModel); use(AutoDataSwitchPreferenceController.class).init(mSubId); use(DisabledSubscriptionController.class).init(mSubId); use(DeleteSimProfilePreferenceController.class).init(mSubId); use(DisableSimFooterPreferenceController.class).init(mSubId); Loading src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt +36 −45 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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) -> Loading @@ -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) 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) carrierConfigRepository.getBoolean( subId, CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL) 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 } } } src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt +3 −2 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -43,7 +45,6 @@ fun AutomaticDataSwitchingPreference( override val onCheckedChange: (Boolean) -> Unit = { newEnabled -> coroutineScope.launch(Dispatchers.Default) { setAutoDataEnabled(newEnabled) crossSimCallingViewModel.updateCrossSimCalling() } } } Loading Loading
src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java +1 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -63,8 +62,6 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc @Nullable private MobileDataContentObserver mMobileDataContentObserver; @Nullable private CrossSimCallingViewModel mCrossSimCallingViewModel; @Nullable private PreferenceScreen mScreen; public AutoDataSwitchPreferenceController( Loading @@ -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) Loading Loading @@ -122,9 +118,6 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, isChecked); } if (mCrossSimCallingViewModel != null) { mCrossSimCallingViewModel.updateCrossSimCalling(); } return true; } Loading
src/com/android/settings/network/telephony/DataSubscriptionRepository.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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( Loading @@ -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> = Loading
src/com/android/settings/network/telephony/MobileNetworkSettings.java +4 −3 Original line number Diff line number Diff line Loading @@ -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 = // CrossSimCallingViewModel is responsible for maintaining the correct cross sim calling // settings (backup calling). new ViewModelProvider(this).get(CrossSimCallingViewModel.class); use(AutoDataSwitchPreferenceController.class).init(mSubId, crossSimCallingViewModel); use(AutoDataSwitchPreferenceController.class).init(mSubId); use(DisabledSubscriptionController.class).init(mSubId); use(DeleteSimProfilePreferenceController.class).init(mSubId); use(DisableSimFooterPreferenceController.class).init(mSubId); Loading
src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt +36 −45 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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) -> Loading @@ -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) 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) carrierConfigRepository.getBoolean( subId, CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL) 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 } } }
src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt +3 −2 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -43,7 +45,6 @@ fun AutomaticDataSwitchingPreference( override val onCheckedChange: (Boolean) -> Unit = { newEnabled -> coroutineScope.launch(Dispatchers.Default) { setAutoDataEnabled(newEnabled) crossSimCallingViewModel.updateCrossSimCalling() } } } Loading