• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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.ContentValues
20 import android.content.Context
21 import android.database.Cursor
22 import android.net.Uri
23 import android.provider.Telephony
24 import android.telephony.TelephonyManager
25 import android.util.Log
26 import com.android.settings.R
27 import com.android.settings.network.telephony.telephonyManager
28 import com.android.settingslib.utils.ThreadUtils
29 import java.util.Locale
30 
31 val Projection = arrayOf(
32     Telephony.Carriers._ID,  // 0
33     Telephony.Carriers.NAME,  // 1
34     Telephony.Carriers.APN,  // 2
35     Telephony.Carriers.PROXY,  // 3
36     Telephony.Carriers.PORT,  // 4
37     Telephony.Carriers.USER,  // 5
38     Telephony.Carriers.SERVER,  // 6
39     Telephony.Carriers.PASSWORD,  // 7
40     Telephony.Carriers.MMSC,  // 8
41     Telephony.Carriers.MMSPROXY,  // 9
42     Telephony.Carriers.MMSPORT,  // 10
43     Telephony.Carriers.AUTH_TYPE,  // 11
44     Telephony.Carriers.TYPE,  // 12
45     Telephony.Carriers.PROTOCOL,  // 13
46     Telephony.Carriers.CARRIER_ENABLED,  // 14
47     Telephony.Carriers.NETWORK_TYPE_BITMASK, // 15
48     Telephony.Carriers.ROAMING_PROTOCOL,  // 16
49     Telephony.Carriers.EDITED_STATUS,  // 17
50     Telephony.Carriers.USER_EDITABLE,  // 18
51 )
52 
53 private const val TAG = "ApnRepository"
54 
55 /**
56  * Query apn related information based on uri.
57  * @param uri URI data used for query.
58  *
59  * @return Stored apn related information.
60  */
61 fun getApnDataFromUri(uri: Uri, context: Context): ApnData {
62     var apnData = ApnData()
63     val contentResolver = context.contentResolver
64 
65     contentResolver.query(
66         uri,
67         Projection,
68         null /* selection */,
69         null /* selectionArgs */,
70         null /* sortOrder */
71     ).use { cursor ->
72         if (cursor != null && cursor.moveToFirst()) {
73             apnData = ApnData(
74                 id = cursor.getInt(Telephony.Carriers._ID),
75                 name = cursor.getString(Telephony.Carriers.NAME),
76                 apn = cursor.getString(Telephony.Carriers.APN),
77                 proxy = cursor.getString(Telephony.Carriers.PROXY),
78                 port = cursor.getString(Telephony.Carriers.PORT),
79                 userName = cursor.getString(Telephony.Carriers.USER),
80                 passWord = cursor.getString(Telephony.Carriers.PASSWORD),
81                 server = cursor.getString(Telephony.Carriers.SERVER),
82                 mmsc = cursor.getString(Telephony.Carriers.MMSC),
83                 mmsProxy = cursor.getString(Telephony.Carriers.MMSPROXY),
84                 mmsPort = cursor.getString(Telephony.Carriers.MMSPORT),
85                 authType = cursor.getInt(Telephony.Carriers.AUTH_TYPE),
86                 apnType = cursor.getString(Telephony.Carriers.TYPE),
87                 apnProtocol = context.convertProtocol2Options(
88                     cursor.getString(Telephony.Carriers.PROTOCOL)
89                 ),
90                 apnRoaming = context.convertProtocol2Options(
91                     cursor.getString(Telephony.Carriers.ROAMING_PROTOCOL)
92                 ),
93                 carrierEnabled = cursor.getInt(Telephony.Carriers.CARRIER_ENABLED) == 1,
94                 networkType = cursor.getLong(Telephony.Carriers.NETWORK_TYPE_BITMASK),
95                 edited = cursor.getInt(Telephony.Carriers.EDITED_STATUS),
96                 userEditable = cursor.getInt(Telephony.Carriers.USER_EDITABLE),
97             )
98         }
99     }
100     if (apnData.name == "") {
101         Log.d(TAG, "Can't get apnData from Uri $uri")
102     }
103     return apnData
104 }
105 
getStringnull106 private fun Cursor.getString(columnName: String) = getString(getColumnIndexOrThrow(columnName))
107 private fun Cursor.getInt(columnName: String) = getInt(getColumnIndexOrThrow(columnName))
108 private fun Cursor.getLong(columnName: String) = getLong(getColumnIndexOrThrow(columnName))
109 
110 /**
111  * Returns The UI choice index corresponding to the given raw value of the protocol preference
112  * (e.g., "IPV4V6").
113  * If unknown, return -1.
114  */
115 private fun Context.convertProtocol2Options(protocol: String): Int {
116     var normalizedProtocol = protocol.uppercase(Locale.getDefault())
117     if (normalizedProtocol == "IPV4") normalizedProtocol = "IP"
118     return resources.getStringArray(R.array.apn_protocol_values).indexOf(normalizedProtocol)
119 }
120 
Contextnull121 fun Context.convertOptions2Protocol(protocolIndex: Int): String =
122     resources.getStringArray(R.array.apn_protocol_values).getOrElse(protocolIndex) { "" }
123 
updateApnDataToDatabasenull124 fun updateApnDataToDatabase(
125     newApn: Boolean,
126     values: ContentValues,
127     context: Context,
128     uriInit: Uri
129 ) {
130     ThreadUtils.postOnBackgroundThread {
131         if (newApn) {
132             Log.d(TAG, "Adding an new APN to the database $uriInit $values")
133             val newUri = context.contentResolver.insert(uriInit, values)
134             if (newUri == null) {
135                 Log.e(TAG, "Can't add a new apn to database $uriInit")
136             }
137         } else {
138             Log.d(TAG, "Updating an existing APN to the database $uriInit $values")
139             context.contentResolver.update(
140                 uriInit, values, null /* where */, null /* selection Args */
141             )
142         }
143     }
144 }
145 
146 /** Not allowing add duplicated items, if the values of the following keys are all identical. */
147 private val NonDuplicatedKeys = setOf(
148     Telephony.Carriers.APN,
149     Telephony.Carriers.PROXY,
150     Telephony.Carriers.PORT,
151     Telephony.Carriers.MMSC,
152     Telephony.Carriers.MMSPROXY,
153     Telephony.Carriers.MMSPORT,
154     Telephony.Carriers.PROTOCOL,
155     Telephony.Carriers.ROAMING_PROTOCOL,
156 )
157 
isItemExistnull158 fun isItemExist(apnData: ApnData, context: Context): String? {
159     val selectionMap = apnData.getContentValueMap(context).filterKeys { it in NonDuplicatedKeys }
160         .mapKeys { "${it.key} = ?" }
161         .toMutableMap()
162     if (apnData.id != -1) selectionMap += "${Telephony.Carriers._ID} != ?" to apnData.id
163     val list = selectionMap.entries.toList()
164     val selection = list.joinToString(" AND ") { it.key }
165     val selectionArgs: Array<String> = list.map { it.value.toString() }.toTypedArray()
166     context.contentResolver.query(
167         Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, apnData.subId.toString()),
168         /* projection = */ emptyArray(),
169         selection,
170         selectionArgs,
171         /* sortOrder = */ null,
172     )?.use { cursor ->
173         if (cursor.count > 0) {
174             return context.resources.getString(R.string.error_duplicate_apn_entry)
175         }
176     }
177     return null
178 }
179 
Contextnull180 fun Context.getApnIdMap(subId: Int): Map<String, Any> {
181     val telephonyManager = telephonyManager(subId)
182     val carrierId = telephonyManager.simSpecificCarrierId
183     return if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
184         mapOf(Telephony.Carriers.CARRIER_ID to carrierId)
185     } else {
186         mapOf(Telephony.Carriers.NUMERIC to telephonyManager.simOperator)
187     }.also { Log.d(TAG, "[$subId] New APN item with id: $it") }
188 }
189