Merge "Provide confirmation if creating new APN is not filled in enough and add a save button." into main

This commit is contained in:
Charlotte Lu
2023-12-14 06:23:01 +00:00
committed by Android (Google) Code Review
2 changed files with 75 additions and 58 deletions

View File

@@ -39,7 +39,6 @@ import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNam
import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState
import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.LocalNavController import com.android.settingslib.spa.framework.compose.LocalNavController
import com.android.settingslib.spa.framework.compose.OnBackEffect
import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox
import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuCheckBox import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuCheckBox
import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
@@ -98,29 +97,35 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
val networkTypeSelectedOptionsState = remember { val networkTypeSelectedOptionsState = remember {
getNetworkTypeSelectedOptionsState(apnData.networkType) getNetworkTypeSelectedOptionsState(apnData.networkType)
} }
OnBackEffect{ val navController = LocalNavController.current
validateAndSaveApnData( RegularScaffold(
title = if (apnDataInit.newApn) stringResource(id = R.string.apn_add) else stringResource(id = R.string.apn_edit),
actions = {
IconButton(onClick = {
if (!apnData.validEnabled) apnData = apnData.copy(validEnabled = true)
val valid = validateAndSaveApnData(
apnDataInit, apnDataInit,
apnData, apnData,
context, context,
uriInit, uriInit,
networkTypeSelectedOptionsState networkTypeSelectedOptionsState
) )
} if (valid) navController.navigateBack()
val navController = LocalNavController.current }) { Icon(imageVector = Icons.Outlined.Done, contentDescription = null) }
RegularScaffold( },
title = if(apnDataInit.newApn) stringResource(id = R.string.apn_add) else stringResource(id = R.string.apn_edit),
) { ) {
Column { Column {
SettingsOutlinedTextField( SettingsOutlinedTextField(
value = apnData.name, value = apnData.name,
label = stringResource(R.string.apn_name), label = stringResource(R.string.apn_name),
enabled = apnData.nameEnabled enabled = apnData.nameEnabled,
errorMessage = validateName(apnData.validEnabled, apnData.name, context)
) { apnData = apnData.copy(name = it) } ) { apnData = apnData.copy(name = it) }
SettingsOutlinedTextField( SettingsOutlinedTextField(
value = apnData.apn, value = apnData.apn,
label = stringResource(R.string.apn_apn), label = stringResource(R.string.apn_apn),
enabled = apnData.apnEnabled enabled = apnData.apnEnabled,
errorMessage = validateAPN(apnData.validEnabled, apnData.apn, context)
) { apnData = apnData.copy(apn = it) } ) { apnData = apnData.copy(apn = it) }
SettingsOutlinedTextField( SettingsOutlinedTextField(
value = apnData.proxy, value = apnData.proxy,
@@ -150,7 +155,7 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
SettingsOutlinedTextField( SettingsOutlinedTextField(
value = apnData.mmsc, value = apnData.mmsc,
label = stringResource(R.string.apn_mmsc), label = stringResource(R.string.apn_mmsc),
errorMessage = validateMMSC(apnData.mmsc, context), errorMessage = validateMMSC(apnData.validEnabled, apnData.mmsc, context),
enabled = apnData.mmscEnabled enabled = apnData.mmscEnabled
) { apnData = apnData.copy(mmsc = it) } ) { apnData = apnData.copy(mmsc = it) }
SettingsOutlinedTextField( SettingsOutlinedTextField(
@@ -172,7 +177,11 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
SettingsOutlinedTextField( SettingsOutlinedTextField(
value = apnData.apnType, value = apnData.apnType,
label = stringResource(R.string.apn_type), label = stringResource(R.string.apn_type),
enabled = apnData.apnTypeEnabled enabled = apnData.apnTypeEnabled,
errorMessage = validateAPNType(
apnData.validEnabled, apnData.apnType,
apnData.customizedConfig.readOnlyApnTypes, context
)
) { apnData = apnData.copy(apnType = updateApnType(apnData.copy(apnType = it))) } ) { apnData = apnData.copy(apnType = updateApnType(apnData.copy(apnType = it))) }
SettingsExposedDropdownMenuBox( SettingsExposedDropdownMenuBox(
label = stringResource(R.string.apn_protocol), label = stringResource(R.string.apn_protocol),
@@ -209,7 +218,6 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
override val title = stringResource(R.string.menu_delete) override val title = stringResource(R.string.menu_delete)
override val onClick = { override val onClick = {
deleteApn(uriInit, context) deleteApn(uriInit, context)
apnData = apnData.copy(saveEnabled = false)
navController.navigateBack() navController.navigateBack()
} }
} }

View File

@@ -69,7 +69,7 @@ data class ApnData(
val networkTypeEnabled: Boolean = true, val networkTypeEnabled: Boolean = true,
val newApn: Boolean = false, val newApn: Boolean = false,
val subId: Int = -1, val subId: Int = -1,
val saveEnabled: Boolean = true, val validEnabled: Boolean = false,
val customizedConfig: CustomizedConfig = CustomizedConfig() val customizedConfig: CustomizedConfig = CustomizedConfig()
) { ) {
fun getContentValues(context: Context): ContentValues { fun getContentValues(context: Context): ContentValues {
@@ -96,7 +96,8 @@ data class ApnData(
values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED) values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED)
if (newApn) { if (newApn) {
val simCarrierId = val simCarrierId =
context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId) context.getSystemService(TelephonyManager::class.java)!!
.createForSubscriptionId(subId)
.getSimCarrierId() .getSimCarrierId()
values.put(Telephony.Carriers.CARRIER_ID, simCarrierId) values.put(Telephony.Carriers.CARRIER_ID, simCarrierId)
} }
@@ -231,22 +232,12 @@ fun validateAndSaveApnData(
uriInit: Uri, uriInit: Uri,
networkTypeSelectedOptionsState: SnapshotStateList<Int> networkTypeSelectedOptionsState: SnapshotStateList<Int>
): Boolean { ): Boolean {
// Can not be saved
if (!apnData.saveEnabled) {
return false
}
// Nothing to do if it's a read only APN // Nothing to do if it's a read only APN
if (apnData.customizedConfig.readOnlyApn) { if (apnData.customizedConfig.readOnlyApn) {
return true return true
} }
var errorMsg = validateApnData(apnData, context) val errorMsg = validateApnData(apnData, context)
if (errorMsg != null) { if (errorMsg != null) {
//TODO: showError(this)
return false
}
errorMsg = validateMMSC(apnData.mmsc, context)
if (errorMsg != null) {
//TODO: showError(this)
return false return false
} }
val newApnData = apnData.copy(networkType = getNetworkType(networkTypeSelectedOptionsState)) val newApnData = apnData.copy(networkType = getNetworkType(networkTypeSelectedOptionsState))
@@ -268,37 +259,23 @@ fun validateAndSaveApnData(
* @return An error message if the apn data is invalid, otherwise return null. * @return An error message if the apn data is invalid, otherwise return null.
*/ */
fun validateApnData(apnData: ApnData, context: Context): String? { fun validateApnData(apnData: ApnData, context: Context): String? {
var errorMsg: String? = null var errorMsg: String?
val name = apnData.name val name = apnData.name
val apn = apnData.apn val apn = apnData.apn
if (name == "") { errorMsg = if (name == "") {
errorMsg = context.resources.getString(R.string.error_name_empty) context.resources.getString(R.string.error_name_empty)
} else if (apn == "") { } else if (apn == "") {
errorMsg = context.resources.getString(R.string.error_apn_empty) context.resources.getString(R.string.error_apn_empty)
} else {
validateMMSC(apnData.validEnabled, apnData.mmsc, context)
} }
if (errorMsg == null) { if (errorMsg == null) {
// if carrier does not allow editing certain apn types, make sure type does not include errorMsg = validateAPNType(
// those apnData.validEnabled,
if (!ArrayUtils.isEmpty(apnData.customizedConfig.readOnlyApnTypes) apnData.apnType,
&& apnTypesMatch(
apnData.customizedConfig.readOnlyApnTypes, apnData.customizedConfig.readOnlyApnTypes,
getUserEnteredApnType(apnData.apnType, apnData.customizedConfig.readOnlyApnTypes) context
) )
) {
val stringBuilder = StringBuilder()
for (type in apnData.customizedConfig.readOnlyApnTypes) {
stringBuilder.append(type).append(", ")
Log.d(TAG, "validateApnData: appending type: $type")
}
// remove last ", "
if (stringBuilder.length >= 2) {
stringBuilder.delete(stringBuilder.length - 2, stringBuilder.length)
}
errorMsg = String.format(
context.resources.getString(R.string.error_adding_apn_type),
stringBuilder
)
}
} }
return errorMsg return errorMsg
} }
@@ -536,7 +513,39 @@ fun deleteApn(uri: Uri, context: Context) {
contentResolver.delete(uri, null, null) contentResolver.delete(uri, null, null)
} }
fun validateMMSC(mmsc: String, context: Context): String? { fun validateMMSC(validEnabled: Boolean, mmsc: String, context: Context): String? {
return if (mmsc.matches(Regex("^https?:\\/\\/.+"))) null return if (validEnabled && !mmsc.matches(Regex("^https?:\\/\\/.+")))
else context.resources.getString(R.string.error_mmsc_valid) context.resources.getString(R.string.error_mmsc_valid)
else null
}
fun validateName(validEnabled: Boolean, name: String, context: Context): String? {
return if (validEnabled && (name == "")) context.resources.getString(R.string.error_name_empty)
else null
}
fun validateAPN(validEnabled: Boolean, apn: String, context: Context): String? {
return if (validEnabled && (apn == "")) context.resources.getString(R.string.error_apn_empty)
else null
}
fun validateAPNType(
validEnabled: Boolean,
apnType: String,
readOnlyApnTypes: List<String>,
context: Context
): String? {
// if carrier does not allow editing certain apn types, make sure type does not include those
if (validEnabled && !ArrayUtils.isEmpty(readOnlyApnTypes)
&& apnTypesMatch(
readOnlyApnTypes,
getUserEnteredApnType(apnType, readOnlyApnTypes)
)
) {
return String.format(
context.resources.getString(R.string.error_adding_apn_type),
readOnlyApnTypes.joinToString(", ")
)
}
return null
} }