Loading src/com/android/settings/network/apn/ApnEditPageProvider.kt +52 −32 Original line number Diff line number Diff line Loading @@ -40,6 +40,10 @@ import androidx.navigation.navArgument import com.android.settings.R import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNames import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState import com.android.settings.network.apn.ApnTypes.APN_TYPES_OPTIONS import com.android.settings.network.apn.ApnTypes.APN_TYPE_MMS import com.android.settings.network.apn.ApnTypes.getApnTypeSelectedOptionsState import com.android.settings.network.apn.ApnTypes.updateApnType import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.LocalNavController import com.android.settingslib.spa.framework.theme.SettingsDimension Loading Loading @@ -100,6 +104,9 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur val networkTypeSelectedOptionsState = remember { getNetworkTypeSelectedOptionsState(apnData.networkType) } var apnTypeSelectedOptionsState = remember { getApnTypeSelectedOptionsState(apnData.apnType) } val navController = LocalNavController.current var valid: String? RegularScaffold( Loading Loading @@ -191,6 +198,27 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur label = stringResource(R.string.apn_server), enabled = apnData.serverEnabled ) { apnData = apnData.copy(server = it) } SettingsExposedDropdownMenuCheckBox( label = stringResource(R.string.apn_type), options = APN_TYPES_OPTIONS, selectedOptionsState = apnTypeSelectedOptionsState, enabled = apnData.apnTypeEnabled, errorMessage = validateAPNType( apnData.validEnabled, apnData.apnType, apnData.customizedConfig.readOnlyApnTypes, context ) ) { val apnType = updateApnType( apnTypeSelectedOptionsState, apnData.customizedConfig.defaultApnTypes, apnData.customizedConfig.readOnlyApnTypes ) apnTypeSelectedOptionsState = getApnTypeSelectedOptionsState(apnType) apnData = apnData.copy( apnType = apnType ) } if (apnTypeSelectedOptionsState.contains(APN_TYPES_OPTIONS.indexOf(APN_TYPE_MMS))) { SettingsOutlinedTextField( value = apnData.mmsc, label = stringResource(R.string.apn_mmsc), Loading @@ -207,21 +235,13 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur label = stringResource(R.string.apn_mms_port), enabled = apnData.mmsPortEnabled ) { apnData = apnData.copy(mmsPort = it) } } SettingsExposedDropdownMenuBox( label = stringResource(R.string.apn_auth_type), options = authTypeOptions, selectedOptionIndex = apnData.authType, enabled = apnData.authTypeEnabled, ) { apnData = apnData.copy(authType = it) } SettingsOutlinedTextField( value = apnData.apnType, label = stringResource(R.string.apn_type), enabled = apnData.apnTypeEnabled, errorMessage = validateAPNType( apnData.validEnabled, apnData.apnType, apnData.customizedConfig.readOnlyApnTypes, context ) ) { apnData = apnData.copy(apnType = updateApnType(apnData.copy(apnType = it))) } SettingsExposedDropdownMenuBox( label = stringResource(R.string.apn_protocol), options = apnProtocolOptions, Loading @@ -234,6 +254,13 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur selectedOptionIndex = apnData.apnRoaming, enabled = apnData.apnRoamingEnabled ) { apnData = apnData.copy(apnRoaming = it) } SettingsExposedDropdownMenuCheckBox( label = stringResource(R.string.network_type), options = getNetworkTypeDisplayNames(), selectedOptionsState = networkTypeSelectedOptionsState, emptyVal = stringResource(R.string.network_type_unspecified), enabled = apnData.networkTypeEnabled ) {} SwitchPreference( object : SwitchPreferenceModel { override val title = context.resources.getString(R.string.carrier_enabled) Loading @@ -244,13 +271,6 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur } } ) SettingsExposedDropdownMenuCheckBox( label = stringResource(R.string.network_type), options = getNetworkTypeDisplayNames(), selectedOptionsState = networkTypeSelectedOptionsState, emptyVal = stringResource(R.string.network_type_unspecified), enabled = apnData.networkTypeEnabled ) {} } } } No newline at end of file src/com/android/settings/network/apn/ApnStatus.kt +6 −80 Original line number Diff line number Diff line Loading @@ -29,6 +29,12 @@ import androidx.compose.runtime.snapshots.SnapshotStateList import com.android.internal.util.ArrayUtils import com.android.settings.R import com.android.settings.network.apn.ApnNetworkTypes.getNetworkType import com.android.settings.network.apn.ApnTypes.APN_TYPES import com.android.settings.network.apn.ApnTypes.APN_TYPE_ALL import com.android.settings.network.apn.ApnTypes.APN_TYPE_EMERGENCY import com.android.settings.network.apn.ApnTypes.APN_TYPE_IA import com.android.settings.network.apn.ApnTypes.APN_TYPE_IMS import com.android.settings.network.apn.ApnTypes.APN_TYPE_MCX import java.util.Locale data class ApnData( Loading Loading @@ -113,67 +119,6 @@ data class CustomizedConfig( val defaultApnRoamingProtocol: String = "", ) /** * APN types for data connections. These are usage categories for an APN * entry. One APN entry may support multiple APN types, eg, a single APN * may service regular internet traffic ("default") as well as MMS-specific * connections.<br></br> * APN_TYPE_ALL is a special type to indicate that this APN entry can * service all data connections. */ const val APN_TYPE_ALL = "*" /** APN type for default data traffic */ const val APN_TYPE_DEFAULT = "default" /** APN type for MMS traffic */ const val APN_TYPE_MMS = "mms" /** APN type for SUPL assisted GPS */ const val APN_TYPE_SUPL = "supl" /** APN type for DUN traffic */ const val APN_TYPE_DUN = "dun" /** APN type for HiPri traffic */ const val APN_TYPE_HIPRI = "hipri" /** APN type for FOTA */ const val APN_TYPE_FOTA = "fota" /** APN type for IMS */ const val APN_TYPE_IMS = "ims" /** APN type for CBS */ const val APN_TYPE_CBS = "cbs" /** APN type for IA Initial Attach APN */ const val APN_TYPE_IA = "ia" /** APN type for Emergency PDN. This is not an IA apn, but is used * for access to carrier services in an emergency call situation. */ const val APN_TYPE_EMERGENCY = "emergency" /** APN type for Mission Critical Services */ const val APN_TYPE_MCX = "mcx" /** APN type for XCAP */ const val APN_TYPE_XCAP = "xcap" val APN_TYPES = arrayOf( APN_TYPE_DEFAULT, APN_TYPE_MMS, APN_TYPE_SUPL, APN_TYPE_DUN, APN_TYPE_HIPRI, APN_TYPE_FOTA, APN_TYPE_IMS, APN_TYPE_CBS, APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_XCAP ) /** * Initialize ApnData according to the arguments. * @param arguments The data passed in when the user calls PageProvider. Loading Loading @@ -483,25 +428,6 @@ fun hasAllApns(apnTypes: List<String>): Boolean { private fun normalizeApnType(apnType: String): String = apnType.trim().lowercase(Locale.getDefault()) fun updateApnType(apnData: ApnData): String { return if (apnData.apnType == "" && apnData.customizedConfig.defaultApnTypes.isNotEmpty()) getEditableApnType(apnData) else apnData.apnType } private fun getEditableApnType(apnData: ApnData): String { val customizedConfig = apnData.customizedConfig return customizedConfig.defaultApnTypes.filterNot { apnType -> customizedConfig.readOnlyApnTypes.contains(apnType) || apnType in listOf( APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_IMS, ) }.joinToString() } fun deleteApn(uri: Uri, context: Context) { val contentResolver = context.contentResolver contentResolver.delete(uri, null, null) Loading src/com/android/settings/network/apn/ApnTypes.kt 0 → 100644 +143 −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.network.apn import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.snapshots.SnapshotStateList object ApnTypes { /** * APN types for data connections. These are usage categories for an APN * entry. One APN entry may support multiple APN types, eg, a single APN * may service regular internet traffic ("default") as well as MMS-specific * connections.<br></br> * APN_TYPE_ALL is a special type to indicate that this APN entry can * service all data connections. */ const val APN_TYPE_ALL = "*" /** APN type for default data traffic */ const val APN_TYPE_DEFAULT = "default" /** APN type for MMS traffic */ const val APN_TYPE_MMS = "mms" /** APN type for SUPL assisted GPS */ const val APN_TYPE_SUPL = "supl" /** APN type for DUN traffic */ const val APN_TYPE_DUN = "dun" /** APN type for HiPri traffic */ const val APN_TYPE_HIPRI = "hipri" /** APN type for FOTA */ const val APN_TYPE_FOTA = "fota" /** APN type for IMS */ const val APN_TYPE_IMS = "ims" /** APN type for CBS */ const val APN_TYPE_CBS = "cbs" /** APN type for IA Initial Attach APN */ const val APN_TYPE_IA = "ia" /** APN type for Emergency PDN. This is not an IA apn, but is used * for access to carrier services in an emergency call situation. */ const val APN_TYPE_EMERGENCY = "emergency" /** APN type for Mission Critical Services */ const val APN_TYPE_MCX = "mcx" /** APN type for XCAP */ const val APN_TYPE_XCAP = "xcap" /** APN type for VSIM */ const val APN_TYPE_VSIM = "vsim" /** APN type for BIP */ const val APN_TYPE_BIP = "bip" /** APN type for ENTERPRISE */ const val APN_TYPE_ENTERPRISE = "enterprise" val APN_TYPES = arrayOf( APN_TYPE_DEFAULT, APN_TYPE_MMS, APN_TYPE_SUPL, APN_TYPE_DUN, APN_TYPE_HIPRI, APN_TYPE_FOTA, APN_TYPE_IMS, APN_TYPE_CBS, APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_XCAP, APN_TYPE_VSIM, APN_TYPE_BIP, APN_TYPE_ENTERPRISE ) val APN_TYPES_OPTIONS = listOf(APN_TYPE_ALL) + APN_TYPES fun getApnTypeSelectedOptionsState(apnType: String): SnapshotStateList<Int> { val apnTypeSelectedOptionsState = mutableStateListOf<Int>() if (apnType.contains(APN_TYPE_ALL)) APN_TYPES_OPTIONS.forEachIndexed { index, _ -> apnTypeSelectedOptionsState.add(index) } else { APN_TYPES_OPTIONS.forEachIndexed { index, type -> if (apnType.contains(type)) { apnTypeSelectedOptionsState.add(index) } } if (apnTypeSelectedOptionsState.size == APN_TYPES.size) apnTypeSelectedOptionsState.add(APN_TYPES_OPTIONS.indexOf(APN_TYPE_ALL)) } return apnTypeSelectedOptionsState } fun updateApnType( apnTypeSelectedOptionsState: SnapshotStateList<Int>, defaultApnTypes: List<String>, readOnlyApnTypes: List<String> ): String { val apnType = apnTypeSelectedOptionsState.joinToString { APN_TYPES_OPTIONS[it] } if (apnType.contains(APN_TYPE_ALL)) return APN_TYPE_ALL return if (apnType == "" && defaultApnTypes.isNotEmpty()) getEditableApnType(defaultApnTypes, readOnlyApnTypes) else apnType } private fun getEditableApnType( defaultApnTypes: List<String>, readOnlyApnTypes: List<String> ): String { return defaultApnTypes.filterNot { apnType -> readOnlyApnTypes.contains(apnType) || apnType in listOf( APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_IMS, ) }.joinToString() } } No newline at end of file tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt +11 −11 Original line number Diff line number Diff line Loading @@ -50,9 +50,9 @@ class ApnEditPageProviderTest { private val context: Context = ApplicationProvider.getApplicationContext() private val apnName = "apn_name" private val mmsc = "mmsc" private val mmsProxy = "mms_proxy" private val apnType = "apn_type" private val proxy = "proxy" private val port = "port" private val apnType = context.resources.getString(R.string.apn_type) private val apnRoaming = "IPv4" private val apnEnable = context.resources.getString(R.string.carrier_enabled) private val apnProtocolOptions = Loading @@ -61,8 +61,8 @@ class ApnEditPageProviderTest { private val passwordTitle = context.resources.getString(R.string.apn_password) private val apnInit = ApnData( name = apnName, mmsc = mmsc, mmsProxy = mmsProxy, proxy = proxy, port = port, apnType = apnType, apnRoaming = apnProtocolOptions.indexOf(apnRoaming), apnEnable = true Loading Loading @@ -94,23 +94,23 @@ class ApnEditPageProviderTest { } @Test fun mmsc_displayed() { fun proxy_displayed() { composeTestRule.setContent { ApnPage(apnInit, remember { apnData }, uri) } composeTestRule.onRoot().onChild().onChildAt(0) .performScrollToNode(hasText(mmsc, true)) composeTestRule.onNodeWithText(mmsc, true).assertIsDisplayed() .performScrollToNode(hasText(proxy, true)) composeTestRule.onNodeWithText(proxy, true).assertIsDisplayed() } @Test fun mms_proxy_displayed() { fun port_displayed() { composeTestRule.setContent { ApnPage(apnInit, remember { apnData }, uri) } composeTestRule.onRoot().onChild().onChildAt(0) .performScrollToNode(hasText(mmsProxy, true)) composeTestRule.onNodeWithText(mmsProxy, true).assertIsDisplayed() .performScrollToNode(hasText(port, true)) composeTestRule.onNodeWithText(port, true).assertIsDisplayed() } @Test Loading Loading
src/com/android/settings/network/apn/ApnEditPageProvider.kt +52 −32 Original line number Diff line number Diff line Loading @@ -40,6 +40,10 @@ import androidx.navigation.navArgument import com.android.settings.R import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNames import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState import com.android.settings.network.apn.ApnTypes.APN_TYPES_OPTIONS import com.android.settings.network.apn.ApnTypes.APN_TYPE_MMS import com.android.settings.network.apn.ApnTypes.getApnTypeSelectedOptionsState import com.android.settings.network.apn.ApnTypes.updateApnType import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.compose.LocalNavController import com.android.settingslib.spa.framework.theme.SettingsDimension Loading Loading @@ -100,6 +104,9 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur val networkTypeSelectedOptionsState = remember { getNetworkTypeSelectedOptionsState(apnData.networkType) } var apnTypeSelectedOptionsState = remember { getApnTypeSelectedOptionsState(apnData.apnType) } val navController = LocalNavController.current var valid: String? RegularScaffold( Loading Loading @@ -191,6 +198,27 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur label = stringResource(R.string.apn_server), enabled = apnData.serverEnabled ) { apnData = apnData.copy(server = it) } SettingsExposedDropdownMenuCheckBox( label = stringResource(R.string.apn_type), options = APN_TYPES_OPTIONS, selectedOptionsState = apnTypeSelectedOptionsState, enabled = apnData.apnTypeEnabled, errorMessage = validateAPNType( apnData.validEnabled, apnData.apnType, apnData.customizedConfig.readOnlyApnTypes, context ) ) { val apnType = updateApnType( apnTypeSelectedOptionsState, apnData.customizedConfig.defaultApnTypes, apnData.customizedConfig.readOnlyApnTypes ) apnTypeSelectedOptionsState = getApnTypeSelectedOptionsState(apnType) apnData = apnData.copy( apnType = apnType ) } if (apnTypeSelectedOptionsState.contains(APN_TYPES_OPTIONS.indexOf(APN_TYPE_MMS))) { SettingsOutlinedTextField( value = apnData.mmsc, label = stringResource(R.string.apn_mmsc), Loading @@ -207,21 +235,13 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur label = stringResource(R.string.apn_mms_port), enabled = apnData.mmsPortEnabled ) { apnData = apnData.copy(mmsPort = it) } } SettingsExposedDropdownMenuBox( label = stringResource(R.string.apn_auth_type), options = authTypeOptions, selectedOptionIndex = apnData.authType, enabled = apnData.authTypeEnabled, ) { apnData = apnData.copy(authType = it) } SettingsOutlinedTextField( value = apnData.apnType, label = stringResource(R.string.apn_type), enabled = apnData.apnTypeEnabled, errorMessage = validateAPNType( apnData.validEnabled, apnData.apnType, apnData.customizedConfig.readOnlyApnTypes, context ) ) { apnData = apnData.copy(apnType = updateApnType(apnData.copy(apnType = it))) } SettingsExposedDropdownMenuBox( label = stringResource(R.string.apn_protocol), options = apnProtocolOptions, Loading @@ -234,6 +254,13 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur selectedOptionIndex = apnData.apnRoaming, enabled = apnData.apnRoamingEnabled ) { apnData = apnData.copy(apnRoaming = it) } SettingsExposedDropdownMenuCheckBox( label = stringResource(R.string.network_type), options = getNetworkTypeDisplayNames(), selectedOptionsState = networkTypeSelectedOptionsState, emptyVal = stringResource(R.string.network_type_unspecified), enabled = apnData.networkTypeEnabled ) {} SwitchPreference( object : SwitchPreferenceModel { override val title = context.resources.getString(R.string.carrier_enabled) Loading @@ -244,13 +271,6 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur } } ) SettingsExposedDropdownMenuCheckBox( label = stringResource(R.string.network_type), options = getNetworkTypeDisplayNames(), selectedOptionsState = networkTypeSelectedOptionsState, emptyVal = stringResource(R.string.network_type_unspecified), enabled = apnData.networkTypeEnabled ) {} } } } No newline at end of file
src/com/android/settings/network/apn/ApnStatus.kt +6 −80 Original line number Diff line number Diff line Loading @@ -29,6 +29,12 @@ import androidx.compose.runtime.snapshots.SnapshotStateList import com.android.internal.util.ArrayUtils import com.android.settings.R import com.android.settings.network.apn.ApnNetworkTypes.getNetworkType import com.android.settings.network.apn.ApnTypes.APN_TYPES import com.android.settings.network.apn.ApnTypes.APN_TYPE_ALL import com.android.settings.network.apn.ApnTypes.APN_TYPE_EMERGENCY import com.android.settings.network.apn.ApnTypes.APN_TYPE_IA import com.android.settings.network.apn.ApnTypes.APN_TYPE_IMS import com.android.settings.network.apn.ApnTypes.APN_TYPE_MCX import java.util.Locale data class ApnData( Loading Loading @@ -113,67 +119,6 @@ data class CustomizedConfig( val defaultApnRoamingProtocol: String = "", ) /** * APN types for data connections. These are usage categories for an APN * entry. One APN entry may support multiple APN types, eg, a single APN * may service regular internet traffic ("default") as well as MMS-specific * connections.<br></br> * APN_TYPE_ALL is a special type to indicate that this APN entry can * service all data connections. */ const val APN_TYPE_ALL = "*" /** APN type for default data traffic */ const val APN_TYPE_DEFAULT = "default" /** APN type for MMS traffic */ const val APN_TYPE_MMS = "mms" /** APN type for SUPL assisted GPS */ const val APN_TYPE_SUPL = "supl" /** APN type for DUN traffic */ const val APN_TYPE_DUN = "dun" /** APN type for HiPri traffic */ const val APN_TYPE_HIPRI = "hipri" /** APN type for FOTA */ const val APN_TYPE_FOTA = "fota" /** APN type for IMS */ const val APN_TYPE_IMS = "ims" /** APN type for CBS */ const val APN_TYPE_CBS = "cbs" /** APN type for IA Initial Attach APN */ const val APN_TYPE_IA = "ia" /** APN type for Emergency PDN. This is not an IA apn, but is used * for access to carrier services in an emergency call situation. */ const val APN_TYPE_EMERGENCY = "emergency" /** APN type for Mission Critical Services */ const val APN_TYPE_MCX = "mcx" /** APN type for XCAP */ const val APN_TYPE_XCAP = "xcap" val APN_TYPES = arrayOf( APN_TYPE_DEFAULT, APN_TYPE_MMS, APN_TYPE_SUPL, APN_TYPE_DUN, APN_TYPE_HIPRI, APN_TYPE_FOTA, APN_TYPE_IMS, APN_TYPE_CBS, APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_XCAP ) /** * Initialize ApnData according to the arguments. * @param arguments The data passed in when the user calls PageProvider. Loading Loading @@ -483,25 +428,6 @@ fun hasAllApns(apnTypes: List<String>): Boolean { private fun normalizeApnType(apnType: String): String = apnType.trim().lowercase(Locale.getDefault()) fun updateApnType(apnData: ApnData): String { return if (apnData.apnType == "" && apnData.customizedConfig.defaultApnTypes.isNotEmpty()) getEditableApnType(apnData) else apnData.apnType } private fun getEditableApnType(apnData: ApnData): String { val customizedConfig = apnData.customizedConfig return customizedConfig.defaultApnTypes.filterNot { apnType -> customizedConfig.readOnlyApnTypes.contains(apnType) || apnType in listOf( APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_IMS, ) }.joinToString() } fun deleteApn(uri: Uri, context: Context) { val contentResolver = context.contentResolver contentResolver.delete(uri, null, null) Loading
src/com/android/settings/network/apn/ApnTypes.kt 0 → 100644 +143 −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.network.apn import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.snapshots.SnapshotStateList object ApnTypes { /** * APN types for data connections. These are usage categories for an APN * entry. One APN entry may support multiple APN types, eg, a single APN * may service regular internet traffic ("default") as well as MMS-specific * connections.<br></br> * APN_TYPE_ALL is a special type to indicate that this APN entry can * service all data connections. */ const val APN_TYPE_ALL = "*" /** APN type for default data traffic */ const val APN_TYPE_DEFAULT = "default" /** APN type for MMS traffic */ const val APN_TYPE_MMS = "mms" /** APN type for SUPL assisted GPS */ const val APN_TYPE_SUPL = "supl" /** APN type for DUN traffic */ const val APN_TYPE_DUN = "dun" /** APN type for HiPri traffic */ const val APN_TYPE_HIPRI = "hipri" /** APN type for FOTA */ const val APN_TYPE_FOTA = "fota" /** APN type for IMS */ const val APN_TYPE_IMS = "ims" /** APN type for CBS */ const val APN_TYPE_CBS = "cbs" /** APN type for IA Initial Attach APN */ const val APN_TYPE_IA = "ia" /** APN type for Emergency PDN. This is not an IA apn, but is used * for access to carrier services in an emergency call situation. */ const val APN_TYPE_EMERGENCY = "emergency" /** APN type for Mission Critical Services */ const val APN_TYPE_MCX = "mcx" /** APN type for XCAP */ const val APN_TYPE_XCAP = "xcap" /** APN type for VSIM */ const val APN_TYPE_VSIM = "vsim" /** APN type for BIP */ const val APN_TYPE_BIP = "bip" /** APN type for ENTERPRISE */ const val APN_TYPE_ENTERPRISE = "enterprise" val APN_TYPES = arrayOf( APN_TYPE_DEFAULT, APN_TYPE_MMS, APN_TYPE_SUPL, APN_TYPE_DUN, APN_TYPE_HIPRI, APN_TYPE_FOTA, APN_TYPE_IMS, APN_TYPE_CBS, APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_XCAP, APN_TYPE_VSIM, APN_TYPE_BIP, APN_TYPE_ENTERPRISE ) val APN_TYPES_OPTIONS = listOf(APN_TYPE_ALL) + APN_TYPES fun getApnTypeSelectedOptionsState(apnType: String): SnapshotStateList<Int> { val apnTypeSelectedOptionsState = mutableStateListOf<Int>() if (apnType.contains(APN_TYPE_ALL)) APN_TYPES_OPTIONS.forEachIndexed { index, _ -> apnTypeSelectedOptionsState.add(index) } else { APN_TYPES_OPTIONS.forEachIndexed { index, type -> if (apnType.contains(type)) { apnTypeSelectedOptionsState.add(index) } } if (apnTypeSelectedOptionsState.size == APN_TYPES.size) apnTypeSelectedOptionsState.add(APN_TYPES_OPTIONS.indexOf(APN_TYPE_ALL)) } return apnTypeSelectedOptionsState } fun updateApnType( apnTypeSelectedOptionsState: SnapshotStateList<Int>, defaultApnTypes: List<String>, readOnlyApnTypes: List<String> ): String { val apnType = apnTypeSelectedOptionsState.joinToString { APN_TYPES_OPTIONS[it] } if (apnType.contains(APN_TYPE_ALL)) return APN_TYPE_ALL return if (apnType == "" && defaultApnTypes.isNotEmpty()) getEditableApnType(defaultApnTypes, readOnlyApnTypes) else apnType } private fun getEditableApnType( defaultApnTypes: List<String>, readOnlyApnTypes: List<String> ): String { return defaultApnTypes.filterNot { apnType -> readOnlyApnTypes.contains(apnType) || apnType in listOf( APN_TYPE_IA, APN_TYPE_EMERGENCY, APN_TYPE_MCX, APN_TYPE_IMS, ) }.joinToString() } } No newline at end of file
tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt +11 −11 Original line number Diff line number Diff line Loading @@ -50,9 +50,9 @@ class ApnEditPageProviderTest { private val context: Context = ApplicationProvider.getApplicationContext() private val apnName = "apn_name" private val mmsc = "mmsc" private val mmsProxy = "mms_proxy" private val apnType = "apn_type" private val proxy = "proxy" private val port = "port" private val apnType = context.resources.getString(R.string.apn_type) private val apnRoaming = "IPv4" private val apnEnable = context.resources.getString(R.string.carrier_enabled) private val apnProtocolOptions = Loading @@ -61,8 +61,8 @@ class ApnEditPageProviderTest { private val passwordTitle = context.resources.getString(R.string.apn_password) private val apnInit = ApnData( name = apnName, mmsc = mmsc, mmsProxy = mmsProxy, proxy = proxy, port = port, apnType = apnType, apnRoaming = apnProtocolOptions.indexOf(apnRoaming), apnEnable = true Loading Loading @@ -94,23 +94,23 @@ class ApnEditPageProviderTest { } @Test fun mmsc_displayed() { fun proxy_displayed() { composeTestRule.setContent { ApnPage(apnInit, remember { apnData }, uri) } composeTestRule.onRoot().onChild().onChildAt(0) .performScrollToNode(hasText(mmsc, true)) composeTestRule.onNodeWithText(mmsc, true).assertIsDisplayed() .performScrollToNode(hasText(proxy, true)) composeTestRule.onNodeWithText(proxy, true).assertIsDisplayed() } @Test fun mms_proxy_displayed() { fun port_displayed() { composeTestRule.setContent { ApnPage(apnInit, remember { apnData }, uri) } composeTestRule.onRoot().onChild().onChildAt(0) .performScrollToNode(hasText(mmsProxy, true)) composeTestRule.onNodeWithText(mmsProxy, true).assertIsDisplayed() .performScrollToNode(hasText(port, true)) composeTestRule.onNodeWithText(port, true).assertIsDisplayed() } @Test Loading