Merge "Always set cross sim calling" into main

This commit is contained in:
Chaohui Wang
2024-07-17 07:48:59 +00:00
committed by Android (Google) Code Review
6 changed files with 47 additions and 59 deletions

View File

@@ -38,7 +38,6 @@ import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.flags.Flags; import com.android.settings.flags.Flags;
import com.android.settings.network.MobileDataContentObserver; import com.android.settings.network.MobileDataContentObserver;
import com.android.settings.network.SubscriptionsChangeListener; 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 * 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 @Nullable
private MobileDataContentObserver mMobileDataContentObserver; private MobileDataContentObserver mMobileDataContentObserver;
@Nullable @Nullable
private CrossSimCallingViewModel mCrossSimCallingViewModel;
@Nullable
private PreferenceScreen mScreen; private PreferenceScreen mScreen;
public AutoDataSwitchPreferenceController( public AutoDataSwitchPreferenceController(
@@ -72,10 +69,9 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
super(context, preferenceKey); super(context, preferenceKey);
} }
void init(int subId, @Nullable CrossSimCallingViewModel crossSimCallingViewModel) { void init(int subId) {
this.mSubId = subId; this.mSubId = subId;
mManager = mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(subId); mManager = mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
mCrossSimCallingViewModel = crossSimCallingViewModel;
} }
@OnLifecycleEvent(ON_RESUME) @OnLifecycleEvent(ON_RESUME)
@@ -122,9 +118,6 @@ public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenc
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
isChecked); isChecked);
} }
if (mCrossSimCallingViewModel != null) {
mCrossSimCallingViewModel.updateCrossSimCalling();
}
return true; return true;
} }

View File

@@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
class DataSubscriptionRepository( class DataSubscriptionRepository(
@@ -53,6 +54,7 @@ class DataSubscriptionRepository(
.onStart { emit(SubscriptionManager.getDefaultDataSubscriptionId()) } .onStart { emit(SubscriptionManager.getDefaultDataSubscriptionId()) }
.distinctUntilChanged() .distinctUntilChanged()
.conflate() .conflate()
.onEach { Log.d(TAG, "defaultDataSubscriptionIdFlow: $it") }
.flowOn(Dispatchers.Default) .flowOn(Dispatchers.Default)
fun activeDataSubscriptionIdFlow(): Flow<Int> = fun activeDataSubscriptionIdFlow(): Flow<Int> =

View File

@@ -247,9 +247,10 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
use(CarrierSettingsVersionPreferenceController.class).init(mSubId); use(CarrierSettingsVersionPreferenceController.class).init(mSubId);
use(BillingCyclePreferenceController.class).init(mSubId); use(BillingCyclePreferenceController.class).init(mSubId);
use(MmsMessagePreferenceController.class).init(mSubId); use(MmsMessagePreferenceController.class).init(mSubId);
final var crossSimCallingViewModel = // CrossSimCallingViewModel is responsible for maintaining the correct cross sim calling
new ViewModelProvider(this).get(CrossSimCallingViewModel.class); // settings (backup calling).
use(AutoDataSwitchPreferenceController.class).init(mSubId, crossSimCallingViewModel); new ViewModelProvider(this).get(CrossSimCallingViewModel.class);
use(AutoDataSwitchPreferenceController.class).init(mSubId);
use(DisabledSubscriptionController.class).init(mSubId); use(DisabledSubscriptionController.class).init(mSubId);
use(DeleteSimProfilePreferenceController.class).init(mSubId); use(DeleteSimProfilePreferenceController.class).init(mSubId);
use(DisableSimFooterPreferenceController.class).init(mSubId); use(DisableSimFooterPreferenceController.class).init(mSubId);

View File

@@ -24,22 +24,22 @@ import android.telephony.TelephonyManager
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.android.settings.R 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.MobileDataRepository
import com.android.settings.network.telephony.SubscriptionRepository import com.android.settings.network.telephony.SubscriptionRepository
import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl 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 com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi 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.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.plus import kotlinx.coroutines.plus
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
@@ -48,24 +48,23 @@ class CrossSimCallingViewModel(
) : AndroidViewModel(application) { ) : AndroidViewModel(application) {
private val subscriptionRepository = SubscriptionRepository(application) private val subscriptionRepository = SubscriptionRepository(application)
private val carrierConfigManager = private val dataSubscriptionRepository = DataSubscriptionRepository(application)
application.getSystemService(CarrierConfigManager::class.java)!! private val mobileDataRepository = MobileDataRepository(application)
private val carrierConfigRepository = CarrierConfigRepository(application)
private val scope = viewModelScope + Dispatchers.Default private val scope = viewModelScope + Dispatchers.Default
private val metricsFeatureProvider = featureFactory.metricsFeatureProvider private val metricsFeatureProvider = featureFactory.metricsFeatureProvider
private val updateChannel = Channel<Unit>()
private val mobileDataRepository = MobileDataRepository(application)
init { init {
val resources = application.resources val resources = application.resources
if (resources.getBoolean(R.bool.config_auto_data_switch_enables_cross_sim_calling)) { if (resources.getBoolean(R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
subscriptionRepository.activeSubscriptionIdListFlow() combine(
.flatMapLatest { activeSubIds -> subscriptionRepository.activeSubscriptionIdListFlow(),
merge( dataSubscriptionRepository.defaultDataSubscriptionIdFlow(),
activeSubIds.anyMobileDataEnableChangedFlow(), ) { activeSubIds, defaultDataSubId ->
updateChannel.receiveAsFlow(), activeSubIds to crossSimCallNewEnabled(activeSubIds, defaultDataSubId)
).map { }
activeSubIds to crossSimCallNewEnabled(activeSubIds) .flatMapLatest { (activeSubIds, newEnabledFlow) ->
} newEnabledFlow.map { newEnabled -> activeSubIds to newEnabled }
} }
.distinctUntilChanged() .distinctUntilChanged()
.onEach { (activeSubIds, newEnabled) -> .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) { private suspend fun updateCrossSimCalling(activeSubIds: List<Int>, newEnabled: Boolean) {
metricsFeatureProvider.action( metricsFeatureProvider.action(
application, application,
SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT, SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT,
newEnabled, newEnabled,
) )
activeSubIds.filter { crossSimAvailable(it) }.forEach { subId -> activeSubIds
ImsMmTelRepositoryImpl(application, subId) .filter { subId -> crossSimAvailable(subId) }
.setCrossSimCallingEnabled(newEnabled) .forEach { subId ->
} ImsMmTelRepositoryImpl(application, subId).setCrossSimCallingEnabled(newEnabled)
}
} }
private suspend fun crossSimAvailable(subId: Int): Boolean = private suspend fun crossSimAvailable(subId: Int): Boolean =
WifiCallingRepository(application, subId).isWifiCallingSupported() && WifiCallingRepository(application, subId).isWifiCallingSupported() &&
crossSimImsAvailable(subId) carrierConfigRepository.getBoolean(
subId, CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL)
private fun crossSimImsAvailable(subId: Int): Boolean = private fun crossSimCallNewEnabled(
carrierConfigManager.safeGetConfig( activeSubscriptionIdList: List<Int>,
keys = listOf(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL), defaultDataSubId: Int,
subId = subId, ): Flow<Boolean> {
).getBoolean(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false) if (!SubscriptionManager.isValidSubscriptionId(defaultDataSubId)) return flowOf(false)
val isMobileDataPolicyEnabledFlows =
private fun crossSimCallNewEnabled(activeSubscriptionIdList: List<Int>): Boolean { activeSubscriptionIdList
val defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId() .filter { subId -> subId != defaultDataSubId }
return SubscriptionManager.isValidSubscriptionId(defaultDataSubId) && .map { subId ->
activeSubscriptionIdList.any { subId -> mobileDataRepository.isMobileDataPolicyEnabledFlow(
subId != defaultDataSubId && subId, TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
application.telephonyManager(subId).isMobileDataPolicyEnabled( }
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH return combine(isMobileDataPolicyEnabledFlows) { true in it }
)
}
} }
} }

View File

@@ -34,7 +34,9 @@ fun AutomaticDataSwitchingPreference(
) { ) {
val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg) val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
val coroutineScope = rememberCoroutineScope() 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( SwitchPreference(
object : SwitchPreferenceModel { object : SwitchPreferenceModel {
override val title = stringResource(id = R.string.primary_sim_automatic_data_title) override val title = stringResource(id = R.string.primary_sim_automatic_data_title)
@@ -43,7 +45,6 @@ fun AutomaticDataSwitchingPreference(
override val onCheckedChange: (Boolean) -> Unit = { newEnabled -> override val onCheckedChange: (Boolean) -> Unit = { newEnabled ->
coroutineScope.launch(Dispatchers.Default) { coroutineScope.launch(Dispatchers.Default) {
setAutoDataEnabled(newEnabled) setAutoDataEnabled(newEnabled)
crossSimCallingViewModel.updateCrossSimCalling()
} }
} }
} }

View File

@@ -85,7 +85,7 @@ public class AutoDataSwitchPreferenceControllerTest {
return true; return true;
} }
}; };
mController.init(SUB_ID_1, null); mController.init(SUB_ID_1);
} }
@Test @Test