• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.network.apn
18 
19 import android.content.Context
20 import android.os.PersistableBundle
21 import android.telephony.CarrierConfigManager
22 import android.telephony.data.ApnSetting
23 import android.util.Log
24 import android.widget.Toast
25 import androidx.compose.runtime.mutableStateOf
26 import androidx.compose.ui.text.intl.Locale
27 import androidx.compose.ui.text.toLowerCase
28 import com.android.settings.R
29 import com.android.settingslib.spa.widget.editor.SettingsDropdownCheckOption
30 
31 object ApnTypes {
32     private const val TAG = "ApnTypes"
33 
34     private val APN_TYPES = arrayOf(
35         ApnSetting.TYPE_DEFAULT_STRING,
36         ApnSetting.TYPE_MMS_STRING,
37         ApnSetting.TYPE_SUPL_STRING,
38         ApnSetting.TYPE_DUN_STRING,
39         ApnSetting.TYPE_HIPRI_STRING,
40         ApnSetting.TYPE_FOTA_STRING,
41         ApnSetting.TYPE_IMS_STRING,
42         ApnSetting.TYPE_CBS_STRING,
43         ApnSetting.TYPE_IA_STRING,
44         ApnSetting.TYPE_EMERGENCY_STRING,
45         ApnSetting.TYPE_MCX_STRING,
46         ApnSetting.TYPE_XCAP_STRING,
47         ApnSetting.TYPE_VSIM_STRING,
48         ApnSetting.TYPE_BIP_STRING,
49         ApnSetting.TYPE_ENTERPRISE_STRING,
50         ApnSetting.TYPE_OEM_PAID_STRING,
51         ApnSetting.TYPE_OEM_PRIVATE_STRING,
52     )
53 
splitToListnull54     private fun splitToList(apnType: String): List<String> {
55         val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
56         if (hasAllApnTypes(types)) return listOf(ApnSetting.TYPE_ALL_STRING)
57         return APN_TYPES.filter { it in types }
58     }
59 
isApnTypeReadOnlynull60     fun isApnTypeReadOnly(apnType: String, readOnlyTypes: List<String>): Boolean {
61         val apnTypes = splitToList(apnType)
62         return ApnSetting.TYPE_ALL_STRING in readOnlyTypes ||
63             ApnSetting.TYPE_ALL_STRING in apnTypes && readOnlyTypes.isNotEmpty() ||
64             apnTypes.any { it in readOnlyTypes }
65     }
66 
<lambda>null67     fun getOptions(context: Context, apnType: String, readOnlyTypes: List<String>) = buildList {
68         val apnTypes = splitToList(apnType)
69         add(
70             context.createSettingsDropdownCheckOption(
71                 text = ApnSetting.TYPE_ALL_STRING,
72                 isSelectAll = true,
73                 changeable = readOnlyTypes.isEmpty(),
74                 selected = ApnSetting.TYPE_ALL_STRING in apnTypes,
75             )
76         )
77         for (type in APN_TYPES) {
78             add(
79                 context.createSettingsDropdownCheckOption(
80                     text = type,
81                     changeable = ApnSetting.TYPE_ALL_STRING !in readOnlyTypes &&
82                         type !in readOnlyTypes,
83                     selected = ApnSetting.TYPE_ALL_STRING in apnTypes || type in apnTypes,
84                 )
85             )
86         }
87     }.also { Log.d(TAG, "APN Type options: $it") }
88 
Contextnull89     private fun Context.createSettingsDropdownCheckOption(
90         text: String,
91         isSelectAll: Boolean = false,
92         changeable: Boolean,
93         selected: Boolean,
94     ) = SettingsDropdownCheckOption(
95         text = text,
96         isSelectAll = isSelectAll,
97         changeable = changeable,
98         selected = mutableStateOf(selected),
99     ) {
100         if (!changeable) {
101             val message = resources.getString(R.string.error_adding_apn_type, text)
102             Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
103         }
104     }
105 
<lambda>null106     fun List<SettingsDropdownCheckOption>.isValid(): Boolean = any { it.selected.value }
107 
toApnTypenull108     fun List<SettingsDropdownCheckOption>.toApnType(): String {
109         val (selectAllOptions, regularOptions) = partition { it.isSelectAll }
110         for (selectAllOption in selectAllOptions) {
111             if (selectAllOption.selected.value) return ApnSetting.TYPE_ALL_STRING
112         }
113         return regularOptions.filter { it.selected.value }.joinToString(",") { it.text }
114     }
115 
116     private val PreSelectedTypes = setOf(
117         ApnSetting.TYPE_DEFAULT_STRING,
118         ApnSetting.TYPE_MMS_STRING,
119         ApnSetting.TYPE_SUPL_STRING,
120         ApnSetting.TYPE_DUN_STRING,
121         ApnSetting.TYPE_HIPRI_STRING,
122         ApnSetting.TYPE_FOTA_STRING,
123         ApnSetting.TYPE_CBS_STRING,
124         ApnSetting.TYPE_XCAP_STRING,
125     )
126 
getPreSelectedApnTypenull127     fun getPreSelectedApnType(customizedConfig: CustomizedConfig): String =
128         (customizedConfig.defaultApnTypes
129             ?: defaultPreSelectedApnTypes(customizedConfig.readOnlyApnTypes))
130             .joinToString(",")
131 
132     private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
133         if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
134         else PreSelectedTypes.filterNot { it in readOnlyApnTypes }
135 
136     /** Array of APN types that are never user-editable */
137     private val ALWAYS_READ_ONLY_APN_TYPES =
138         arrayOf(ApnSetting.TYPE_OEM_PAID_STRING, ApnSetting.TYPE_OEM_PRIVATE_STRING)
139 
140     /**
141      * Fetch complete list of read only APN types.
142      *
143      * The list primarily comes from carrier config, but is also supplied by APN types which are
144      * always read only.
145      */
146     @JvmStatic
PersistableBundlenull147     fun PersistableBundle.getReadOnlyApnTypes(): List<String> {
148         val carrierReadOnlyApnTypes =
149             getStringArray(CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY)?.toList()
150                 ?: emptyList()
151         return carrierReadOnlyApnTypes + ALWAYS_READ_ONLY_APN_TYPES
152     }
153 
154     /**
155      * Check if passed in array of APN types indicates all APN types
156      *
157      * @param apnTypes array of APN types. "*" indicates all types.
158      * @return true if all apn types are included in the array, false otherwise
159      */
160     @JvmStatic
hasAllApnTypesnull161     fun hasAllApnTypes(apnTypes: List<String>): Boolean =
162         ApnSetting.TYPE_ALL_STRING in apnTypes || APN_TYPES.all { it in apnTypes }
163 }
164