Loading src/com/android/settings/network/SimOnboardingActivity.kt +16 −1 Original line number Diff line number Diff line Loading @@ -46,15 +46,18 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.LifecycleRegistry import com.android.settings.R import com.android.settings.SidecarFragment import com.android.settings.network.telephony.SubscriptionActionDialogActivity import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity import com.android.settings.spa.SpaActivity.Companion.startSpaActivity import com.android.settings.spa.network.SimOnboardingPageProvider.getRoute import com.android.settings.wifi.WifiPickerTrackerHelper import com.android.settingslib.spa.SpaBaseDialogActivity import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle Loading @@ -74,6 +77,8 @@ import kotlinx.coroutines.launch class SimOnboardingActivity : SpaBaseDialogActivity() { lateinit var scope: CoroutineScope lateinit var wifiPickerTrackerHelper: WifiPickerTrackerHelper lateinit var context: Context lateinit var showStartingDialog: MutableState<Boolean> lateinit var showError: MutableState<ErrorType> lateinit var showProgressDialog: MutableState<Boolean> Loading @@ -86,6 +91,7 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (!this.userManager.isAdminUser) { Log.e(TAG, "It is not the admin user. Unable to toggle subscription.") finish() Loading Loading @@ -152,7 +158,10 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { CallbackType.CALLBACK_SETUP_PRIMARY_SIM -> { scope.launch { onboardingService.startSetupPrimarySim(this@SimOnboardingActivity) onboardingService.startSetupPrimarySim( this@SimOnboardingActivity, wifiPickerTrackerHelper ) } } Loading Loading @@ -184,6 +193,12 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { showDsdsProgressDialog = rememberSaveable { mutableStateOf(false) } showRestartDialog = rememberSaveable { mutableStateOf(false) } scope = rememberCoroutineScope() context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current wifiPickerTrackerHelper = WifiPickerTrackerHelper( LifecycleRegistry(lifecycleOwner), context, null /* WifiPickerTrackerCallback */ ) registerSidecarReceiverFlow() Loading src/com/android/settings/network/SimOnboardingService.kt +6 −2 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.settings.spa.network.setAutomaticData import com.android.settings.spa.network.setDefaultData import com.android.settings.spa.network.setDefaultSms import com.android.settings.spa.network.setDefaultVoice import com.android.settings.wifi.WifiPickerTrackerHelper import com.android.settingslib.utils.ThreadUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow Loading Loading @@ -336,14 +337,17 @@ class SimOnboardingService { } } suspend fun startSetupPrimarySim(context: Context) { suspend fun startSetupPrimarySim( context: Context, wifiPickerTrackerHelper: WifiPickerTrackerHelper ) { withContext(Dispatchers.Default) { setDefaultVoice(subscriptionManager, targetPrimarySimCalls) setDefaultSms(subscriptionManager, targetPrimarySimTexts) setDefaultData( context, subscriptionManager, null, wifiPickerTrackerHelper, targetPrimarySimMobileData ) TelephonyRepository(context).setAutomaticData( Loading src/com/android/settings/network/telephony/TelephonyRepository.kt +38 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.telephony.SubscriptionManager import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.util.Log import com.android.settings.network.mobileDataEnabledFlow import com.android.settings.wifi.WifiPickerTrackerHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor import kotlinx.coroutines.channels.ProducerScope Loading Loading @@ -62,6 +64,42 @@ class TelephonyRepository( telephonyManager.setMobileDataPolicyEnabled(policy, enabled) } fun isDataEnabled( subId: Int, ): Flow<Boolean> { if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false) Log.d(TAG, "register mobileDataEnabledFlow: [$subId]") return context.mobileDataEnabledFlow(subId) .map { Log.d(TAG, "mobileDataEnabledFlow: receive mobile data [$subId] start") val telephonyManager = context.telephonyManager(subId) telephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER) .also { Log.d(TAG, "mobileDataEnabledFlow: [$subId] isDataEnabled(): $it") } } } fun setMobileData( subId: Int, enabled: Boolean, wifiPickerTrackerHelper: WifiPickerTrackerHelper? = null ) { if (!SubscriptionManager.isValidSubscriptionId(subId)) return Log.d(TAG, "setMobileData: $enabled") MobileNetworkUtils.setMobileDataEnabled( context, subId, enabled /* enabled */, true /* disableOtherSubscriptions */ ) if (wifiPickerTrackerHelper != null && !wifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(subId) ) { wifiPickerTrackerHelper.setCarrierNetworkEnabled(enabled) } } private companion object { private const val TAG = "TelephonyRepository" } Loading src/com/android/settings/spa/network/MobileDataSwitchingPreference.kt 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.spa.network import android.telephony.TelephonyManager import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.res.stringResource import com.android.settings.R import com.android.settings.network.telephony.TelephonyRepository import com.android.settingslib.spa.widget.preference.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @Composable fun MobileDataSwitchingPreference( isMobileDataEnabled: () -> Boolean?, setMobileDataEnabled: (newEnabled: Boolean) -> Unit, ) { val mobileDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg) val coroutineScope = rememberCoroutineScope() SwitchPreference( object : SwitchPreferenceModel { override val title = stringResource(id = R.string.mobile_data_settings_title) override val summary = { mobileDataSummary } override val checked = { isMobileDataEnabled() } override val onCheckedChange: (Boolean) -> Unit = { newEnabled -> coroutineScope.launch(Dispatchers.Default) { setMobileDataEnabled(newEnabled) } } override val changeable:() -> Boolean = {true} } ) } src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt +94 −35 Original line number Diff line number Diff line Loading @@ -38,11 +38,12 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.android.settings.R import com.android.settings.network.SubscriptionInfoListViewModel import com.android.settings.network.telephony.MobileNetworkUtils import com.android.settings.network.telephony.TelephonyRepository import com.android.settings.spa.network.PrimarySimRepository.PrimarySimInfo import com.android.settings.wifi.WifiPickerTrackerHelper Loading Loading @@ -167,7 +168,7 @@ fun PageImpl( defaultVoiceSubId: MutableIntState, defaultSmsSubId: MutableIntState, defaultDataSubId: MutableIntState, nonDds: MutableIntState nonDds: MutableIntState, ) { val selectableSubscriptionInfoList by selectableSubscriptionInfoListFlow .collectAsStateWithLifecycle(initialValue = emptyList()) Loading @@ -175,22 +176,76 @@ fun PageImpl( val stringSims = stringResource(R.string.provider_network_settings_title) RegularScaffold(title = stringSims) { SimsSection(selectableSubscriptionInfoList) MobileDataSectionImpl(defaultDataSubId, nonDds, ) PrimarySimSectionImpl( selectableSubscriptionInfoListFlow, defaultVoiceSubId, defaultSmsSubId, defaultDataSubId, nonDds ) } } @Composable fun MobileDataSectionImpl( mobileDataSelectedId: MutableIntState, nonDds: MutableIntState, ) { val context = LocalContext.current val localLifecycleOwner = LocalLifecycleOwner.current val wifiPickerTrackerHelper = getWifiPickerTrackerHelper(context, localLifecycleOwner) val subscriptionManager: SubscriptionManager? = context.getSystemService(SubscriptionManager::class.java) Category(title = stringResource(id = R.string.mobile_data_settings_title)) { val isAutoDataEnabled by remember(nonDds.intValue) { TelephonyRepository(context).isMobileDataPolicyEnabledFlow( subId = nonDds.intValue, policy = TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH ) }.collectAsStateWithLifecycle(initialValue = null) val mobileDataStateChanged by remember(mobileDataSelectedId.intValue) { TelephonyRepository(context).isDataEnabled(mobileDataSelectedId.intValue) }.collectAsStateWithLifecycle(initialValue = false) val coroutineScope = rememberCoroutineScope() MobileDataSwitchingPreference( isMobileDataEnabled = { mobileDataStateChanged }, setMobileDataEnabled = { newEnabled -> coroutineScope.launch { setMobileData( context, subscriptionManager, wifiPickerTrackerHelper, mobileDataSelectedId.intValue, newEnabled ) } }, ) if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { AutomaticDataSwitchingPreference( isAutoDataEnabled = { isAutoDataEnabled }, setAutoDataEnabled = { newEnabled -> TelephonyRepository(context).setAutomaticData(nonDds.intValue, newEnabled) }, ) } } } @Composable fun PrimarySimImpl( primarySimInfo: PrimarySimInfo, callsSelectedId: MutableIntState, textsSelectedId: MutableIntState, mobileDataSelectedId: MutableIntState, wifiPickerTrackerHelper: WifiPickerTrackerHelper? = null, subscriptionManager: SubscriptionManager? = LocalContext.current.getSystemService(SubscriptionManager::class.java), coroutineScope: CoroutineScope = rememberCoroutineScope(), Loading @@ -208,20 +263,15 @@ fun PrimarySimImpl( } }, actionSetMobileData: (Int) -> Unit = { mobileDataSelectedId.intValue = it coroutineScope.launch { // TODO: to fix the WifiPickerTracker crash when create // the wifiPickerTrackerHelper setDefaultData( context, subscriptionManager, null/*wifiPickerTrackerHelper*/, wifiPickerTrackerHelper, it ) } }, isAutoDataEnabled: () -> Boolean?, setAutoDataEnabled: (newEnabled: Boolean) -> Unit, ) { CreatePrimarySimListPreference( stringResource(id = R.string.primary_sim_calls_title), Loading @@ -244,8 +294,6 @@ fun PrimarySimImpl( Icons.Outlined.DataUsage, actionSetMobileData ) AutomaticDataSwitchingPreference(isAutoDataEnabled, setAutoDataEnabled) } @Composable Loading @@ -254,9 +302,11 @@ fun PrimarySimSectionImpl( callsSelectedId: MutableIntState, textsSelectedId: MutableIntState, mobileDataSelectedId: MutableIntState, nonDds: MutableIntState, ) { val context = LocalContext.current val localLifecycleOwner = LocalLifecycleOwner.current val wifiPickerTrackerHelper = getWifiPickerTrackerHelper(context, localLifecycleOwner) val primarySimInfo = remember(subscriptionInfoListFlow) { subscriptionInfoListFlow .map { subscriptionInfoList -> Loading @@ -267,25 +317,25 @@ fun PrimarySimSectionImpl( }.collectAsStateWithLifecycle(initialValue = null).value ?: return Category(title = stringResource(id = R.string.primary_sim_title)) { val isAutoDataEnabled by remember(nonDds.intValue) { TelephonyRepository(context).isMobileDataPolicyEnabledFlow( subId = nonDds.intValue, policy = TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH ) }.collectAsStateWithLifecycle(initialValue = null) PrimarySimImpl( primarySimInfo, callsSelectedId, textsSelectedId, mobileDataSelectedId, isAutoDataEnabled = { isAutoDataEnabled }, setAutoDataEnabled = { newEnabled -> TelephonyRepository(context).setAutomaticData(nonDds.intValue, newEnabled) }, wifiPickerTrackerHelper ) } } private fun getWifiPickerTrackerHelper( context: Context, lifecycleOwner: LifecycleOwner ): WifiPickerTrackerHelper { return WifiPickerTrackerHelper( LifecycleRegistry(lifecycleOwner), context, null /* WifiPickerTrackerCallback */ ) } private fun Context.defaultVoiceSubscriptionFlow(): Flow<Int> = merge( flowOf(null), // kick an initial value Loading Loading @@ -335,18 +385,27 @@ suspend fun setDefaultData( wifiPickerTrackerHelper: WifiPickerTrackerHelper?, subId: Int ): Unit = withContext(Dispatchers.Default) { subscriptionManager?.setDefaultDataSubId(subId) Log.d(NetworkCellularGroupProvider.name, "setMobileDataEnabled: true") MobileNetworkUtils.setMobileDataEnabled( setMobileData( context, subscriptionManager, wifiPickerTrackerHelper, subId, true /* enabled */, true /* disableOtherSubscriptions */ true ) if (wifiPickerTrackerHelper != null && !wifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(subId) ) { wifiPickerTrackerHelper.setCarrierNetworkEnabled(true) suspend fun setMobileData( context: Context, subscriptionManager: SubscriptionManager?, wifiPickerTrackerHelper: WifiPickerTrackerHelper?, subId: Int, enabled: Boolean, ): Unit = withContext(Dispatchers.Default) { Log.d(NetworkCellularGroupProvider.name, "setMobileData: $enabled") if (enabled) { Log.d(NetworkCellularGroupProvider.name, "setDefaultData: [$subId]") subscriptionManager?.setDefaultDataSubId(subId) } TelephonyRepository(context) .setMobileData(subId, enabled, wifiPickerTrackerHelper) } No newline at end of file Loading
src/com/android/settings/network/SimOnboardingActivity.kt +16 −1 Original line number Diff line number Diff line Loading @@ -46,15 +46,18 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.LifecycleRegistry import com.android.settings.R import com.android.settings.SidecarFragment import com.android.settings.network.telephony.SubscriptionActionDialogActivity import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity import com.android.settings.spa.SpaActivity.Companion.startSpaActivity import com.android.settings.spa.network.SimOnboardingPageProvider.getRoute import com.android.settings.wifi.WifiPickerTrackerHelper import com.android.settingslib.spa.SpaBaseDialogActivity import com.android.settingslib.spa.framework.theme.SettingsDimension import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle Loading @@ -74,6 +77,8 @@ import kotlinx.coroutines.launch class SimOnboardingActivity : SpaBaseDialogActivity() { lateinit var scope: CoroutineScope lateinit var wifiPickerTrackerHelper: WifiPickerTrackerHelper lateinit var context: Context lateinit var showStartingDialog: MutableState<Boolean> lateinit var showError: MutableState<ErrorType> lateinit var showProgressDialog: MutableState<Boolean> Loading @@ -86,6 +91,7 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (!this.userManager.isAdminUser) { Log.e(TAG, "It is not the admin user. Unable to toggle subscription.") finish() Loading Loading @@ -152,7 +158,10 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { CallbackType.CALLBACK_SETUP_PRIMARY_SIM -> { scope.launch { onboardingService.startSetupPrimarySim(this@SimOnboardingActivity) onboardingService.startSetupPrimarySim( this@SimOnboardingActivity, wifiPickerTrackerHelper ) } } Loading Loading @@ -184,6 +193,12 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { showDsdsProgressDialog = rememberSaveable { mutableStateOf(false) } showRestartDialog = rememberSaveable { mutableStateOf(false) } scope = rememberCoroutineScope() context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current wifiPickerTrackerHelper = WifiPickerTrackerHelper( LifecycleRegistry(lifecycleOwner), context, null /* WifiPickerTrackerCallback */ ) registerSidecarReceiverFlow() Loading
src/com/android/settings/network/SimOnboardingService.kt +6 −2 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.settings.spa.network.setAutomaticData import com.android.settings.spa.network.setDefaultData import com.android.settings.spa.network.setDefaultSms import com.android.settings.spa.network.setDefaultVoice import com.android.settings.wifi.WifiPickerTrackerHelper import com.android.settingslib.utils.ThreadUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow Loading Loading @@ -336,14 +337,17 @@ class SimOnboardingService { } } suspend fun startSetupPrimarySim(context: Context) { suspend fun startSetupPrimarySim( context: Context, wifiPickerTrackerHelper: WifiPickerTrackerHelper ) { withContext(Dispatchers.Default) { setDefaultVoice(subscriptionManager, targetPrimarySimCalls) setDefaultSms(subscriptionManager, targetPrimarySimTexts) setDefaultData( context, subscriptionManager, null, wifiPickerTrackerHelper, targetPrimarySimMobileData ) TelephonyRepository(context).setAutomaticData( Loading
src/com/android/settings/network/telephony/TelephonyRepository.kt +38 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.telephony.SubscriptionManager import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.util.Log import com.android.settings.network.mobileDataEnabledFlow import com.android.settings.wifi.WifiPickerTrackerHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor import kotlinx.coroutines.channels.ProducerScope Loading Loading @@ -62,6 +64,42 @@ class TelephonyRepository( telephonyManager.setMobileDataPolicyEnabled(policy, enabled) } fun isDataEnabled( subId: Int, ): Flow<Boolean> { if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false) Log.d(TAG, "register mobileDataEnabledFlow: [$subId]") return context.mobileDataEnabledFlow(subId) .map { Log.d(TAG, "mobileDataEnabledFlow: receive mobile data [$subId] start") val telephonyManager = context.telephonyManager(subId) telephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER) .also { Log.d(TAG, "mobileDataEnabledFlow: [$subId] isDataEnabled(): $it") } } } fun setMobileData( subId: Int, enabled: Boolean, wifiPickerTrackerHelper: WifiPickerTrackerHelper? = null ) { if (!SubscriptionManager.isValidSubscriptionId(subId)) return Log.d(TAG, "setMobileData: $enabled") MobileNetworkUtils.setMobileDataEnabled( context, subId, enabled /* enabled */, true /* disableOtherSubscriptions */ ) if (wifiPickerTrackerHelper != null && !wifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(subId) ) { wifiPickerTrackerHelper.setCarrierNetworkEnabled(enabled) } } private companion object { private const val TAG = "TelephonyRepository" } Loading
src/com/android/settings/spa/network/MobileDataSwitchingPreference.kt 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.spa.network import android.telephony.TelephonyManager import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.res.stringResource import com.android.settings.R import com.android.settings.network.telephony.TelephonyRepository import com.android.settingslib.spa.widget.preference.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @Composable fun MobileDataSwitchingPreference( isMobileDataEnabled: () -> Boolean?, setMobileDataEnabled: (newEnabled: Boolean) -> Unit, ) { val mobileDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg) val coroutineScope = rememberCoroutineScope() SwitchPreference( object : SwitchPreferenceModel { override val title = stringResource(id = R.string.mobile_data_settings_title) override val summary = { mobileDataSummary } override val checked = { isMobileDataEnabled() } override val onCheckedChange: (Boolean) -> Unit = { newEnabled -> coroutineScope.launch(Dispatchers.Default) { setMobileDataEnabled(newEnabled) } } override val changeable:() -> Boolean = {true} } ) }
src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt +94 −35 Original line number Diff line number Diff line Loading @@ -38,11 +38,12 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.android.settings.R import com.android.settings.network.SubscriptionInfoListViewModel import com.android.settings.network.telephony.MobileNetworkUtils import com.android.settings.network.telephony.TelephonyRepository import com.android.settings.spa.network.PrimarySimRepository.PrimarySimInfo import com.android.settings.wifi.WifiPickerTrackerHelper Loading Loading @@ -167,7 +168,7 @@ fun PageImpl( defaultVoiceSubId: MutableIntState, defaultSmsSubId: MutableIntState, defaultDataSubId: MutableIntState, nonDds: MutableIntState nonDds: MutableIntState, ) { val selectableSubscriptionInfoList by selectableSubscriptionInfoListFlow .collectAsStateWithLifecycle(initialValue = emptyList()) Loading @@ -175,22 +176,76 @@ fun PageImpl( val stringSims = stringResource(R.string.provider_network_settings_title) RegularScaffold(title = stringSims) { SimsSection(selectableSubscriptionInfoList) MobileDataSectionImpl(defaultDataSubId, nonDds, ) PrimarySimSectionImpl( selectableSubscriptionInfoListFlow, defaultVoiceSubId, defaultSmsSubId, defaultDataSubId, nonDds ) } } @Composable fun MobileDataSectionImpl( mobileDataSelectedId: MutableIntState, nonDds: MutableIntState, ) { val context = LocalContext.current val localLifecycleOwner = LocalLifecycleOwner.current val wifiPickerTrackerHelper = getWifiPickerTrackerHelper(context, localLifecycleOwner) val subscriptionManager: SubscriptionManager? = context.getSystemService(SubscriptionManager::class.java) Category(title = stringResource(id = R.string.mobile_data_settings_title)) { val isAutoDataEnabled by remember(nonDds.intValue) { TelephonyRepository(context).isMobileDataPolicyEnabledFlow( subId = nonDds.intValue, policy = TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH ) }.collectAsStateWithLifecycle(initialValue = null) val mobileDataStateChanged by remember(mobileDataSelectedId.intValue) { TelephonyRepository(context).isDataEnabled(mobileDataSelectedId.intValue) }.collectAsStateWithLifecycle(initialValue = false) val coroutineScope = rememberCoroutineScope() MobileDataSwitchingPreference( isMobileDataEnabled = { mobileDataStateChanged }, setMobileDataEnabled = { newEnabled -> coroutineScope.launch { setMobileData( context, subscriptionManager, wifiPickerTrackerHelper, mobileDataSelectedId.intValue, newEnabled ) } }, ) if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { AutomaticDataSwitchingPreference( isAutoDataEnabled = { isAutoDataEnabled }, setAutoDataEnabled = { newEnabled -> TelephonyRepository(context).setAutomaticData(nonDds.intValue, newEnabled) }, ) } } } @Composable fun PrimarySimImpl( primarySimInfo: PrimarySimInfo, callsSelectedId: MutableIntState, textsSelectedId: MutableIntState, mobileDataSelectedId: MutableIntState, wifiPickerTrackerHelper: WifiPickerTrackerHelper? = null, subscriptionManager: SubscriptionManager? = LocalContext.current.getSystemService(SubscriptionManager::class.java), coroutineScope: CoroutineScope = rememberCoroutineScope(), Loading @@ -208,20 +263,15 @@ fun PrimarySimImpl( } }, actionSetMobileData: (Int) -> Unit = { mobileDataSelectedId.intValue = it coroutineScope.launch { // TODO: to fix the WifiPickerTracker crash when create // the wifiPickerTrackerHelper setDefaultData( context, subscriptionManager, null/*wifiPickerTrackerHelper*/, wifiPickerTrackerHelper, it ) } }, isAutoDataEnabled: () -> Boolean?, setAutoDataEnabled: (newEnabled: Boolean) -> Unit, ) { CreatePrimarySimListPreference( stringResource(id = R.string.primary_sim_calls_title), Loading @@ -244,8 +294,6 @@ fun PrimarySimImpl( Icons.Outlined.DataUsage, actionSetMobileData ) AutomaticDataSwitchingPreference(isAutoDataEnabled, setAutoDataEnabled) } @Composable Loading @@ -254,9 +302,11 @@ fun PrimarySimSectionImpl( callsSelectedId: MutableIntState, textsSelectedId: MutableIntState, mobileDataSelectedId: MutableIntState, nonDds: MutableIntState, ) { val context = LocalContext.current val localLifecycleOwner = LocalLifecycleOwner.current val wifiPickerTrackerHelper = getWifiPickerTrackerHelper(context, localLifecycleOwner) val primarySimInfo = remember(subscriptionInfoListFlow) { subscriptionInfoListFlow .map { subscriptionInfoList -> Loading @@ -267,25 +317,25 @@ fun PrimarySimSectionImpl( }.collectAsStateWithLifecycle(initialValue = null).value ?: return Category(title = stringResource(id = R.string.primary_sim_title)) { val isAutoDataEnabled by remember(nonDds.intValue) { TelephonyRepository(context).isMobileDataPolicyEnabledFlow( subId = nonDds.intValue, policy = TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH ) }.collectAsStateWithLifecycle(initialValue = null) PrimarySimImpl( primarySimInfo, callsSelectedId, textsSelectedId, mobileDataSelectedId, isAutoDataEnabled = { isAutoDataEnabled }, setAutoDataEnabled = { newEnabled -> TelephonyRepository(context).setAutomaticData(nonDds.intValue, newEnabled) }, wifiPickerTrackerHelper ) } } private fun getWifiPickerTrackerHelper( context: Context, lifecycleOwner: LifecycleOwner ): WifiPickerTrackerHelper { return WifiPickerTrackerHelper( LifecycleRegistry(lifecycleOwner), context, null /* WifiPickerTrackerCallback */ ) } private fun Context.defaultVoiceSubscriptionFlow(): Flow<Int> = merge( flowOf(null), // kick an initial value Loading Loading @@ -335,18 +385,27 @@ suspend fun setDefaultData( wifiPickerTrackerHelper: WifiPickerTrackerHelper?, subId: Int ): Unit = withContext(Dispatchers.Default) { subscriptionManager?.setDefaultDataSubId(subId) Log.d(NetworkCellularGroupProvider.name, "setMobileDataEnabled: true") MobileNetworkUtils.setMobileDataEnabled( setMobileData( context, subscriptionManager, wifiPickerTrackerHelper, subId, true /* enabled */, true /* disableOtherSubscriptions */ true ) if (wifiPickerTrackerHelper != null && !wifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(subId) ) { wifiPickerTrackerHelper.setCarrierNetworkEnabled(true) suspend fun setMobileData( context: Context, subscriptionManager: SubscriptionManager?, wifiPickerTrackerHelper: WifiPickerTrackerHelper?, subId: Int, enabled: Boolean, ): Unit = withContext(Dispatchers.Default) { Log.d(NetworkCellularGroupProvider.name, "setMobileData: $enabled") if (enabled) { Log.d(NetworkCellularGroupProvider.name, "setDefaultData: [$subId]") subscriptionManager?.setDefaultDataSubId(subId) } TelephonyRepository(context) .setMobileData(subId, enabled, wifiPickerTrackerHelper) } No newline at end of file