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.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;
}

View File

@@ -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> =

View File

@@ -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);

View File

@@ -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 }
}
}

View File

@@ -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()
}
}
}

View File

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