blob: 7fe80425eeee3ae447edfa2d18895f4f617725cc [file] [log] [blame]
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001/* //device/content/providers/telephony/TelephonyProvider.java
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18package com.android.providers.telephony;
19
Jeff Davidsonb114ed22017-04-09 14:55:23 -070020import static android.provider.Telephony.Carriers.APN;
Jordan Liu92da8c82018-04-10 16:00:06 -070021import static android.provider.Telephony.Carriers.APN_SET_ID;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070022import static android.provider.Telephony.Carriers.AUTH_TYPE;
23import static android.provider.Telephony.Carriers.BEARER;
24import static android.provider.Telephony.Carriers.BEARER_BITMASK;
25import static android.provider.Telephony.Carriers.CARRIER_DELETED;
26import static android.provider.Telephony.Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML;
27import static android.provider.Telephony.Carriers.CARRIER_EDITED;
28import static android.provider.Telephony.Carriers.CARRIER_ENABLED;
calvinpan2b419442018-10-23 15:05:11 +080029import static android.provider.Telephony.Carriers.CARRIER_ID;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070030import static android.provider.Telephony.Carriers.CONTENT_URI;
31import static android.provider.Telephony.Carriers.CURRENT;
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +090032import static android.provider.Telephony.Carriers.DEFAULT_SORT_ORDER;
chen xu3e303942018-11-28 00:23:01 -080033import static android.provider.Telephony.Carriers.EDITED_STATUS;
34import static android.provider.Telephony.Carriers.MAX_CONNECTIONS;
35import static android.provider.Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070036import static android.provider.Telephony.Carriers.MCC;
37import static android.provider.Telephony.Carriers.MMSC;
38import static android.provider.Telephony.Carriers.MMSPORT;
39import static android.provider.Telephony.Carriers.MMSPROXY;
40import static android.provider.Telephony.Carriers.MNC;
chen xu3e303942018-11-28 00:23:01 -080041import static android.provider.Telephony.Carriers.MODEM_PERSIST;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070042import static android.provider.Telephony.Carriers.MTU;
43import static android.provider.Telephony.Carriers.MVNO_MATCH_DATA;
44import static android.provider.Telephony.Carriers.MVNO_TYPE;
45import static android.provider.Telephony.Carriers.NAME;
Cassiea58ce712017-12-06 16:21:50 -080046import static android.provider.Telephony.Carriers.NETWORK_TYPE_BITMASK;
chen xu3e303942018-11-28 00:23:01 -080047import static android.provider.Telephony.Carriers.NO_APN_SET_ID;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070048import static android.provider.Telephony.Carriers.NUMERIC;
yuemingwc4d40a72017-11-08 14:14:37 +000049import static android.provider.Telephony.Carriers.OWNED_BY;
yuemingwc4d40a72017-11-08 14:14:37 +000050import static android.provider.Telephony.Carriers.OWNED_BY_DPC;
calvinpanba94b592018-11-01 09:09:30 +080051import static android.provider.Telephony.Carriers.OWNED_BY_OTHERS;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070052import static android.provider.Telephony.Carriers.PASSWORD;
53import static android.provider.Telephony.Carriers.PORT;
54import static android.provider.Telephony.Carriers.PROFILE_ID;
55import static android.provider.Telephony.Carriers.PROTOCOL;
56import static android.provider.Telephony.Carriers.PROXY;
57import static android.provider.Telephony.Carriers.ROAMING_PROTOCOL;
58import static android.provider.Telephony.Carriers.SERVER;
Yuuki Habu95aacb12019-02-22 10:49:06 +090059import static android.provider.Telephony.Carriers.SKIP_464XLAT;
60import static android.provider.Telephony.Carriers.SKIP_464XLAT_DEFAULT;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070061import static android.provider.Telephony.Carriers.SUBSCRIPTION_ID;
62import static android.provider.Telephony.Carriers.TYPE;
63import static android.provider.Telephony.Carriers.UNEDITED;
64import static android.provider.Telephony.Carriers.USER;
65import static android.provider.Telephony.Carriers.USER_DELETED;
66import static android.provider.Telephony.Carriers.USER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan460d7032017-07-17 14:42:33 -070067import static android.provider.Telephony.Carriers.USER_EDITABLE;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070068import static android.provider.Telephony.Carriers.USER_EDITED;
69import static android.provider.Telephony.Carriers.USER_VISIBLE;
chen xu3e303942018-11-28 00:23:01 -080070import static android.provider.Telephony.Carriers.WAIT_TIME_RETRY;
Jeff Davidsonb114ed22017-04-09 14:55:23 -070071import static android.provider.Telephony.Carriers._ID;
72
calvinpan33a10a02019-11-04 21:36:12 +080073import android.annotation.NonNull;
Hall Liu018f8b12020-02-25 15:58:56 -080074import android.app.compat.CompatChanges;
Jordan Liu3de76f82017-05-15 15:21:01 -070075import android.content.ComponentName;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070076import android.content.ContentProvider;
chen xu4590bd72018-10-18 14:07:02 -070077import android.content.ContentResolver;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070078import android.content.ContentUris;
79import android.content.ContentValues;
80import android.content.Context;
Jordan Liu3de76f82017-05-15 15:21:01 -070081import android.content.Intent;
82import android.content.ServiceConnection;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070083import android.content.SharedPreferences;
84import android.content.UriMatcher;
Shishir Agrawalacf787b2014-07-14 17:13:51 -070085import android.content.pm.PackageManager;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080086import android.content.res.Resources;
87import android.content.res.XmlResourceParser;
88import android.database.Cursor;
yuemingwc41e5c82017-11-09 13:30:33 +000089import android.database.MatrixCursor;
jewon.lee4167fcc2013-01-17 13:10:37 +090090import android.database.SQLException;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080091import android.database.sqlite.SQLiteDatabase;
Wink Saville6de10272014-06-22 07:38:43 -070092import android.database.sqlite.SQLiteException;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080093import android.database.sqlite.SQLiteOpenHelper;
94import android.database.sqlite.SQLiteQueryBuilder;
95import android.net.Uri;
Shishir Agrawalacf787b2014-07-14 17:13:51 -070096import android.os.Binder;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080097import android.os.Environment;
Jordan Liu3de76f82017-05-15 15:21:01 -070098import android.os.IBinder;
yuemingwc41e5c82017-11-09 13:30:33 +000099import android.os.Process;
Jordan Liu3de76f82017-05-15 15:21:01 -0700100import android.os.RemoteException;
Hall Liu7ee663d2019-11-21 16:30:47 -0800101import android.os.ServiceManager;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800102import android.os.SystemProperties;
Amith Yamasani887288c2014-11-06 09:01:20 -0800103import android.os.UserHandle;
Hall Liu5479f4d2018-07-14 00:31:13 +0000104import android.provider.Telephony;
SongFerngWang64fb3dd2019-12-02 20:59:47 +0800105import android.telephony.Annotation;
Wink Savillee84c0a82014-06-09 21:04:39 -0700106import android.telephony.SubscriptionManager;
107import android.telephony.TelephonyManager;
yuemingwb9d42b52018-06-13 12:56:32 +0100108import android.telephony.data.ApnSetting;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800109import android.text.TextUtils;
zoey chen715880a2019-11-12 18:47:02 +0800110import android.util.ArrayMap;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800111import android.util.Log;
Jordan Liu6cf9bda2017-05-19 11:42:55 -0700112import android.util.Pair;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800113import android.util.Xml;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700114
Jordan Liu3de76f82017-05-15 15:21:01 -0700115import com.android.internal.annotations.GuardedBy;
Jordan Liue6f0bce2016-09-21 18:31:43 -0700116import com.android.internal.annotations.VisibleForTesting;
Amit Mahajan0c1d0dd2020-04-21 20:38:29 +0000117import com.android.internal.telephony.PhoneFactory;
Jeff Davidsonb114ed22017-04-09 14:55:23 -0700118import com.android.internal.util.XmlUtils;
Chen Xu9e3e0192019-09-16 18:26:19 -0700119import android.service.carrier.IApnSourceService;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800120
121import org.xmlpull.v1.XmlPullParser;
122import org.xmlpull.v1.XmlPullParserException;
123
Niklas Lindgren9392c702018-05-03 15:58:06 +0200124import java.io.ByteArrayOutputStream;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800125import java.io.File;
Jayachandran C0c685ce2019-10-17 11:11:56 -0700126import java.io.FileInputStream;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800127import java.io.FileNotFoundException;
128import java.io.FileReader;
129import java.io.IOException;
Niklas Lindgren9392c702018-05-03 15:58:06 +0200130import java.io.InputStream;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800131import java.util.ArrayList;
132import java.util.Arrays;
James.cf Lin90f42ec2020-04-21 22:23:31 +0800133import java.util.concurrent.atomic.AtomicBoolean;
Jordan Liu5d666212017-11-13 15:07:52 -0800134import java.util.HashMap;
Jordan Liu8b78f712018-05-21 11:10:48 -0700135import java.util.HashSet;
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700136import java.util.List;
Hall Liu5479f4d2018-07-14 00:31:13 +0000137import java.util.Locale;
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700138import java.util.Map;
Jordan Liu8b78f712018-05-21 11:10:48 -0700139import java.util.Set;
Jayachandran C0c685ce2019-10-17 11:11:56 -0700140import java.util.zip.CheckedInputStream;
calvinpanba94b592018-11-01 09:09:30 +0800141import java.util.zip.CRC32;
Wink Savilled7c93502011-06-04 07:17:01 -0700142
xiangyu.deng233d88c2021-07-16 14:09:40 +0800143import com.android.internal.telephony.dataconnection.ApnSettingUtils;
144import com.android.internal.telephony.uicc.IccRecords;
145import com.android.internal.telephony.uicc.UiccController;
146
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800147public class TelephonyProvider extends ContentProvider
148{
149 private static final String DATABASE_NAME = "telephony.db";
Fyodor Kupolov66304f62017-09-01 16:13:49 -0700150 private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
Wink Savilled7c93502011-06-04 07:17:01 -0700151 private static final boolean DBG = true;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800152 private static final boolean VDBG = false; // STOPSHIP if true
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700153
Brad Ebinger748c7622020-01-22 16:12:04 -0800154 private static final int DATABASE_VERSION = 45 << 16;
Wink Savillee84c0a82014-06-09 21:04:39 -0700155 private static final int URL_UNKNOWN = 0;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800156 private static final int URL_TELEPHONY = 1;
157 private static final int URL_CURRENT = 2;
158 private static final int URL_ID = 3;
159 private static final int URL_RESTOREAPN = 4;
John Huangb1bc16d2009-03-24 18:26:28 -0700160 private static final int URL_PREFERAPN = 5;
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600161 private static final int URL_PREFERAPN_NO_UPDATE = 6;
Wink Savillee84c0a82014-06-09 21:04:39 -0700162 private static final int URL_SIMINFO = 7;
163 private static final int URL_TELEPHONY_USING_SUBID = 8;
164 private static final int URL_CURRENT_USING_SUBID = 9;
165 private static final int URL_RESTOREAPN_USING_SUBID = 10;
166 private static final int URL_PREFERAPN_USING_SUBID = 11;
167 private static final int URL_PREFERAPN_NO_UPDATE_USING_SUBID = 12;
168 private static final int URL_SIMINFO_USING_SUBID = 13;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800169 private static final int URL_UPDATE_DB = 14;
Amit Mahajan7005be82017-04-26 10:35:18 -0700170 private static final int URL_DELETE = 15;
yuemingwc41e5c82017-11-09 13:30:33 +0000171 private static final int URL_DPC = 16;
172 private static final int URL_DPC_ID = 17;
173 private static final int URL_FILTERED = 18;
yuemingwcd80d172018-01-15 14:08:55 +0000174 private static final int URL_FILTERED_ID = 19;
175 private static final int URL_ENFORCE_MANAGED = 20;
Jordan Liu748c8322020-07-15 15:09:12 -0700176 // URL_PREFERAPNSET and URL_PREFERAPNSET_USING_SUBID return all APNs for the current
177 // carrier which have an apn_set_id equal to the preferred APN
178 // (if no preferred APN, or preferred APN has no set id, the query will return null)
Jordan Liuc6078b72018-05-01 11:34:21 -0700179 private static final int URL_PREFERAPNSET = 21;
180 private static final int URL_PREFERAPNSET_USING_SUBID = 22;
calvinpanba94b592018-11-01 09:09:30 +0800181 private static final int URL_SIM_APN_LIST = 23;
182 private static final int URL_SIM_APN_LIST_ID = 24;
Malcolm Chen09ebf8d2018-12-07 13:45:54 -0800183 private static final int URL_FILTERED_USING_SUBID = 25;
Josh Hou42049bb2018-12-10 22:22:05 +0800184 private static final int URL_SIM_APN_LIST_FILTERED = 26;
185 private static final int URL_SIM_APN_LIST_FILTERED_ID = 27;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800186
zoey chen715880a2019-11-12 18:47:02 +0800187 /**
188 * Default value for mtu if it's not set. Moved from PhoneConstants.
189 */
190 private static final int UNSPECIFIED_INT = -1;
191
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800192 private static final String TAG = "TelephonyProvider";
193 private static final String CARRIERS_TABLE = "carriers";
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800194 private static final String CARRIERS_TABLE_TMP = "carriers_tmp";
Wink Savillee84c0a82014-06-09 21:04:39 -0700195 private static final String SIMINFO_TABLE = "siminfo";
yinxu3d98b6c2018-01-05 16:27:30 -0800196 private static final String SIMINFO_TABLE_TMP = "siminfo_tmp";
John Huangb1bc16d2009-03-24 18:26:28 -0700197
Amit Mahajan28a5d002016-03-02 11:34:28 -0800198 private static final String PREF_FILE_APN = "preferred-apn";
John Huangb1bc16d2009-03-24 18:26:28 -0700199 private static final String COLUMN_APN_ID = "apn_id";
Amit Mahajanbf7144e2017-08-29 11:39:48 -0700200 private static final String EXPLICIT_SET_CALLED = "explicit_set_called";
John Huangb1bc16d2009-03-24 18:26:28 -0700201
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700202 private static final String PREF_FILE_FULL_APN = "preferred-full-apn";
203 private static final String DB_VERSION_KEY = "version";
204
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800205 private static final String BUILD_ID_FILE = "build-id";
206 private static final String RO_BUILD_ID = "ro_build_id";
207
yuemingwc41e5c82017-11-09 13:30:33 +0000208 private static final String ENFORCED_FILE = "dpc-apn-enforced";
209 private static final String ENFORCED_KEY = "enforced";
210
Amit Mahajan28a5d002016-03-02 11:34:28 -0800211 private static final String PREF_FILE = "telephonyprovider";
212 private static final String APN_CONF_CHECKSUM = "apn_conf_checksum";
213
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800214 private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";
Legler Wub16a1202014-12-29 13:20:29 +0800215 private static final String OEM_APNS_PATH = "telephony/apns-conf.xml";
Niklas Lindgren648f12e2018-05-21 16:48:20 +0200216 private static final String OTA_UPDATED_APNS_PATH = "misc/apns/apns-conf.xml";
Amit Mahajan899cc602015-05-14 17:22:09 -0700217 private static final String OLD_APNS_PATH = "etc/old-apns-conf.xml";
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800218
yuemingwe0101b82017-12-13 21:49:09 +0000219 private static final String DEFAULT_PROTOCOL = "IP";
220 private static final String DEFAULT_ROAMING_PROTOCOL = "IP";
221
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800222 private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
223
224 private static final ContentValues s_currentNullMap;
225 private static final ContentValues s_currentSetMap;
226
chen xu3e303942018-11-28 00:23:01 -0800227 private static final String IS_UNEDITED = EDITED_STATUS + "=" + UNEDITED;
228 private static final String IS_EDITED = EDITED_STATUS + "!=" + UNEDITED;
229 private static final String IS_USER_EDITED = EDITED_STATUS + "=" + USER_EDITED;
230 private static final String IS_NOT_USER_EDITED = EDITED_STATUS + "!=" + USER_EDITED;
231 private static final String IS_USER_DELETED = EDITED_STATUS + "=" + USER_DELETED;
232 private static final String IS_NOT_USER_DELETED = EDITED_STATUS + "!=" + USER_DELETED;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800233 private static final String IS_USER_DELETED_BUT_PRESENT_IN_XML =
chen xu3e303942018-11-28 00:23:01 -0800234 EDITED_STATUS + "=" + USER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800235 private static final String IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML =
chen xu3e303942018-11-28 00:23:01 -0800236 EDITED_STATUS + "!=" + USER_DELETED_BUT_PRESENT_IN_XML;
237 private static final String IS_CARRIER_EDITED = EDITED_STATUS + "=" + CARRIER_EDITED;
238 private static final String IS_NOT_CARRIER_EDITED = EDITED_STATUS + "!=" + CARRIER_EDITED;
239 private static final String IS_CARRIER_DELETED = EDITED_STATUS + "=" + CARRIER_DELETED;
240 private static final String IS_NOT_CARRIER_DELETED = EDITED_STATUS + "!=" + CARRIER_DELETED;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800241 private static final String IS_CARRIER_DELETED_BUT_PRESENT_IN_XML =
chen xu3e303942018-11-28 00:23:01 -0800242 EDITED_STATUS + "=" + CARRIER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800243 private static final String IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML =
chen xu3e303942018-11-28 00:23:01 -0800244 EDITED_STATUS + "!=" + CARRIER_DELETED_BUT_PRESENT_IN_XML;
yuemingwc41e5c82017-11-09 13:30:33 +0000245 private static final String IS_OWNED_BY_DPC = OWNED_BY + "=" + OWNED_BY_DPC;
246 private static final String IS_NOT_OWNED_BY_DPC = OWNED_BY + "!=" + OWNED_BY_DPC;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800247
Brad Ebinger1c69fea2018-03-27 11:33:16 -0700248 private static final String ORDER_BY_SUB_ID =
Peter Wangb8e281d2020-01-31 18:50:00 -0800249 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + " ASC";
Brad Ebinger1c69fea2018-03-27 11:33:16 -0700250
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700251 private static final int INVALID_APN_ID = -1;
252 private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>();
Jordan Liu8b78f712018-05-21 11:10:48 -0700253 private static final Set<String> CARRIERS_BOOLEAN_FIELDS = new HashSet<String>();
Jordan Liu5d666212017-11-13 15:07:52 -0800254 private static final Map<String, String> CARRIERS_UNIQUE_FIELDS_DEFAULTS = new HashMap();
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700255
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +0900256 @VisibleForTesting
257 static Boolean s_apnSourceServiceExists;
Jordan Liu3de76f82017-05-15 15:21:01 -0700258
259 protected final Object mLock = new Object();
260 @GuardedBy("mLock")
261 private IApnSourceService mIApnSourceService;
yuemingwc41e5c82017-11-09 13:30:33 +0000262 private Injector mInjector;
263
264 private boolean mManagedApnEnforced;
Jordan Liu3de76f82017-05-15 15:21:01 -0700265
SongFerngWang64fb3dd2019-12-02 20:59:47 +0800266 /**
267 * Available radio technologies for GSM, UMTS and CDMA.
268 * Duplicates the constants from hardware/radio/include/ril.h
269 * This should only be used by agents working with the ril. Others
270 * should use the equivalent TelephonyManager.NETWORK_TYPE_*
271 */
272 private static final int RIL_RADIO_TECHNOLOGY_UNKNOWN = 0;
273 private static final int RIL_RADIO_TECHNOLOGY_GPRS = 1;
274 private static final int RIL_RADIO_TECHNOLOGY_EDGE = 2;
275 private static final int RIL_RADIO_TECHNOLOGY_UMTS = 3;
276 private static final int RIL_RADIO_TECHNOLOGY_IS95A = 4;
277 private static final int RIL_RADIO_TECHNOLOGY_IS95B = 5;
278 private static final int RIL_RADIO_TECHNOLOGY_1xRTT = 6;
279 private static final int RIL_RADIO_TECHNOLOGY_EVDO_0 = 7;
280 private static final int RIL_RADIO_TECHNOLOGY_EVDO_A = 8;
281 private static final int RIL_RADIO_TECHNOLOGY_HSDPA = 9;
282 private static final int RIL_RADIO_TECHNOLOGY_HSUPA = 10;
283 private static final int RIL_RADIO_TECHNOLOGY_HSPA = 11;
284 private static final int RIL_RADIO_TECHNOLOGY_EVDO_B = 12;
285 private static final int RIL_RADIO_TECHNOLOGY_EHRPD = 13;
286 private static final int RIL_RADIO_TECHNOLOGY_LTE = 14;
287 private static final int RIL_RADIO_TECHNOLOGY_HSPAP = 15;
288
289 /**
290 * GSM radio technology only supports voice. It does not support data.
291 */
292 private static final int RIL_RADIO_TECHNOLOGY_GSM = 16;
293 private static final int RIL_RADIO_TECHNOLOGY_TD_SCDMA = 17;
294
295 /**
296 * IWLAN
297 */
298 private static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18;
299
300 /**
301 * LTE_CA
302 */
303 private static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
304
305 /**
306 * NR(New Radio) 5G.
307 */
308 private static final int RIL_RADIO_TECHNOLOGY_NR = 20;
309
310 /**
311 * The number of the radio technologies.
312 */
313 private static final int NEXT_RIL_RADIO_TECHNOLOGY = 21;
314
zoey chen715880a2019-11-12 18:47:02 +0800315 private static final Map<String, Integer> MVNO_TYPE_STRING_MAP;
316
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700317 static {
318 // Columns not included in UNIQUE constraint: name, current, edited, user, server, password,
Amit Mahajan28a5d002016-03-02 11:34:28 -0800319 // authtype, type, protocol, roaming_protocol, sub_id, modem_cognitive, max_conns,
Yuuki Habu95aacb12019-02-22 10:49:06 +0900320 // wait_time, max_conns_time, mtu, bearer_bitmask, user_visible, network_type_bitmask,
321 // skip_464xlat
Jordan Liu5d666212017-11-13 15:07:52 -0800322 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(NUMERIC, "");
323 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MCC, "");
324 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MNC, "");
325 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN, "");
326 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROXY, "");
327 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PORT, "");
328 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPROXY, "");
329 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPORT, "");
330 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSC, "");
331 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ENABLED, "1");
332 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(BEARER, "0");
333 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_TYPE, "");
334 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_MATCH_DATA, "");
335 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROFILE_ID, "0");
336 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROTOCOL, "IP");
337 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(ROAMING_PROTOCOL, "IP");
338 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(USER_EDITABLE, "1");
339 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(OWNED_BY, String.valueOf(OWNED_BY_OTHERS));
chen xu3e303942018-11-28 00:23:01 -0800340 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN_SET_ID, String.valueOf(NO_APN_SET_ID));
calvinpan2b419442018-10-23 15:05:11 +0800341 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ID,
342 String.valueOf(TelephonyManager.UNKNOWN_CARRIER_ID));
Jordan Liu5d666212017-11-13 15:07:52 -0800343
344 CARRIERS_UNIQUE_FIELDS.addAll(CARRIERS_UNIQUE_FIELDS_DEFAULTS.keySet());
Jordan Liu8b78f712018-05-21 11:10:48 -0700345
346 // SQLite databases store bools as ints but the ContentValues objects passed in through
347 // queries use bools. As a result there is some special handling of boolean fields within
348 // the TelephonyProvider.
349 CARRIERS_BOOLEAN_FIELDS.add(CARRIER_ENABLED);
chen xu3e303942018-11-28 00:23:01 -0800350 CARRIERS_BOOLEAN_FIELDS.add(MODEM_PERSIST);
Jordan Liu8b78f712018-05-21 11:10:48 -0700351 CARRIERS_BOOLEAN_FIELDS.add(USER_VISIBLE);
352 CARRIERS_BOOLEAN_FIELDS.add(USER_EDITABLE);
zoey chen715880a2019-11-12 18:47:02 +0800353
354 MVNO_TYPE_STRING_MAP = new ArrayMap<String, Integer>();
355 MVNO_TYPE_STRING_MAP.put("spn", ApnSetting.MVNO_TYPE_SPN);
356 MVNO_TYPE_STRING_MAP.put("imsi", ApnSetting.MVNO_TYPE_IMSI);
357 MVNO_TYPE_STRING_MAP.put("gid", ApnSetting.MVNO_TYPE_GID);
358 MVNO_TYPE_STRING_MAP.put("iccid", ApnSetting.MVNO_TYPE_ICCID);
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700359 }
360
Jordan Liue6f0bce2016-09-21 18:31:43 -0700361 @VisibleForTesting
pkanware08f3ac2017-02-02 18:26:32 -0800362 public static String getStringForCarrierTableCreation(String tableName) {
363 return "CREATE TABLE " + tableName +
364 "(_id INTEGER PRIMARY KEY," +
365 NAME + " TEXT DEFAULT ''," +
366 NUMERIC + " TEXT DEFAULT ''," +
367 MCC + " TEXT DEFAULT ''," +
368 MNC + " TEXT DEFAULT ''," +
calvinpan2b419442018-10-23 15:05:11 +0800369 CARRIER_ID + " INTEGER DEFAULT " + TelephonyManager.UNKNOWN_CARRIER_ID + "," +
pkanware08f3ac2017-02-02 18:26:32 -0800370 APN + " TEXT DEFAULT ''," +
371 USER + " TEXT DEFAULT ''," +
372 SERVER + " TEXT DEFAULT ''," +
373 PASSWORD + " TEXT DEFAULT ''," +
374 PROXY + " TEXT DEFAULT ''," +
375 PORT + " TEXT DEFAULT ''," +
376 MMSPROXY + " TEXT DEFAULT ''," +
377 MMSPORT + " TEXT DEFAULT ''," +
378 MMSC + " TEXT DEFAULT ''," +
379 AUTH_TYPE + " INTEGER DEFAULT -1," +
380 TYPE + " TEXT DEFAULT ''," +
381 CURRENT + " INTEGER," +
yuemingwe0101b82017-12-13 21:49:09 +0000382 PROTOCOL + " TEXT DEFAULT " + DEFAULT_PROTOCOL + "," +
383 ROAMING_PROTOCOL + " TEXT DEFAULT " + DEFAULT_ROAMING_PROTOCOL + "," +
Jordan Liu8b78f712018-05-21 11:10:48 -0700384 CARRIER_ENABLED + " BOOLEAN DEFAULT 1," + // SQLite databases store bools as ints
pkanware08f3ac2017-02-02 18:26:32 -0800385 BEARER + " INTEGER DEFAULT 0," +
386 BEARER_BITMASK + " INTEGER DEFAULT 0," +
Cassiea58ce712017-12-06 16:21:50 -0800387 NETWORK_TYPE_BITMASK + " INTEGER DEFAULT 0," +
pkanware08f3ac2017-02-02 18:26:32 -0800388 MVNO_TYPE + " TEXT DEFAULT ''," +
389 MVNO_MATCH_DATA + " TEXT DEFAULT ''," +
calvinpan2b419442018-10-23 15:05:11 +0800390 SUBSCRIPTION_ID + " INTEGER DEFAULT " +
391 SubscriptionManager.INVALID_SUBSCRIPTION_ID + "," +
pkanware08f3ac2017-02-02 18:26:32 -0800392 PROFILE_ID + " INTEGER DEFAULT 0," +
chen xu3e303942018-11-28 00:23:01 -0800393 MODEM_PERSIST + " BOOLEAN DEFAULT 0," +
394 MAX_CONNECTIONS + " INTEGER DEFAULT 0," +
395 WAIT_TIME_RETRY + " INTEGER DEFAULT 0," +
396 TIME_LIMIT_FOR_MAX_CONNECTIONS + " INTEGER DEFAULT 0," +
pkanware08f3ac2017-02-02 18:26:32 -0800397 MTU + " INTEGER DEFAULT 0," +
chen xu3e303942018-11-28 00:23:01 -0800398 EDITED_STATUS + " INTEGER DEFAULT " + UNEDITED + "," +
pkanware08f3ac2017-02-02 18:26:32 -0800399 USER_VISIBLE + " BOOLEAN DEFAULT 1," +
Amit Mahajan460d7032017-07-17 14:42:33 -0700400 USER_EDITABLE + " BOOLEAN DEFAULT 1," +
yuemingwc4d40a72017-11-08 14:14:37 +0000401 OWNED_BY + " INTEGER DEFAULT " + OWNED_BY_OTHERS + "," +
chen xu3e303942018-11-28 00:23:01 -0800402 APN_SET_ID + " INTEGER DEFAULT " + NO_APN_SET_ID + "," +
Yuuki Habu95aacb12019-02-22 10:49:06 +0900403 SKIP_464XLAT + " INTEGER DEFAULT " + SKIP_464XLAT_DEFAULT + "," +
pkanware08f3ac2017-02-02 18:26:32 -0800404 // Uniqueness collisions are used to trigger merge code so if a field is listed
405 // here it means we will accept both (user edited + new apn_conf definition)
406 // Columns not included in UNIQUE constraint: name, current, edited,
407 // user, server, password, authtype, type, sub_id, modem_cognitive, max_conns,
Cassiea58ce712017-12-06 16:21:50 -0800408 // wait_time, max_conns_time, mtu, bearer_bitmask, user_visible,
Yuuki Habu95aacb12019-02-22 10:49:06 +0900409 // network_type_bitmask, skip_464xlat.
pkanware08f3ac2017-02-02 18:26:32 -0800410 "UNIQUE (" + TextUtils.join(", ", CARRIERS_UNIQUE_FIELDS) + "));";
411 }
Jordan Liue6f0bce2016-09-21 18:31:43 -0700412
413 @VisibleForTesting
yinxu3d98b6c2018-01-05 16:27:30 -0800414 public static String getStringForSimInfoTableCreation(String tableName) {
415 return "CREATE TABLE " + tableName + "("
Peter Wangb8e281d2020-01-31 18:50:00 -0800416 + Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID
Jordan Liue6f0bce2016-09-21 18:31:43 -0700417 + " INTEGER PRIMARY KEY AUTOINCREMENT,"
Peter Wangb8e281d2020-01-31 18:50:00 -0800418 + Telephony.SimInfo.COLUMN_ICC_ID + " TEXT NOT NULL,"
419 + Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX
Peter Wangb097cb62019-12-05 11:01:18 -0800420 + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_NOT_INSERTED + ","
Peter Wangb8e281d2020-01-31 18:50:00 -0800421 + Telephony.SimInfo.COLUMN_DISPLAY_NAME + " TEXT,"
422 + Telephony.SimInfo.COLUMN_CARRIER_NAME + " TEXT,"
423 + Telephony.SimInfo.COLUMN_NAME_SOURCE
424 + " INTEGER DEFAULT " + Telephony.SimInfo.NAME_SOURCE_CARRIER_ID + ","
425 + Telephony.SimInfo.COLUMN_COLOR + " INTEGER DEFAULT "
Peter Wangb097cb62019-12-05 11:01:18 -0800426 + Telephony.SimInfo.COLOR_DEFAULT + ","
Peter Wangb8e281d2020-01-31 18:50:00 -0800427 + Telephony.SimInfo.COLUMN_NUMBER + " TEXT,"
428 + Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT
Peter Wangb097cb62019-12-05 11:01:18 -0800429 + " INTEGER NOT NULL DEFAULT " + Telephony.SimInfo.DISPLAY_NUMBER_DEFAULT + ","
Peter Wangb8e281d2020-01-31 18:50:00 -0800430 + Telephony.SimInfo.COLUMN_DATA_ROAMING
431 + " INTEGER DEFAULT " + Telephony.SimInfo.DATA_ROAMING_DISABLE + ","
432 + Telephony.SimInfo.COLUMN_MCC + " INTEGER DEFAULT 0,"
433 + Telephony.SimInfo.COLUMN_MNC + " INTEGER DEFAULT 0,"
434 + Telephony.SimInfo.COLUMN_MCC_STRING + " TEXT,"
435 + Telephony.SimInfo.COLUMN_MNC_STRING + " TEXT,"
436 + Telephony.SimInfo.COLUMN_EHPLMNS + " TEXT,"
437 + Telephony.SimInfo.COLUMN_HPLMNS + " TEXT,"
438 + Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS
Peter Wangb097cb62019-12-05 11:01:18 -0800439 + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_PROVISIONED + ","
Peter Wangb8e281d2020-01-31 18:50:00 -0800440 + Telephony.SimInfo.COLUMN_IS_EMBEDDED + " INTEGER DEFAULT 0,"
441 + Telephony.SimInfo.COLUMN_CARD_ID + " TEXT NOT NULL,"
442 + Telephony.SimInfo.COLUMN_ACCESS_RULES + " BLOB,"
443 + Telephony.SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB,"
444 + Telephony.SimInfo.COLUMN_IS_REMOVABLE + " INTEGER DEFAULT 0,"
445 + Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
446 + Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
447 + Telephony.SimInfo.COLUMN_CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
448 + Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
449 + Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
450 + Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
451 + Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
452 + Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
453 + Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
454 + Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
455 + Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
456 + Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1,"
457 + Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED + " INTEGER DEFAULT -1,"
458 + Telephony.SimInfo.COLUMN_VT_IMS_ENABLED + " INTEGER DEFAULT -1,"
459 + Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED + " INTEGER DEFAULT -1,"
460 + Telephony.SimInfo.COLUMN_WFC_IMS_MODE + " INTEGER DEFAULT -1,"
461 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1,"
462 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1,"
463 + Telephony.SimInfo.COLUMN_IS_OPPORTUNISTIC + " INTEGER DEFAULT 0,"
464 + Telephony.SimInfo.COLUMN_GROUP_UUID + " TEXT,"
465 + Telephony.SimInfo.COLUMN_IS_METERED + " INTEGER DEFAULT 1,"
466 + Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE + " TEXT,"
467 + Telephony.SimInfo.COLUMN_CARRIER_ID + " INTEGER DEFAULT -1,"
468 + Telephony.SimInfo.COLUMN_PROFILE_CLASS + " INTEGER DEFAULT "
469 + Telephony.SimInfo.PROFILE_CLASS_UNSET + ","
470 + Telephony.SimInfo.COLUMN_SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
Peter Wangb097cb62019-12-05 11:01:18 -0800471 + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ","
Peter Wangb8e281d2020-01-31 18:50:00 -0800472 + Telephony.SimInfo.COLUMN_GROUP_OWNER + " TEXT,"
473 + Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES + " TEXT,"
474 + Telephony.SimInfo.COLUMN_IMSI + " TEXT,"
475 + Telephony.SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED + " INTEGER DEFAULT 1,"
476 + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES + " BIGINT DEFAULT -1,"
477 + Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED + " INTEGER DEFAULT 0"
yinxu3d98b6c2018-01-05 16:27:30 -0800478 + ");";
479 }
Jordan Liue6f0bce2016-09-21 18:31:43 -0700480
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800481 static {
482 s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY);
483 s_urlMatcher.addURI("telephony", "carriers/current", URL_CURRENT);
484 s_urlMatcher.addURI("telephony", "carriers/#", URL_ID);
485 s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN);
John Huangb1bc16d2009-03-24 18:26:28 -0700486 s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN);
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600487 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE);
Jordan Liuc6078b72018-05-01 11:34:21 -0700488 s_urlMatcher.addURI("telephony", "carriers/preferapnset", URL_PREFERAPNSET);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800489
Wink Savillee84c0a82014-06-09 21:04:39 -0700490 s_urlMatcher.addURI("telephony", "siminfo", URL_SIMINFO);
chen xu195e2ec2018-10-02 18:42:41 -0700491 s_urlMatcher.addURI("telephony", "siminfo/#", URL_SIMINFO_USING_SUBID);
Wink Savillee84c0a82014-06-09 21:04:39 -0700492
493 s_urlMatcher.addURI("telephony", "carriers/subId/*", URL_TELEPHONY_USING_SUBID);
494 s_urlMatcher.addURI("telephony", "carriers/current/subId/*", URL_CURRENT_USING_SUBID);
495 s_urlMatcher.addURI("telephony", "carriers/restore/subId/*", URL_RESTOREAPN_USING_SUBID);
496 s_urlMatcher.addURI("telephony", "carriers/preferapn/subId/*", URL_PREFERAPN_USING_SUBID);
497 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update/subId/*",
498 URL_PREFERAPN_NO_UPDATE_USING_SUBID);
Jordan Liuc6078b72018-05-01 11:34:21 -0700499 s_urlMatcher.addURI("telephony", "carriers/preferapnset/subId/*",
500 URL_PREFERAPNSET_USING_SUBID);
Wink Savillee84c0a82014-06-09 21:04:39 -0700501
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800502 s_urlMatcher.addURI("telephony", "carriers/update_db", URL_UPDATE_DB);
Amit Mahajan7005be82017-04-26 10:35:18 -0700503 s_urlMatcher.addURI("telephony", "carriers/delete", URL_DELETE);
Wink Savillee84c0a82014-06-09 21:04:39 -0700504
yuemingwc41e5c82017-11-09 13:30:33 +0000505 // Only called by DevicePolicyManager to manipulate DPC records.
506 s_urlMatcher.addURI("telephony", "carriers/dpc", URL_DPC);
507 // Only called by DevicePolicyManager to manipulate a DPC record with certain _ID.
508 s_urlMatcher.addURI("telephony", "carriers/dpc/#", URL_DPC_ID);
509 // Only called by Settings app, DcTracker and other telephony components to get APN list
510 // according to whether DPC records are enforced.
511 s_urlMatcher.addURI("telephony", "carriers/filtered", URL_FILTERED);
yuemingwcd80d172018-01-15 14:08:55 +0000512 // Only called by Settings app, DcTracker and other telephony components to get a
513 // single APN according to whether DPC records are enforced.
514 s_urlMatcher.addURI("telephony", "carriers/filtered/#", URL_FILTERED_ID);
Malcolm Chen09ebf8d2018-12-07 13:45:54 -0800515 // Used by DcTracker to pass a subId.
516 s_urlMatcher.addURI("telephony", "carriers/filtered/subId/*", URL_FILTERED_USING_SUBID);
517
yuemingwc41e5c82017-11-09 13:30:33 +0000518 // Only Called by DevicePolicyManager to enforce DPC records.
519 s_urlMatcher.addURI("telephony", "carriers/enforce_managed", URL_ENFORCE_MANAGED);
calvinpanba94b592018-11-01 09:09:30 +0800520 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list", URL_SIM_APN_LIST);
521 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list/#", URL_SIM_APN_LIST_ID);
Josh Hou42049bb2018-12-10 22:22:05 +0800522 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list/filtered",
523 URL_SIM_APN_LIST_FILTERED);
524 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list/filtered/subId/*",
525 URL_SIM_APN_LIST_FILTERED_ID);
yuemingwc41e5c82017-11-09 13:30:33 +0000526
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800527 s_currentNullMap = new ContentValues(1);
Amit Mahajan28a5d002016-03-02 11:34:28 -0800528 s_currentNullMap.put(CURRENT, "0");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800529
530 s_currentSetMap = new ContentValues(1);
Amit Mahajan28a5d002016-03-02 11:34:28 -0800531 s_currentSetMap.put(CURRENT, "1");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800532 }
533
yuemingwc41e5c82017-11-09 13:30:33 +0000534 /**
535 * Unit test will subclass it to inject mocks.
536 */
537 @VisibleForTesting
538 static class Injector {
539 int binderGetCallingUid() {
540 return Binder.getCallingUid();
541 }
542 }
543
544 public TelephonyProvider() {
545 this(new Injector());
546 }
547
548 @VisibleForTesting
549 public TelephonyProvider(Injector injector) {
550 mInjector = injector;
551 }
552
Jordan Liuc591b112018-05-02 16:35:03 -0700553 @VisibleForTesting
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -0700554 public static int getVersion(Context context) {
555 if (VDBG) log("getVersion:+");
556 // Get the database version, combining a static schema version and the XML version
557 Resources r = context.getResources();
558 if (r == null) {
559 loge("resources=null, return version=" + Integer.toHexString(DATABASE_VERSION));
560 return DATABASE_VERSION;
561 }
562 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
563 try {
564 XmlUtils.beginDocument(parser, "apns");
565 int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
566 int version = DATABASE_VERSION | publicversion;
567 if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
568 return version;
569 } catch (Exception e) {
570 loge("Can't get version of APN database" + e + " return version=" +
571 Integer.toHexString(DATABASE_VERSION));
572 return DATABASE_VERSION;
573 } finally {
574 parser.close();
575 }
576 }
577
578 static public ContentValues setDefaultValue(ContentValues values) {
579 if (!values.containsKey(SUBSCRIPTION_ID)) {
580 int subId = SubscriptionManager.getDefaultSubscriptionId();
581 values.put(SUBSCRIPTION_ID, subId);
582 }
583
584 return values;
585 }
586
587 @VisibleForTesting
588 public class DatabaseHelper extends SQLiteOpenHelper {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800589 // Context to access resources with
590 private Context mContext;
591
592 /**
593 * DatabaseHelper helper class for loading apns into a database.
594 *
Wink Savilled7c93502011-06-04 07:17:01 -0700595 * @param context of the user.
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800596 */
597 public DatabaseHelper(Context context) {
598 super(context, DATABASE_NAME, null, getVersion(context));
599 mContext = context;
Fyodor Kupolov66304f62017-09-01 16:13:49 -0700600 // Memory optimization - close idle connections after 30s of inactivity
601 setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
Makoto Onukie6842ee2018-09-07 11:32:47 -0700602 setWriteAheadLoggingEnabled(false);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800603 }
604
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800605 @Override
606 public void onCreate(SQLiteDatabase db) {
Wink Saville6de10272014-06-22 07:38:43 -0700607 if (DBG) log("dbh.onCreate:+ db=" + db);
yinxu3d98b6c2018-01-05 16:27:30 -0800608 createSimInfoTable(db, SIMINFO_TABLE);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800609 createCarriersTable(db, CARRIERS_TABLE);
Jordan Liu3de76f82017-05-15 15:21:01 -0700610 // if CarrierSettings app is installed, we expect it to do the initializiation instead
611 if (apnSourceServiceExists(mContext)) {
612 log("dbh.onCreate: Skipping apply APNs from xml.");
613 } else {
614 log("dbh.onCreate: Apply apns from xml.");
615 initDatabase(db);
616 }
Wink Saville6de10272014-06-22 07:38:43 -0700617 if (DBG) log("dbh.onCreate:- db=" + db);
618 }
619
620 @Override
621 public void onOpen(SQLiteDatabase db) {
622 if (VDBG) log("dbh.onOpen:+ db=" + db);
623 try {
624 // Try to access the table and create it if "no such table"
625 db.query(SIMINFO_TABLE, null, null, null, null, null, null);
626 if (DBG) log("dbh.onOpen: ok, queried table=" + SIMINFO_TABLE);
627 } catch (SQLiteException e) {
628 loge("Exception " + SIMINFO_TABLE + "e=" + e);
629 if (e.getMessage().startsWith("no such table")) {
yinxu3d98b6c2018-01-05 16:27:30 -0800630 createSimInfoTable(db, SIMINFO_TABLE);
Wink Saville6de10272014-06-22 07:38:43 -0700631 }
632 }
633 try {
634 db.query(CARRIERS_TABLE, null, null, null, null, null, null);
635 if (DBG) log("dbh.onOpen: ok, queried table=" + CARRIERS_TABLE);
636 } catch (SQLiteException e) {
637 loge("Exception " + CARRIERS_TABLE + " e=" + e);
638 if (e.getMessage().startsWith("no such table")) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800639 createCarriersTable(db, CARRIERS_TABLE);
Wink Saville6de10272014-06-22 07:38:43 -0700640 }
641 }
642 if (VDBG) log("dbh.onOpen:- db=" + db);
643 }
644
yinxu3d98b6c2018-01-05 16:27:30 -0800645 private void createSimInfoTable(SQLiteDatabase db, String tableName) {
646 if (DBG) log("dbh.createSimInfoTable:+ " + tableName);
647 db.execSQL(getStringForSimInfoTableCreation(tableName));
Wink Saville6de10272014-06-22 07:38:43 -0700648 if (DBG) log("dbh.createSimInfoTable:-");
649 }
650
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800651 private void createCarriersTable(SQLiteDatabase db, String tableName) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800652 // Set up the database schema
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800653 if (DBG) log("dbh.createCarriersTable: " + tableName);
pkanware08f3ac2017-02-02 18:26:32 -0800654 db.execSQL(getStringForCarrierTableCreation(tableName));
Wink Saville6de10272014-06-22 07:38:43 -0700655 if (DBG) log("dbh.createCarriersTable:-");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800656 }
Shri Borde7ed9c332014-09-15 13:46:01 -0700657
Amit Mahajan28a5d002016-03-02 11:34:28 -0800658 private long getChecksum(File file) {
Jayachandran C0c685ce2019-10-17 11:11:56 -0700659 CRC32 checkSummer = new CRC32();
660 long checkSum = -1;
661 try (CheckedInputStream cis =
662 new CheckedInputStream(new FileInputStream(file), checkSummer)){
663 byte[] buf = new byte[128];
664 if(cis != null) {
665 while(cis.read(buf) >= 0) {
666 // Just read for checksum to get calculated.
667 }
668 }
669 checkSum = checkSummer.getValue();
670 if (DBG) log("Checksum for " + file.getAbsolutePath() + " is " + checkSum);
Amit Mahajan28a5d002016-03-02 11:34:28 -0800671 } catch (FileNotFoundException e) {
672 loge("FileNotFoundException for " + file.getAbsolutePath() + ":" + e);
673 } catch (IOException e) {
674 loge("IOException for " + file.getAbsolutePath() + ":" + e);
675 }
Niklas Lindgren9392c702018-05-03 15:58:06 +0200676
677 // The RRO may have been updated in a firmware upgrade. Add checksum for the
678 // resources to the total checksum so that apns in an RRO update is not missed.
679 try (InputStream inputStream = mContext.getResources().
680 openRawResource(com.android.internal.R.xml.apns)) {
681 byte[] array = toByteArray(inputStream);
Jayachandran C0c685ce2019-10-17 11:11:56 -0700682 checkSummer.reset();
683 checkSummer.update(array);
684 checkSum += checkSummer.getValue();
685 if (DBG) log("Checksum after adding resource is " + checkSummer.getValue());
Niklas Lindgren9392c702018-05-03 15:58:06 +0200686 } catch (IOException | Resources.NotFoundException e) {
687 loge("Exception when calculating checksum for internal apn resources: " + e);
688 }
Jayachandran C0c685ce2019-10-17 11:11:56 -0700689 return checkSum;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800690 }
691
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -0700692 private byte[] toByteArray(InputStream input) throws IOException {
Niklas Lindgren9392c702018-05-03 15:58:06 +0200693 byte[] buffer = new byte[128];
694 int bytesRead;
695 ByteArrayOutputStream output = new ByteArrayOutputStream();
696 while ((bytesRead = input.read(buffer)) != -1) {
697 output.write(buffer, 0, bytesRead);
698 }
699 return output.toByteArray();
700 }
701
Amit Mahajan28a5d002016-03-02 11:34:28 -0800702 private long getApnConfChecksum() {
703 SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
704 return sp.getLong(APN_CONF_CHECKSUM, -1);
705 }
706
707 private void setApnConfChecksum(long checksum) {
708 SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
709 SharedPreferences.Editor editor = sp.edit();
710 editor.putLong(APN_CONF_CHECKSUM, checksum);
711 editor.apply();
712 }
713
714 private File getApnConfFile() {
715 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
716 File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);
717 File oemConfFile = new File(Environment.getOemDirectory(), OEM_APNS_PATH);
718 File updatedConfFile = new File(Environment.getDataDirectory(), OTA_UPDATED_APNS_PATH);
Miaocf39f062018-12-14 08:50:03 +0800719 File productConfFile = new File(Environment.getProductDirectory(), PARTNER_APNS_PATH);
bohu075ee992018-05-24 14:20:28 -0700720 confFile = pickSecondIfExists(confFile, oemConfFile);
Miaocf39f062018-12-14 08:50:03 +0800721 confFile = pickSecondIfExists(confFile, productConfFile);
bohu075ee992018-05-24 14:20:28 -0700722 confFile = pickSecondIfExists(confFile, updatedConfFile);
Amit Mahajan28a5d002016-03-02 11:34:28 -0800723 return confFile;
724 }
725
726 /**
727 * This function computes checksum for the file to be read and compares it against the
728 * last read file. DB needs to be updated only if checksum has changed, or old checksum does
729 * not exist.
730 * @return true if DB should be updated with new conf file, false otherwise
731 */
732 private boolean apnDbUpdateNeeded() {
733 File confFile = getApnConfFile();
734 long newChecksum = getChecksum(confFile);
735 long oldChecksum = getApnConfChecksum();
736 if (DBG) log("newChecksum: " + newChecksum);
737 if (DBG) log("oldChecksum: " + oldChecksum);
738 if (newChecksum == oldChecksum) {
739 return false;
740 } else {
741 return true;
742 }
743 }
744
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700745 /**
746 * This function adds APNs from xml file(s) to db. The db may or may not be empty to begin
747 * with.
748 */
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800749 private void initDatabase(SQLiteDatabase db) {
Wink Saville6de10272014-06-22 07:38:43 -0700750 if (VDBG) log("dbh.initDatabase:+ db=" + db);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800751 // Read internal APNS data
752 Resources r = mContext.getResources();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800753 int publicversion = -1;
Jordan Liuc591b112018-05-02 16:35:03 -0700754 if (r != null) {
755 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
756 try {
757 XmlUtils.beginDocument(parser, "apns");
758 publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
759 loadApns(db, parser);
760 } catch (Exception e) {
761 loge("Got exception while loading APN database." + e);
762 } finally {
763 parser.close();
764 }
765 } else {
766 loge("initDatabase: resources=null");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800767 }
768
Sungmin Choi22b63062013-01-25 15:53:15 +0900769 // Read external APNS data (partner-provided)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800770 XmlPullParser confparser = null;
Amit Mahajan28a5d002016-03-02 11:34:28 -0800771 File confFile = getApnConfFile();
Legler Wub16a1202014-12-29 13:20:29 +0800772
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800773 FileReader confreader = null;
Legler Wub16a1202014-12-29 13:20:29 +0800774 if (DBG) log("confFile = " + confFile);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800775 try {
776 confreader = new FileReader(confFile);
777 confparser = Xml.newPullParser();
778 confparser.setInput(confreader);
779 XmlUtils.beginDocument(confparser, "apns");
780
781 // Sanity check. Force internal version and confidential versions to agree
782 int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version"));
783 if (publicversion != confversion) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800784 log("initDatabase: throwing exception due to version mismatch");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800785 throw new IllegalStateException("Internal APNS file version doesn't match "
786 + confFile.getAbsolutePath());
787 }
788
789 loadApns(db, confparser);
790 } catch (FileNotFoundException e) {
791 // It's ok if the file isn't found. It means there isn't a confidential file
792 // Log.e(TAG, "File not found: '" + confFile.getAbsolutePath() + "'");
793 } catch (Exception e) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800794 loge("initDatabase: Exception while parsing '" + confFile.getAbsolutePath() + "'" +
795 e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800796 } finally {
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700797 // Get rid of user/carrier deleted entries that are not present in apn xml file.
Amit Mahajanb80f7332015-04-16 10:02:52 -0700798 // Those entries have edited value USER_DELETED/CARRIER_DELETED.
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800799 if (VDBG) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700800 log("initDatabase: deleting USER_DELETED and replacing "
801 + "DELETED_BUT_PRESENT_IN_XML with DELETED");
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800802 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700803
804 // Delete USER_DELETED
Amit Mahajan28a5d002016-03-02 11:34:28 -0800805 db.delete(CARRIERS_TABLE, IS_USER_DELETED + " or " + IS_CARRIER_DELETED, null);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700806
807 // Change USER_DELETED_BUT_PRESENT_IN_XML to USER_DELETED
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800808 ContentValues cv = new ContentValues();
chen xu3e303942018-11-28 00:23:01 -0800809 cv.put(EDITED_STATUS, USER_DELETED);
Amit Mahajan28a5d002016-03-02 11:34:28 -0800810 db.update(CARRIERS_TABLE, cv, IS_USER_DELETED_BUT_PRESENT_IN_XML, null);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700811
812 // Change CARRIER_DELETED_BUT_PRESENT_IN_XML to CARRIER_DELETED
813 cv = new ContentValues();
chen xu3e303942018-11-28 00:23:01 -0800814 cv.put(EDITED_STATUS, CARRIER_DELETED);
Amit Mahajan28a5d002016-03-02 11:34:28 -0800815 db.update(CARRIERS_TABLE, cv, IS_CARRIER_DELETED_BUT_PRESENT_IN_XML, null);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700816
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800817 if (confreader != null) {
818 try {
819 confreader.close();
820 } catch (IOException e) {
821 // do nothing
822 }
823 }
Amit Mahajan28a5d002016-03-02 11:34:28 -0800824
825 // Update the stored checksum
826 setApnConfChecksum(getChecksum(confFile));
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800827 }
Wink Saville6de10272014-06-22 07:38:43 -0700828 if (VDBG) log("dbh.initDatabase:- db=" + db);
Amit Mahajanb0688862014-08-13 16:53:51 +0000829
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800830 }
831
bohu075ee992018-05-24 14:20:28 -0700832 private File pickSecondIfExists(File sysApnFile, File altApnFile) {
Amit Mahajanb80f7332015-04-16 10:02:52 -0700833 if (altApnFile.exists()) {
bohu075ee992018-05-24 14:20:28 -0700834 if (DBG) log("Load APNs from " + altApnFile.getPath() +
835 " instead of " + sysApnFile.getPath());
836 return altApnFile;
Amit Mahajanb80f7332015-04-16 10:02:52 -0700837 } else {
bohu075ee992018-05-24 14:20:28 -0700838 if (DBG) log("Load APNs from " + sysApnFile.getPath() +
839 " instead of " + altApnFile.getPath());
840 return sysApnFile;
Amit Mahajanb80f7332015-04-16 10:02:52 -0700841 }
Amit Mahajanb80f7332015-04-16 10:02:52 -0700842 }
843
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800844 @Override
845 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Wink Saville6de10272014-06-22 07:38:43 -0700846 if (DBG) {
847 log("dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
848 }
849
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -0700850 deletePreferredApnId(mContext);
851
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700852 if (oldVersion < (5 << 16 | 6)) {
853 // 5 << 16 is the Database version and 6 in the xml version.
854
855 // This change adds a new authtype column to the database.
856 // The auth type column can have 4 values: 0 (None), 1 (PAP), 2 (CHAP)
857 // 3 (PAP or CHAP). To avoid breaking compatibility, with already working
858 // APNs, the unset value (-1) will be used. If the value is -1.
859 // the authentication will default to 0 (if no user / password) is specified
860 // or to 3. Currently, there have been no reported problems with
861 // pre-configured APNs and hence it is set to -1 for them. Similarly,
862 // if the user, has added a new APN, we set the authentication type
863 // to -1.
864
865 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
866 " ADD COLUMN authtype INTEGER DEFAULT -1;");
867
868 oldVersion = 5 << 16 | 6;
869 }
Lorenzo Colitti9dd054f2010-12-29 15:54:00 -0800870 if (oldVersion < (6 << 16 | 6)) {
871 // Add protcol fields to the APN. The XML file does not change.
872 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
873 " ADD COLUMN protocol TEXT DEFAULT IP;");
874 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
875 " ADD COLUMN roaming_protocol TEXT DEFAULT IP;");
876 oldVersion = 6 << 16 | 6;
877 }
sinikangbae4b072011-09-02 09:49:37 +0900878 if (oldVersion < (7 << 16 | 6)) {
Sungmin Choi22b63062013-01-25 15:53:15 +0900879 // Add carrier_enabled, bearer fields to the APN. The XML file does not change.
sinikangbae4b072011-09-02 09:49:37 +0900880 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
881 " ADD COLUMN carrier_enabled BOOLEAN DEFAULT 1;");
882 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
883 " ADD COLUMN bearer INTEGER DEFAULT 0;");
884 oldVersion = 7 << 16 | 6;
885 }
Sungmin Choi27045ef2013-01-25 17:48:06 +0900886 if (oldVersion < (8 << 16 | 6)) {
887 // Add mvno_type, mvno_match_data fields to the APN.
888 // The XML file does not change.
889 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
890 " ADD COLUMN mvno_type TEXT DEFAULT '';");
891 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
892 " ADD COLUMN mvno_match_data TEXT DEFAULT '';");
893 oldVersion = 8 << 16 | 6;
894 }
Wink Savillee84c0a82014-06-09 21:04:39 -0700895 if (oldVersion < (9 << 16 | 6)) {
896 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
Tom Taylor1ad5f912014-10-28 13:35:34 -0700897 " ADD COLUMN sub_id INTEGER DEFAULT " +
Wink Saville72b14732014-11-20 13:06:04 -0800898 SubscriptionManager.INVALID_SUBSCRIPTION_ID + ";");
Wink Savillee84c0a82014-06-09 21:04:39 -0700899 oldVersion = 9 << 16 | 6;
900 }
Amit Mahajanb0688862014-08-13 16:53:51 +0000901 if (oldVersion < (10 << 16 | 6)) {
902 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
903 " ADD COLUMN profile_id INTEGER DEFAULT 0;");
904 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
905 " ADD COLUMN modem_cognitive BOOLEAN DEFAULT 0;");
906 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
907 " ADD COLUMN max_conns INTEGER DEFAULT 0;");
908 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
909 " ADD COLUMN wait_time INTEGER DEFAULT 0;");
910 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
911 " ADD COLUMN max_conns_time INTEGER DEFAULT 0;");
912 oldVersion = 10 << 16 | 6;
913 }
w19976e9a6c452014-07-18 16:43:00 -0700914 if (oldVersion < (11 << 16 | 6)) {
915 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
916 " ADD COLUMN mtu INTEGER DEFAULT 0;");
917 oldVersion = 11 << 16 | 6;
918 }
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700919 if (oldVersion < (12 << 16 | 6)) {
Tom Taylorc55054d2014-09-10 11:01:44 -0700920 try {
921 // Try to update the siminfo table. It might not be there.
922 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
Peter Wangb8e281d2020-01-31 18:50:00 -0800923 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MCC + " INTEGER DEFAULT 0;");
Tom Taylorc55054d2014-09-10 11:01:44 -0700924 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
Peter Wangb8e281d2020-01-31 18:50:00 -0800925 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MNC + " INTEGER DEFAULT 0;");
Tom Taylorc55054d2014-09-10 11:01:44 -0700926 } catch (SQLiteException e) {
927 if (DBG) {
928 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
929 " The table will get created in onOpen.");
930 }
931 }
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700932 oldVersion = 12 << 16 | 6;
933 }
Sanket Padawe7e633bd2014-11-06 11:50:40 -0800934 if (oldVersion < (13 << 16 | 6)) {
935 try {
936 // Try to update the siminfo table. It might not be there.
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800937 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -0800938 Telephony.SimInfo.COLUMN_CARRIER_NAME + " TEXT DEFAULT '';");
Sanket Padawe7e633bd2014-11-06 11:50:40 -0800939 } catch (SQLiteException e) {
940 if (DBG) {
941 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
942 " The table will get created in onOpen.");
943 }
944 }
945 oldVersion = 13 << 16 | 6;
946 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800947 if (oldVersion < (14 << 16 | 6)) {
Amit Mahajanb80f7332015-04-16 10:02:52 -0700948 // Do nothing. This is to avoid recreating table twice. Table is anyway recreated
949 // for next version and that takes care of updates for this version as well.
950 // This version added a new column user_edited to carriers db.
951 }
952 if (oldVersion < (15 << 16 | 6)) {
Amit Mahajan899cc602015-05-14 17:22:09 -0700953 // Most devices should be upgrading from version 13. On upgrade new db will be
954 // populated from the xml included in OTA but user and carrier edited/added entries
955 // need to be preserved. This new version also adds new columns EDITED and
956 // BEARER_BITMASK to the table. Upgrade steps from version 13 are:
957 // 1. preserve user and carrier added/edited APNs (by comparing against
958 // old-apns-conf.xml included in OTA) - done in preserveUserAndCarrierApns()
959 // 2. add new columns EDITED and BEARER_BITMASK (create a new table for that) - done
960 // in createCarriersTable()
961 // 3. copy over preserved APNs from old table to new table - done in
962 // copyPreservedApnsToNewTable()
963 // The only exception if upgrading from version 14 is that EDITED field is already
964 // present (but is called USER_EDITED)
Amit Mahajand4091e02015-10-28 12:32:28 -0700965 /*********************************************************************************
966 * IMPORTANT NOTE: SINCE CARRIERS TABLE IS RECREATED HERE, IT WILL BE THE LATEST
967 * VERSION AFTER THIS. AS A RESULT ANY SUBSEQUENT UPDATES TO THE TABLE WILL FAIL
968 * (DUE TO COLUMN-ALREADY-EXISTS KIND OF EXCEPTION). ALL SUBSEQUENT UPDATES SHOULD
969 * HANDLE THAT GRACEFULLY.
970 *********************************************************************************/
Amit Mahajan899cc602015-05-14 17:22:09 -0700971 Cursor c;
972 String[] proj = {"_id"};
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800973 if (VDBG) {
Amit Mahajan899cc602015-05-14 17:22:09 -0700974 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800975 log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount());
976 }
Amit Mahajan899cc602015-05-14 17:22:09 -0700977
978 // Compare db with old apns xml file so that any user or carrier edited/added
979 // entries can be preserved across upgrade
980 preserveUserAndCarrierApns(db);
981
982 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null);
983
984 if (VDBG) {
985 log("dbh.onUpgrade:- after preserveUserAndCarrierApns() total number of " +
986 "rows: " + ((c == null) ? 0 : c.getCount()));
987 }
988
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800989 createCarriersTable(db, CARRIERS_TABLE_TMP);
990
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700991 copyPreservedApnsToNewTable(db, c);
Amit Mahajan899cc602015-05-14 17:22:09 -0700992 c.close();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800993
994 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE);
995
996 db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE +
997 ";");
998
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800999 if (VDBG) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001000 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
1001 log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount());
1002 c.close();
Amit Mahajan28a5d002016-03-02 11:34:28 -08001003 c = db.query(CARRIERS_TABLE, proj, IS_UNEDITED, null, null, null, null);
1004 log("dbh.onUpgrade:- after upgrading total number of rows with " + IS_UNEDITED +
1005 ": " + c.getCount());
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001006 c.close();
Amit Mahajan28a5d002016-03-02 11:34:28 -08001007 c = db.query(CARRIERS_TABLE, proj, IS_EDITED, null, null, null, null);
1008 log("dbh.onUpgrade:- after upgrading total number of rows with " + IS_EDITED +
1009 ": " + c.getCount());
Amit Mahajan899cc602015-05-14 17:22:09 -07001010 c.close();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001011 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07001012
1013 oldVersion = 15 << 16 | 6;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001014 }
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001015 if (oldVersion < (16 << 16 | 6)) {
1016 try {
1017 // Try to update the siminfo table. It might not be there.
1018 // These columns may already be present in which case execSQL will throw an
1019 // exception
1020 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001021 + Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT
1022 + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001023 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001024 + Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT
1025 + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001026 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001027 + Telephony.SimInfo.COLUMN_CB_AMBER_ALERT + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001028 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001029 + Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001030 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001031 + Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION
1032 + " INTEGER DEFAULT 4;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001033 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001034 + Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL
1035 + " INTEGER DEFAULT 0;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001036 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001037 + Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001038 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001039 + Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001040 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001041 + Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001042 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001043 + Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001044 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001045 + Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001046 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001047 + Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001048 } catch (SQLiteException e) {
1049 if (DBG) {
1050 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1051 " The table will get created in onOpen.");
1052 }
1053 }
1054 oldVersion = 16 << 16 | 6;
1055 }
Amit Mahajanda607212015-10-08 09:13:00 -07001056 if (oldVersion < (17 << 16 | 6)) {
Amit Mahajand4091e02015-10-28 12:32:28 -07001057 Cursor c = null;
1058 try {
1059 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null,
1060 String.valueOf(1));
Amit Mahajan28a5d002016-03-02 11:34:28 -08001061 if (c == null || c.getColumnIndex(USER_VISIBLE) == -1) {
Amit Mahajand4091e02015-10-28 12:32:28 -07001062 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
Amit Mahajan28a5d002016-03-02 11:34:28 -08001063 USER_VISIBLE + " BOOLEAN DEFAULT 1;");
Amit Mahajand4091e02015-10-28 12:32:28 -07001064 } else {
1065 if (DBG) {
1066 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. Column " +
Amit Mahajan28a5d002016-03-02 11:34:28 -08001067 USER_VISIBLE + " already exists.");
Amit Mahajand4091e02015-10-28 12:32:28 -07001068 }
1069 }
1070 } finally {
1071 if (c != null) {
1072 c.close();
1073 }
1074 }
Amit Mahajanda607212015-10-08 09:13:00 -07001075 oldVersion = 17 << 16 | 6;
1076 }
fionaxue58c1602016-04-11 01:40:19 -07001077 if (oldVersion < (18 << 16 | 6)) {
1078 try {
1079 // Try to update the siminfo table. It might not be there.
1080 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -08001081 Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS + " INTEGER DEFAULT " +
Peter Wangb097cb62019-12-05 11:01:18 -08001082 Telephony.SimInfo.SIM_PROVISIONED + ";");
fionaxue58c1602016-04-11 01:40:19 -07001083 } catch (SQLiteException e) {
1084 if (DBG) {
1085 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1086 " The table will get created in onOpen.");
1087 }
1088 }
1089 oldVersion = 18 << 16 | 6;
1090 }
pkanware08f3ac2017-02-02 18:26:32 -08001091 if (oldVersion < (19 << 16 | 6)) {
Cassiea58ce712017-12-06 16:21:50 -08001092 // Do nothing. This is to avoid recreating table twice. Table is anyway recreated
1093 // for version 24 and that takes care of updates for this version as well.
1094 // This version added more fields protocol and roaming protocol to the primary key.
pkanware08f3ac2017-02-02 18:26:32 -08001095 }
Jeff Davidsonb114ed22017-04-09 14:55:23 -07001096 if (oldVersion < (20 << 16 | 6)) {
1097 try {
1098 // Try to update the siminfo table. It might not be there.
1099 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -08001100 Telephony.SimInfo.COLUMN_IS_EMBEDDED + " INTEGER DEFAULT 0;");
Jeff Davidsonb114ed22017-04-09 14:55:23 -07001101 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -08001102 Telephony.SimInfo.COLUMN_ACCESS_RULES + " BLOB;");
Jeff Davidsonb114ed22017-04-09 14:55:23 -07001103 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -08001104 Telephony.SimInfo.COLUMN_IS_REMOVABLE + " INTEGER DEFAULT 0;");
Jeff Davidsonb114ed22017-04-09 14:55:23 -07001105 } catch (SQLiteException e) {
1106 if (DBG) {
1107 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
Amit Mahajan460d7032017-07-17 14:42:33 -07001108 "The table will get created in onOpen.");
Jeff Davidsonb114ed22017-04-09 14:55:23 -07001109 }
1110 }
1111 oldVersion = 20 << 16 | 6;
1112 }
Amit Mahajan460d7032017-07-17 14:42:33 -07001113 if (oldVersion < (21 << 16 | 6)) {
1114 try {
yuemingwc4d40a72017-11-08 14:14:37 +00001115 // Try to update the carriers table. It might not be there.
Amit Mahajan460d7032017-07-17 14:42:33 -07001116 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
1117 USER_EDITABLE + " INTEGER DEFAULT 1;");
1118 } catch (SQLiteException e) {
1119 // This is possible if the column already exists which may be the case if the
1120 // table was just created as part of upgrade to version 19
1121 if (DBG) {
1122 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
1123 "The table will get created in onOpen.");
1124 }
1125 }
1126 oldVersion = 21 << 16 | 6;
1127 }
yuemingwc4d40a72017-11-08 14:14:37 +00001128 if (oldVersion < (22 << 16 | 6)) {
1129 try {
Malcolm Chenadb3e382017-10-02 16:07:42 -07001130 // Try to update the siminfo table. It might not be there.
1131 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001132 + Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED
Malcolm Chenadb3e382017-10-02 16:07:42 -07001133 + " INTEGER DEFAULT -1;");
1134 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001135 + Telephony.SimInfo.COLUMN_VT_IMS_ENABLED + " INTEGER DEFAULT -1;");
Malcolm Chenadb3e382017-10-02 16:07:42 -07001136 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001137 + Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED + " INTEGER DEFAULT -1;");
Malcolm Chenadb3e382017-10-02 16:07:42 -07001138 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001139 + Telephony.SimInfo.COLUMN_WFC_IMS_MODE + " INTEGER DEFAULT -1;");
Malcolm Chenadb3e382017-10-02 16:07:42 -07001140 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001141 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1;");
Malcolm Chenadb3e382017-10-02 16:07:42 -07001142 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001143 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1;");
Malcolm Chenadb3e382017-10-02 16:07:42 -07001144 } catch (SQLiteException e) {
1145 if (DBG) {
1146 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
1147 "The table will get created in onOpen.");
1148 }
1149 }
1150 oldVersion = 22 << 16 | 6;
1151 }
1152 if (oldVersion < (23 << 16 | 6)) {
1153 try {
yuemingwc4d40a72017-11-08 14:14:37 +00001154 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
1155 OWNED_BY + " INTEGER DEFAULT " + OWNED_BY_OTHERS + ";");
1156 } catch (SQLiteException e) {
1157 if (DBG) {
1158 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
1159 "The table will get created in onOpen.");
1160 }
1161 }
Malcolm Chenadb3e382017-10-02 16:07:42 -07001162 oldVersion = 23 << 16 | 6;
yuemingwc4d40a72017-11-08 14:14:37 +00001163 }
Cassiea58ce712017-12-06 16:21:50 -08001164 if (oldVersion < (24 << 16 | 6)) {
1165 Cursor c = null;
1166 String[] proj = {"_id"};
calvinpan2b419442018-10-23 15:05:11 +08001167 recreateDB(db, proj, /* version */24);
Cassiea58ce712017-12-06 16:21:50 -08001168 if (VDBG) {
1169 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
1170 log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount());
1171 c.close();
yinxu3d98b6c2018-01-05 16:27:30 -08001172 c = db.query(
1173 CARRIERS_TABLE, proj, NETWORK_TYPE_BITMASK, null, null, null, null);
Cassiea58ce712017-12-06 16:21:50 -08001174 log("dbh.onUpgrade:- after upgrading total number of rows with "
1175 + NETWORK_TYPE_BITMASK + ": " + c.getCount());
1176 c.close();
1177 }
1178 oldVersion = 24 << 16 | 6;
1179 }
yinxu3d98b6c2018-01-05 16:27:30 -08001180 if (oldVersion < (25 << 16 | 6)) {
1181 // Add a new column SubscriptionManager.CARD_ID into the database and set the value
1182 // to be the same as the existing column SubscriptionManager.ICC_ID. In order to do
1183 // this, we need to first make a copy of the existing SIMINFO_TABLE, set the value
1184 // of the new column SubscriptionManager.CARD_ID, and replace the SIMINFO_TABLE with
1185 // the new table.
1186 Cursor c = null;
Peter Wangb8e281d2020-01-31 18:50:00 -08001187 String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID};
yinxu3d98b6c2018-01-05 16:27:30 -08001188 recreateSimInfoDB(c, db, proj);
1189 if (VDBG) {
1190 c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null);
1191 log("dbh.onUpgrade:- after upgrading " + SIMINFO_TABLE
1192 + " total number of rows: " + c.getCount());
1193 c.close();
Peter Wangb8e281d2020-01-31 18:50:00 -08001194 c = db.query(SIMINFO_TABLE, proj, Telephony.SimInfo.COLUMN_CARD_ID
1195 + " IS NOT NULL", null, null, null, null);
yinxu3d98b6c2018-01-05 16:27:30 -08001196 log("dbh.onUpgrade:- after upgrading total number of rows with "
Peter Wangb8e281d2020-01-31 18:50:00 -08001197 + Telephony.SimInfo.COLUMN_CARD_ID + ": " + c.getCount());
yinxu3d98b6c2018-01-05 16:27:30 -08001198 c.close();
1199 }
1200 oldVersion = 25 << 16 | 6;
1201 }
Jordan Liu92da8c82018-04-10 16:00:06 -07001202 if (oldVersion < (26 << 16 | 6)) {
1203 // Add a new column Carriers.APN_SET_ID into the database and set the value to
1204 // Carriers.NO_SET_SET by default.
1205 try {
1206 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
chen xu3e303942018-11-28 00:23:01 -08001207 APN_SET_ID + " INTEGER DEFAULT " + NO_APN_SET_ID + ";");
Jordan Liu92da8c82018-04-10 16:00:06 -07001208 } catch (SQLiteException e) {
1209 if (DBG) {
1210 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
1211 "The table will get created in onOpen.");
1212 }
1213 }
1214 oldVersion = 26 << 16 | 6;
1215 }
Hall Liu5479f4d2018-07-14 00:31:13 +00001216
1217 if (oldVersion < (27 << 16 | 6)) {
1218 // Add the new MCC_STRING and MNC_STRING columns into the subscription table,
1219 // and attempt to populate them.
1220 try {
1221 // Try to update the siminfo table. It might not be there.
1222 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
Peter Wangb8e281d2020-01-31 18:50:00 -08001223 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MCC_STRING + " TEXT;");
Hall Liu5479f4d2018-07-14 00:31:13 +00001224 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
Peter Wangb8e281d2020-01-31 18:50:00 -08001225 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MNC_STRING + " TEXT;");
Hall Liu5479f4d2018-07-14 00:31:13 +00001226 } catch (SQLiteException e) {
1227 if (DBG) {
1228 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1229 " The table will get created in onOpen.");
1230 }
1231 }
1232 // Migrate the old integer values over to strings
Peter Wangb8e281d2020-01-31 18:50:00 -08001233 String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID,
1234 Telephony.SimInfo.COLUMN_MCC, Telephony.SimInfo.COLUMN_MNC};
Hall Liu5479f4d2018-07-14 00:31:13 +00001235 try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) {
1236 while (c.moveToNext()) {
1237 fillInMccMncStringAtCursor(mContext, db, c);
1238 }
1239 }
1240 oldVersion = 27 << 16 | 6;
1241 }
Malcolm Chen26b84122018-08-07 15:25:14 -07001242
1243 if (oldVersion < (28 << 16 | 6)) {
1244 try {
1245 // Try to update the siminfo table. It might not be there.
1246 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001247 + Telephony.SimInfo.COLUMN_IS_OPPORTUNISTIC + " INTEGER DEFAULT 0;");
Malcolm Chen26b84122018-08-07 15:25:14 -07001248 } catch (SQLiteException e) {
1249 if (DBG) {
1250 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1251 "The table will get created in onOpen.");
1252 }
1253 }
1254 oldVersion = 28 << 16 | 6;
1255 }
calvinpan2b419442018-10-23 15:05:11 +08001256
1257 if (oldVersion < (29 << 16 | 6)) {
1258 try {
1259 // Add a new column Telephony.CARRIER_ID into the database and add UNIQUE
1260 // constraint into table. However, sqlite cannot add constraints to an existing
1261 // table, so recreate the table.
1262 String[] proj = {"_id"};
1263 recreateDB(db, proj, /* version */29);
1264 } catch (SQLiteException e) {
1265 if (DBG) {
1266 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
1267 "The table will get created in onOpen.");
1268 }
1269 }
1270 oldVersion = 29 << 16 | 6;
1271 }
Malcolm Chenc5630dd2018-10-31 20:19:33 -07001272
1273 if (oldVersion < (30 << 16 | 6)) {
1274 try {
Malcolm Chenc5630dd2018-10-31 20:19:33 -07001275 // Try to update the siminfo table. It might not be there.
1276 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001277 + Telephony.SimInfo.COLUMN_GROUP_UUID + " TEXT;");
Nazanin Bakhshi77e0f792018-11-26 13:32:48 -08001278 } catch (SQLiteException e) {
1279 if (DBG) {
1280 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1281 "The table will get created in onOpen.");
1282 }
1283 }
1284 oldVersion = 30 << 16 | 6;
1285 }
Grace Chen04fc1b22018-12-21 18:19:43 -08001286
Nazanin Bakhshi77e0f792018-11-26 13:32:48 -08001287 if (oldVersion < (31 << 16 | 6)) {
1288 try {
1289 // Try to update the siminfo table. It might not be there.
1290 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001291 + Telephony.SimInfo.COLUMN_IS_METERED + " INTEGER DEFAULT 1;");
Malcolm Chenc5630dd2018-10-31 20:19:33 -07001292 } catch (SQLiteException e) {
1293 if (DBG) {
1294 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1295 "The table will get created in onOpen.");
1296 }
1297 }
Nazanin Bakhshi77e0f792018-11-26 13:32:48 -08001298 oldVersion = 31 << 16 | 6;
Malcolm Chenc5630dd2018-10-31 20:19:33 -07001299 }
Nazanin Bakhshi77e0f792018-11-26 13:32:48 -08001300
chen xu3d1f5a82018-12-02 17:06:39 -08001301 if (oldVersion < (32 << 16 | 6)) {
1302 try {
1303 // Try to update the siminfo table. It might not be there.
1304 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001305 + Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE + " TEXT;");
chen xu3d1f5a82018-12-02 17:06:39 -08001306 } catch (SQLiteException e) {
1307 if (DBG) {
1308 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1309 "The table will get created in onOpen.");
1310 }
1311 }
1312 oldVersion = 32 << 16 | 6;
1313 }
1314
chen xu63dd9902018-12-14 00:11:50 -08001315 if (oldVersion < (33 << 16 | 6)) {
1316 try {
1317 // Try to update the siminfo table. It might not be there.
1318 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001319 + Telephony.SimInfo.COLUMN_CARRIER_ID + " INTEGER DEFAULT -1;");
chen xu63dd9902018-12-14 00:11:50 -08001320 } catch (SQLiteException e) {
1321 if (DBG) {
1322 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1323 "The table will get created in onOpen.");
1324 }
1325 }
1326 oldVersion = 33 << 16 | 6;
1327 }
1328
Grace Chen04fc1b22018-12-21 18:19:43 -08001329 if (oldVersion < (34 << 16 | 6)) {
1330 try {
1331 // Try to update the siminfo table. It might not be there.
1332 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -08001333 Telephony.SimInfo.COLUMN_PROFILE_CLASS + " INTEGER DEFAULT " +
1334 Telephony.SimInfo.PROFILE_CLASS_UNSET + ";");
Grace Chen04fc1b22018-12-21 18:19:43 -08001335 } catch (SQLiteException e) {
1336 if (DBG) {
1337 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1338 "The table will get created in onOpen.");
1339 }
1340 }
1341 oldVersion = 34 << 16 | 6;
1342 }
1343
Vasu Nori815b42f2018-09-25 10:07:14 -07001344 if (oldVersion < (35 << 16 | 6)) {
1345 try {
1346 // Try to update the siminfo table. It might not be there.
1347 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001348 + Telephony.SimInfo.COLUMN_SUBSCRIPTION_TYPE + " INTEGER DEFAULT "
Peter Wangb097cb62019-12-05 11:01:18 -08001349 + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ";");
Vasu Nori815b42f2018-09-25 10:07:14 -07001350 } catch (SQLiteException e) {
1351 if (DBG) {
1352 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1353 "The table will get created in onOpen.");
1354 }
1355 }
Scott Randolphdb811032019-02-21 18:11:24 -08001356 oldVersion = 35 << 16 | 6;
Vasu Nori815b42f2018-09-25 10:07:14 -07001357 }
1358
Yuuki Habu95aacb12019-02-22 10:49:06 +09001359 if (oldVersion < (36 << 16 | 6)) {
1360 // Add a new column Carriers.SKIP_464XLAT into the database and set the value to
1361 // SKIP_464XLAT_DEFAULT.
1362 try {
1363 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
1364 SKIP_464XLAT + " INTEGER DEFAULT " + SKIP_464XLAT_DEFAULT + ";");
1365 } catch (SQLiteException e) {
1366 if (DBG) {
1367 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
1368 "The table will get created in onOpen.");
1369 }
1370 }
1371 oldVersion = 36 << 16 | 6;
1372 }
1373
Hall Liuafbe11c2019-04-11 15:29:47 -07001374 if (oldVersion < (37 << 16 | 6)) {
Peter Wangb097cb62019-12-05 11:01:18 -08001375 // Add new columns Telephony.SimInfo.EHPLMNS and Telephony.SimInfo.HPLMNS into
Hall Liuafbe11c2019-04-11 15:29:47 -07001376 // the database.
1377 try {
1378 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
Peter Wangb8e281d2020-01-31 18:50:00 -08001379 " ADD COLUMN " + Telephony.SimInfo.COLUMN_EHPLMNS + " TEXT;");
Hall Liuafbe11c2019-04-11 15:29:47 -07001380 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
Peter Wangb8e281d2020-01-31 18:50:00 -08001381 " ADD COLUMN " + Telephony.SimInfo.COLUMN_HPLMNS + " TEXT;");
Hall Liuafbe11c2019-04-11 15:29:47 -07001382 } catch (SQLiteException e) {
1383 if (DBG) {
1384 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade for ehplmns. " +
1385 "The table will get created in onOpen.");
1386 }
1387 }
1388 oldVersion = 37 << 16 | 6;
1389 }
1390
Malcolm Chen7000a1a2019-03-31 13:29:10 -07001391 if (oldVersion < (39 << 16 | 6)) {
1392 try {
1393 // Try to update the siminfo table. It might not be there.
1394 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001395 + Telephony.SimInfo.COLUMN_GROUP_OWNER + " TEXT;");
Malcolm Chen7000a1a2019-03-31 13:29:10 -07001396 } catch (SQLiteException e) {
1397 if (DBG) {
1398 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1399 "The table will get created in onOpen.");
1400 }
1401 }
1402 oldVersion = 39 << 16 | 6;
1403 }
1404
Jack Yue9e9cb32019-05-23 16:37:52 -07001405 if (oldVersion < (40 << 16 | 6)) {
1406 try {
1407 // Try to update the siminfo table. It might not be there.
1408 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001409 + Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES + " TEXT;");
Jack Yue9e9cb32019-05-23 16:37:52 -07001410 } catch (SQLiteException e) {
1411 if (DBG) {
1412 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1413 "The table will get created in onOpen.");
1414 }
1415 }
1416 oldVersion = 40 << 16 | 6;
1417 }
1418
Nazanin Bakhshicf1ea8f2019-05-31 16:29:08 -07001419 if (oldVersion < (41 << 16 | 6)) {
1420 try {
1421 // Try to update the siminfo table. It might not be there.
1422 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001423 + Telephony.SimInfo.COLUMN_IMSI + " TEXT;");
Nazanin Bakhshicf1ea8f2019-05-31 16:29:08 -07001424 } catch (SQLiteException e) {
1425 if (DBG) {
1426 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1427 "The table will get created in onOpen.");
1428 }
1429 }
1430 oldVersion = 41 << 16 | 6;
1431 }
1432
Nazanin Bakhshida72e982019-08-13 12:38:22 -07001433 if (oldVersion < (42 << 16 | 6)) {
1434 try {
1435 // Try to update the siminfo table. It might not be there.
1436 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
Peter Wangb8e281d2020-01-31 18:50:00 -08001437 Telephony.SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB;");
Nazanin Bakhshida72e982019-08-13 12:38:22 -07001438 } catch (SQLiteException e) {
1439 if (DBG) {
1440 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1441 "The table will get created in onOpen.");
1442 }
1443 }
1444 }
1445
Malcolm Chen7c602282019-12-04 18:38:17 -08001446 if (oldVersion < (43 << 16 | 6)) {
1447 try {
1448 // Try to update the siminfo table. It might not be there.
1449 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001450 + Telephony.SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED
Malcolm Chen7c602282019-12-04 18:38:17 -08001451 + " INTEGER DEFAULT 1;");
1452 } catch (SQLiteException e) {
1453 if (DBG) {
1454 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1455 "The table will get created in onOpen.");
1456 }
1457 }
1458 oldVersion = 43 << 16 | 6;
1459 }
1460
calvinpan846d9642020-01-14 14:48:29 +08001461 if (oldVersion < (44 << 16 | 6)) {
1462 try {
1463 // Try to update the siminfo table. It might not be there.
1464 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001465 + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES
calvinpan846d9642020-01-14 14:48:29 +08001466 + " BIGINT DEFAULT -1;");
1467 } catch (SQLiteException e) {
1468 if (DBG) {
1469 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1470 "The table will get created in onOpen.");
1471 }
1472 }
1473 oldVersion = 44 << 16 | 6;
1474 }
Nazanin Bakhshicf1ea8f2019-05-31 16:29:08 -07001475
Brad Ebinger748c7622020-01-22 16:12:04 -08001476 if (oldVersion < (45 << 16 | 6)) {
1477 try {
1478 // Try to update the siminfo table. It might not be there.
1479 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Peter Wangb8e281d2020-01-31 18:50:00 -08001480 + Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED
Brad Ebinger748c7622020-01-22 16:12:04 -08001481 + " INTEGER DEFAULT 0;");
1482 } catch (SQLiteException e) {
1483 if (DBG) {
1484 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
1485 "The table will get created in onOpen.");
1486 }
1487 }
1488 oldVersion = 45 << 16 | 6;
1489 }
1490
Wink Saville6de10272014-06-22 07:38:43 -07001491 if (DBG) {
1492 log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
1493 }
Jordan Liuc591b112018-05-02 16:35:03 -07001494 // when adding fields to onUpgrade, also add a unit test to TelephonyDatabaseHelperTest
calvinpan2b419442018-10-23 15:05:11 +08001495 // and update the DATABASE_VERSION field and add a column in copyAllApnValues
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001496 }
1497
yinxu3d98b6c2018-01-05 16:27:30 -08001498 private void recreateSimInfoDB(Cursor c, SQLiteDatabase db, String[] proj) {
1499 if (VDBG) {
1500 c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null);
1501 log("dbh.onUpgrade:+ before upgrading " + SIMINFO_TABLE +
1502 " total number of rows: " + c.getCount());
1503 c.close();
1504 }
1505
Brad Ebinger1c69fea2018-03-27 11:33:16 -07001506 // Sort in ascending order by subscription id to make sure the rows do not get flipped
1507 // during the query and added in the new sim info table in another order (sub id is
1508 // stored in settings between migrations).
1509 c = db.query(SIMINFO_TABLE, null, null, null, null, null, ORDER_BY_SUB_ID);
yinxu3d98b6c2018-01-05 16:27:30 -08001510
1511 db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE_TMP);
1512
1513 createSimInfoTable(db, SIMINFO_TABLE_TMP);
1514
1515 copySimInfoDataToTmpTable(db, c);
1516 c.close();
1517
1518 db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE);
1519
1520 db.execSQL("ALTER TABLE " + SIMINFO_TABLE_TMP + " rename to " + SIMINFO_TABLE + ";");
1521
1522 }
1523
1524 private void copySimInfoDataToTmpTable(SQLiteDatabase db, Cursor c) {
1525 // Move entries from SIMINFO_TABLE to SIMINFO_TABLE_TMP
1526 if (c != null) {
1527 while (c.moveToNext()) {
1528 ContentValues cv = new ContentValues();
1529 copySimInfoValuesV24(cv, c);
1530 // The card ID is supposed to be the ICCID of the profile for UICC card, and
1531 // the EID of the card for eUICC card. Since EID is unknown for old entries in
1532 // SIMINFO_TABLE, we use ICCID as the card ID for all the old entries while
1533 // upgrading the SIMINFO_TABLE. In UiccController, both the card ID and ICCID
1534 // will be checked when user queries the slot information using the card ID
1535 // from the database.
1536 getCardIdfromIccid(cv, c);
1537 try {
1538 db.insert(SIMINFO_TABLE_TMP, null, cv);
1539 if (VDBG) {
1540 log("dbh.copySimInfoDataToTmpTable: db.insert returned >= 0; " +
1541 "insert successful for cv " + cv);
1542 }
1543 } catch (SQLException e) {
1544 if (VDBG)
1545 log("dbh.copySimInfoDataToTmpTable insertWithOnConflict exception " +
1546 e + " for cv " + cv);
1547 }
1548 }
1549 }
1550 }
1551
1552 private void copySimInfoValuesV24(ContentValues cv, Cursor c) {
1553 // String vals
Peter Wangb8e281d2020-01-31 18:50:00 -08001554 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ICC_ID);
1555 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DISPLAY_NAME);
1556 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CARRIER_NAME);
1557 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_NUMBER);
yinxu3d98b6c2018-01-05 16:27:30 -08001558
1559 // bool/int vals
Peter Wangb8e281d2020-01-31 18:50:00 -08001560 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX);
1561 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_NAME_SOURCE);
1562 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_COLOR);
1563 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT);
1564 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DATA_ROAMING);
1565 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_MCC);
1566 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_MNC);
1567 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS);
1568 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_IS_EMBEDDED);
1569 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_IS_REMOVABLE);
1570 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT);
1571 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT);
1572 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_AMBER_ALERT);
1573 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT);
1574 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION);
1575 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL);
1576 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE);
1577 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH);
1578 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT);
1579 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT);
1580 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT);
1581 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG);
1582 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED);
1583 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_VT_IMS_ENABLED);
1584 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED);
1585 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_MODE);
1586 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE);
1587 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED);
yinxu3d98b6c2018-01-05 16:27:30 -08001588
1589 // Blob vals
Peter Wangb8e281d2020-01-31 18:50:00 -08001590 getBlobValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ACCESS_RULES);
yinxu3d98b6c2018-01-05 16:27:30 -08001591 }
1592
1593 private void getCardIdfromIccid(ContentValues cv, Cursor c) {
Peter Wangb8e281d2020-01-31 18:50:00 -08001594 int columnIndex = c.getColumnIndex(Telephony.SimInfo.COLUMN_ICC_ID);
yinxu3d98b6c2018-01-05 16:27:30 -08001595 if (columnIndex != -1) {
1596 String fromCursor = c.getString(columnIndex);
1597 if (!TextUtils.isEmpty(fromCursor)) {
Peter Wangb8e281d2020-01-31 18:50:00 -08001598 cv.put(Telephony.SimInfo.COLUMN_CARD_ID, fromCursor);
yinxu3d98b6c2018-01-05 16:27:30 -08001599 }
1600 }
1601 }
1602
calvinpan2b419442018-10-23 15:05:11 +08001603 private void recreateDB(SQLiteDatabase db, String[] proj, int version) {
Cassiea58ce712017-12-06 16:21:50 -08001604 // Upgrade steps are:
1605 // 1. Create a temp table- done in createCarriersTable()
1606 // 2. copy over APNs from old table to new table - done in copyDataToTmpTable()
1607 // 3. Drop the existing table.
1608 // 4. Copy over the tmp table.
calvinpan2b419442018-10-23 15:05:11 +08001609 Cursor c;
Cassiea58ce712017-12-06 16:21:50 -08001610 if (VDBG) {
1611 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
1612 log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount());
1613 c.close();
1614 }
1615
1616 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null);
1617
1618 if (VDBG) {
1619 log("dbh.onUpgrade:- starting data copy of existing rows: " +
1620 + ((c == null) ? 0 : c.getCount()));
1621 }
1622
1623 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE_TMP);
1624
1625 createCarriersTable(db, CARRIERS_TABLE_TMP);
1626
calvinpan2b419442018-10-23 15:05:11 +08001627 copyDataToTmpTable(db, c, version);
Cassiea58ce712017-12-06 16:21:50 -08001628 c.close();
1629
1630 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE);
1631
1632 db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE + ";");
1633 }
1634
Amit Mahajan899cc602015-05-14 17:22:09 -07001635 private void preserveUserAndCarrierApns(SQLiteDatabase db) {
1636 if (VDBG) log("preserveUserAndCarrierApns");
1637 XmlPullParser confparser;
1638 File confFile = new File(Environment.getRootDirectory(), OLD_APNS_PATH);
1639 FileReader confreader = null;
1640 try {
1641 confreader = new FileReader(confFile);
1642 confparser = Xml.newPullParser();
1643 confparser.setInput(confreader);
1644 XmlUtils.beginDocument(confparser, "apns");
1645
1646 deleteMatchingApns(db, confparser);
1647 } catch (FileNotFoundException e) {
1648 // This function is called only when upgrading db to version 15. Details about the
1649 // upgrade are mentioned in onUpgrade(). This file missing means user/carrier added
Amit Mahajan5cc51a52015-10-23 17:32:32 -07001650 // APNs cannot be preserved. Log an error message so that OEMs know they need to
Amit Mahajan899cc602015-05-14 17:22:09 -07001651 // include old apns file for comparison.
Amit Mahajan5cc51a52015-10-23 17:32:32 -07001652 loge("PRESERVEUSERANDCARRIERAPNS: " + OLD_APNS_PATH +
1653 " NOT FOUND. IT IS NEEDED TO UPGRADE FROM OLDER VERSIONS OF APN " +
1654 "DB WHILE PRESERVING USER/CARRIER ADDED/EDITED ENTRIES.");
Amit Mahajan899cc602015-05-14 17:22:09 -07001655 } catch (Exception e) {
1656 loge("preserveUserAndCarrierApns: Exception while parsing '" +
1657 confFile.getAbsolutePath() + "'" + e);
1658 } finally {
1659 if (confreader != null) {
1660 try {
1661 confreader.close();
1662 } catch (IOException e) {
1663 // do nothing
1664 }
1665 }
1666 }
1667 }
1668
1669 private void deleteMatchingApns(SQLiteDatabase db, XmlPullParser parser) {
1670 if (VDBG) log("deleteMatchingApns");
1671 if (parser != null) {
1672 if (VDBG) log("deleteMatchingApns: parser != null");
1673 try {
1674 XmlUtils.nextElement(parser);
1675 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
1676 ContentValues row = getRow(parser);
1677 if (row == null) {
1678 throw new XmlPullParserException("Expected 'apn' tag", parser, null);
1679 }
1680 deleteRow(db, row);
1681 XmlUtils.nextElement(parser);
1682 }
1683 } catch (XmlPullParserException e) {
1684 loge("deleteMatchingApns: Got XmlPullParserException while deleting apns." + e);
1685 } catch (IOException e) {
1686 loge("deleteMatchingApns: Got IOException while deleting apns." + e);
1687 } catch (SQLException e) {
1688 loge("deleteMatchingApns: Got SQLException while deleting apns." + e);
1689 }
1690 }
1691 }
1692
Amit Mahajan28a5d002016-03-02 11:34:28 -08001693 private String queryValFirst(String field) {
1694 return field + "=?";
1695 }
1696
1697 private String queryVal(String field) {
1698 return " and " + field + "=?";
1699 }
1700
1701 private String queryValOrNull(String field) {
1702 return " and (" + field + "=? or " + field + " is null)";
1703 }
1704
1705 private String queryVal2OrNull(String field) {
1706 return " and (" + field + "=? or " + field + "=? or " + field + " is null)";
1707 }
1708
Amit Mahajan899cc602015-05-14 17:22:09 -07001709 private void deleteRow(SQLiteDatabase db, ContentValues values) {
1710 if (VDBG) log("deleteRow");
Amit Mahajan28a5d002016-03-02 11:34:28 -08001711 String where = queryValFirst(NUMERIC) +
1712 queryVal(MNC) +
1713 queryVal(MNC) +
1714 queryValOrNull(APN) +
1715 queryValOrNull(USER) +
1716 queryValOrNull(SERVER) +
1717 queryValOrNull(PASSWORD) +
1718 queryValOrNull(PROXY) +
1719 queryValOrNull(PORT) +
1720 queryValOrNull(MMSPROXY) +
1721 queryValOrNull(MMSPORT) +
1722 queryValOrNull(MMSC) +
1723 queryValOrNull(AUTH_TYPE) +
1724 queryValOrNull(TYPE) +
1725 queryValOrNull(PROTOCOL) +
1726 queryValOrNull(ROAMING_PROTOCOL) +
1727 queryVal2OrNull(CARRIER_ENABLED) +
1728 queryValOrNull(BEARER) +
1729 queryValOrNull(MVNO_TYPE) +
1730 queryValOrNull(MVNO_MATCH_DATA) +
1731 queryValOrNull(PROFILE_ID) +
chen xu3e303942018-11-28 00:23:01 -08001732 queryVal2OrNull(MODEM_PERSIST) +
1733 queryValOrNull(MAX_CONNECTIONS) +
1734 queryValOrNull(WAIT_TIME_RETRY) +
1735 queryValOrNull(TIME_LIMIT_FOR_MAX_CONNECTIONS) +
Amit Mahajan28a5d002016-03-02 11:34:28 -08001736 queryValOrNull(MTU);
Amit Mahajan899cc602015-05-14 17:22:09 -07001737 String[] whereArgs = new String[29];
1738 int i = 0;
Amit Mahajan28a5d002016-03-02 11:34:28 -08001739 whereArgs[i++] = values.getAsString(NUMERIC);
1740 whereArgs[i++] = values.getAsString(MCC);
1741 whereArgs[i++] = values.getAsString(MNC);
1742 whereArgs[i++] = values.getAsString(NAME);
1743 whereArgs[i++] = values.containsKey(APN) ?
1744 values.getAsString(APN) : "";
1745 whereArgs[i++] = values.containsKey(USER) ?
1746 values.getAsString(USER) : "";
1747 whereArgs[i++] = values.containsKey(SERVER) ?
1748 values.getAsString(SERVER) : "";
1749 whereArgs[i++] = values.containsKey(PASSWORD) ?
1750 values.getAsString(PASSWORD) : "";
1751 whereArgs[i++] = values.containsKey(PROXY) ?
1752 values.getAsString(PROXY) : "";
1753 whereArgs[i++] = values.containsKey(PORT) ?
1754 values.getAsString(PORT) : "";
1755 whereArgs[i++] = values.containsKey(MMSPROXY) ?
1756 values.getAsString(MMSPROXY) : "";
1757 whereArgs[i++] = values.containsKey(MMSPORT) ?
1758 values.getAsString(MMSPORT) : "";
1759 whereArgs[i++] = values.containsKey(MMSC) ?
1760 values.getAsString(MMSC) : "";
1761 whereArgs[i++] = values.containsKey(AUTH_TYPE) ?
1762 values.getAsString(AUTH_TYPE) : "-1";
1763 whereArgs[i++] = values.containsKey(TYPE) ?
1764 values.getAsString(TYPE) : "";
1765 whereArgs[i++] = values.containsKey(PROTOCOL) ?
yuemingwe0101b82017-12-13 21:49:09 +00001766 values.getAsString(PROTOCOL) : DEFAULT_PROTOCOL;
Amit Mahajan28a5d002016-03-02 11:34:28 -08001767 whereArgs[i++] = values.containsKey(ROAMING_PROTOCOL) ?
yuemingwe0101b82017-12-13 21:49:09 +00001768 values.getAsString(ROAMING_PROTOCOL) : DEFAULT_ROAMING_PROTOCOL;
Amit Mahajan899cc602015-05-14 17:22:09 -07001769
Jordan Liu8b78f712018-05-21 11:10:48 -07001770 if (values.containsKey(CARRIER_ENABLED)) {
1771 whereArgs[i++] = convertStringToBoolString(values.getAsString(CARRIER_ENABLED));
1772 whereArgs[i++] = convertStringToIntString(values.getAsString(CARRIER_ENABLED));
Amit Mahajan899cc602015-05-14 17:22:09 -07001773 } else {
Jordan Liu8b78f712018-05-21 11:10:48 -07001774 String defaultIntString = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(CARRIER_ENABLED);
1775 whereArgs[i++] = convertStringToBoolString(defaultIntString);
1776 whereArgs[i++] = defaultIntString;
Amit Mahajan899cc602015-05-14 17:22:09 -07001777 }
1778
Amit Mahajan28a5d002016-03-02 11:34:28 -08001779 whereArgs[i++] = values.containsKey(BEARER) ?
1780 values.getAsString(BEARER) : "0";
1781 whereArgs[i++] = values.containsKey(MVNO_TYPE) ?
1782 values.getAsString(MVNO_TYPE) : "";
1783 whereArgs[i++] = values.containsKey(MVNO_MATCH_DATA) ?
1784 values.getAsString(MVNO_MATCH_DATA) : "";
1785 whereArgs[i++] = values.containsKey(PROFILE_ID) ?
1786 values.getAsString(PROFILE_ID) : "0";
Amit Mahajan899cc602015-05-14 17:22:09 -07001787
chen xu3e303942018-11-28 00:23:01 -08001788 if (values.containsKey(MODEM_PERSIST) &&
1789 (values.getAsString(MODEM_PERSIST).
Amit Mahajan899cc602015-05-14 17:22:09 -07001790 equalsIgnoreCase("true") ||
chen xu3e303942018-11-28 00:23:01 -08001791 values.getAsString(MODEM_PERSIST).equals("1"))) {
Amit Mahajan899cc602015-05-14 17:22:09 -07001792 whereArgs[i++] = "true";
1793 whereArgs[i++] = "1";
1794 } else {
1795 whereArgs[i++] = "false";
1796 whereArgs[i++] = "0";
1797 }
1798
chen xu3e303942018-11-28 00:23:01 -08001799 whereArgs[i++] = values.containsKey(MAX_CONNECTIONS) ?
1800 values.getAsString(MAX_CONNECTIONS) : "0";
1801 whereArgs[i++] = values.containsKey(WAIT_TIME_RETRY) ?
1802 values.getAsString(WAIT_TIME_RETRY) : "0";
1803 whereArgs[i++] = values.containsKey(TIME_LIMIT_FOR_MAX_CONNECTIONS) ?
1804 values.getAsString(TIME_LIMIT_FOR_MAX_CONNECTIONS) : "0";
Amit Mahajan28a5d002016-03-02 11:34:28 -08001805 whereArgs[i++] = values.containsKey(MTU) ?
1806 values.getAsString(MTU) : "0";
Amit Mahajan899cc602015-05-14 17:22:09 -07001807
1808 if (VDBG) {
1809 log("deleteRow: where: " + where);
1810
1811 StringBuilder builder = new StringBuilder();
1812 for (String s : whereArgs) {
1813 builder.append(s + ", ");
1814 }
1815
1816 log("deleteRow: whereArgs: " + builder.toString());
1817 }
1818 db.delete(CARRIERS_TABLE, where, whereArgs);
1819 }
1820
calvinpan2b419442018-10-23 15:05:11 +08001821 private void copyDataToTmpTable(SQLiteDatabase db, Cursor c, int version) {
pkanware08f3ac2017-02-02 18:26:32 -08001822 // Move entries from CARRIERS_TABLE to CARRIERS_TABLE_TMP
1823 if (c != null) {
1824 while (c.moveToNext()) {
1825 ContentValues cv = new ContentValues();
calvinpan2b419442018-10-23 15:05:11 +08001826 copyAllApnValues(cv, c);
1827 if (version == 24) {
1828 // Sync bearer bitmask and network type bitmask
1829 getNetworkTypeBitmaskFromCursor(cv, c);
1830 }
pkanware08f3ac2017-02-02 18:26:32 -08001831 try {
1832 db.insertWithOnConflict(CARRIERS_TABLE_TMP, null, cv,
1833 SQLiteDatabase.CONFLICT_ABORT);
1834 if (VDBG) {
1835 log("dbh.copyPreservedApnsToNewTable: db.insert returned >= 0; " +
1836 "insert successful for cv " + cv);
1837 }
1838 } catch (SQLException e) {
1839 if (VDBG)
1840 log("dbh.copyPreservedApnsToNewTable insertWithOnConflict exception " +
1841 e + " for cv " + cv);
1842 }
1843 }
1844 }
1845 }
1846
Amit Mahajan47688232017-04-09 16:08:19 -07001847 private void copyApnValuesV17(ContentValues cv, Cursor c) {
pkanware08f3ac2017-02-02 18:26:32 -08001848 // Include only non-null values in cv so that null values can be replaced
1849 // with default if there's a default value for the field
1850
1851 // String vals
1852 getStringValueFromCursor(cv, c, NAME);
1853 getStringValueFromCursor(cv, c, NUMERIC);
1854 getStringValueFromCursor(cv, c, MCC);
1855 getStringValueFromCursor(cv, c, MNC);
1856 getStringValueFromCursor(cv, c, APN);
1857 getStringValueFromCursor(cv, c, USER);
1858 getStringValueFromCursor(cv, c, SERVER);
1859 getStringValueFromCursor(cv, c, PASSWORD);
1860 getStringValueFromCursor(cv, c, PROXY);
1861 getStringValueFromCursor(cv, c, PORT);
1862 getStringValueFromCursor(cv, c, MMSPROXY);
1863 getStringValueFromCursor(cv, c, MMSPORT);
1864 getStringValueFromCursor(cv, c, MMSC);
1865 getStringValueFromCursor(cv, c, TYPE);
1866 getStringValueFromCursor(cv, c, PROTOCOL);
1867 getStringValueFromCursor(cv, c, ROAMING_PROTOCOL);
1868 getStringValueFromCursor(cv, c, MVNO_TYPE);
1869 getStringValueFromCursor(cv, c, MVNO_MATCH_DATA);
1870
1871 // bool/int vals
1872 getIntValueFromCursor(cv, c, AUTH_TYPE);
1873 getIntValueFromCursor(cv, c, CURRENT);
1874 getIntValueFromCursor(cv, c, CARRIER_ENABLED);
1875 getIntValueFromCursor(cv, c, BEARER);
1876 getIntValueFromCursor(cv, c, SUBSCRIPTION_ID);
1877 getIntValueFromCursor(cv, c, PROFILE_ID);
chen xu3e303942018-11-28 00:23:01 -08001878 getIntValueFromCursor(cv, c, MODEM_PERSIST);
1879 getIntValueFromCursor(cv, c, MAX_CONNECTIONS);
1880 getIntValueFromCursor(cv, c, WAIT_TIME_RETRY);
1881 getIntValueFromCursor(cv, c, TIME_LIMIT_FOR_MAX_CONNECTIONS);
pkanware08f3ac2017-02-02 18:26:32 -08001882 getIntValueFromCursor(cv, c, MTU);
1883 getIntValueFromCursor(cv, c, BEARER_BITMASK);
chen xu3e303942018-11-28 00:23:01 -08001884 getIntValueFromCursor(cv, c, EDITED_STATUS);
Amit Mahajan47688232017-04-09 16:08:19 -07001885 getIntValueFromCursor(cv, c, USER_VISIBLE);
pkanware08f3ac2017-02-02 18:26:32 -08001886 }
1887
calvinpan2b419442018-10-23 15:05:11 +08001888 private void copyAllApnValues(ContentValues cv, Cursor c) {
1889 // String vals
1890 getStringValueFromCursor(cv, c, NAME);
1891 getStringValueFromCursor(cv, c, NUMERIC);
1892 getStringValueFromCursor(cv, c, MCC);
1893 getStringValueFromCursor(cv, c, MNC);
1894 getStringValueFromCursor(cv, c, APN);
1895 getStringValueFromCursor(cv, c, USER);
1896 getStringValueFromCursor(cv, c, SERVER);
1897 getStringValueFromCursor(cv, c, PASSWORD);
1898 getStringValueFromCursor(cv, c, PROXY);
1899 getStringValueFromCursor(cv, c, PORT);
1900 getStringValueFromCursor(cv, c, MMSPROXY);
1901 getStringValueFromCursor(cv, c, MMSPORT);
1902 getStringValueFromCursor(cv, c, MMSC);
1903 getStringValueFromCursor(cv, c, TYPE);
1904 getStringValueFromCursor(cv, c, PROTOCOL);
1905 getStringValueFromCursor(cv, c, ROAMING_PROTOCOL);
1906 getStringValueFromCursor(cv, c, MVNO_TYPE);
1907 getStringValueFromCursor(cv, c, MVNO_MATCH_DATA);
1908
1909 // bool/int vals
1910 getIntValueFromCursor(cv, c, AUTH_TYPE);
1911 getIntValueFromCursor(cv, c, CURRENT);
1912 getIntValueFromCursor(cv, c, CARRIER_ENABLED);
1913 getIntValueFromCursor(cv, c, BEARER);
1914 getIntValueFromCursor(cv, c, SUBSCRIPTION_ID);
1915 getIntValueFromCursor(cv, c, PROFILE_ID);
chen xu3e303942018-11-28 00:23:01 -08001916 getIntValueFromCursor(cv, c, MODEM_PERSIST);
1917 getIntValueFromCursor(cv, c, MAX_CONNECTIONS);
1918 getIntValueFromCursor(cv, c, WAIT_TIME_RETRY);
1919 getIntValueFromCursor(cv, c, TIME_LIMIT_FOR_MAX_CONNECTIONS);
calvinpan2b419442018-10-23 15:05:11 +08001920 getIntValueFromCursor(cv, c, MTU);
1921 getIntValueFromCursor(cv, c, NETWORK_TYPE_BITMASK);
1922 getIntValueFromCursor(cv, c, BEARER_BITMASK);
chen xu3e303942018-11-28 00:23:01 -08001923 getIntValueFromCursor(cv, c, EDITED_STATUS);
calvinpan2b419442018-10-23 15:05:11 +08001924 getIntValueFromCursor(cv, c, USER_VISIBLE);
1925 getIntValueFromCursor(cv, c, USER_EDITABLE);
1926 getIntValueFromCursor(cv, c, OWNED_BY);
1927 getIntValueFromCursor(cv, c, APN_SET_ID);
Yuuki Habu95aacb12019-02-22 10:49:06 +09001928 getIntValueFromCursor(cv, c, SKIP_464XLAT);
calvinpan2b419442018-10-23 15:05:11 +08001929 }
pkanware08f3ac2017-02-02 18:26:32 -08001930
Sanket Padaweb6fe0852015-07-13 13:37:48 -07001931 private void copyPreservedApnsToNewTable(SQLiteDatabase db, Cursor c) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001932 // Move entries from CARRIERS_TABLE to CARRIERS_TABLE_TMP
Jordan Liuc591b112018-05-02 16:35:03 -07001933 if (c != null && mContext.getResources() != null) {
1934 try {
1935 String[] persistApnsForPlmns = mContext.getResources().getStringArray(
1936 R.array.persist_apns_for_plmn);
1937 while (c.moveToNext()) {
1938 ContentValues cv = new ContentValues();
1939 String val;
1940 // Using V17 copy function for V15 upgrade. This should be fine since it handles
1941 // columns that may not exist properly (getStringValueFromCursor() and
1942 // getIntValueFromCursor() handle column index -1)
1943 copyApnValuesV17(cv, c);
1944 // Change bearer to a bitmask
1945 String bearerStr = c.getString(c.getColumnIndex(BEARER));
1946 if (!TextUtils.isEmpty(bearerStr)) {
SongFerngWang64fb3dd2019-12-02 20:59:47 +08001947 int bearer_bitmask = getBitmaskForTech(Integer.parseInt(bearerStr));
Jordan Liuc591b112018-05-02 16:35:03 -07001948 cv.put(BEARER_BITMASK, bearer_bitmask);
Cassiea58ce712017-12-06 16:21:50 -08001949
SongFerngWang64fb3dd2019-12-02 20:59:47 +08001950 int networkTypeBitmask = rilRadioTechnologyToNetworkTypeBitmask(
1951 Integer.parseInt(bearerStr));
Jordan Liuc591b112018-05-02 16:35:03 -07001952 cv.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001953 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001954
Jordan Liuc591b112018-05-02 16:35:03 -07001955 int userEditedColumnIdx = c.getColumnIndex("user_edited");
1956 if (userEditedColumnIdx != -1) {
1957 String user_edited = c.getString(userEditedColumnIdx);
1958 if (!TextUtils.isEmpty(user_edited)) {
chen xu3e303942018-11-28 00:23:01 -08001959 cv.put(EDITED_STATUS, new Integer(user_edited));
Amit Mahajan899cc602015-05-14 17:22:09 -07001960 }
Jordan Liuc591b112018-05-02 16:35:03 -07001961 } else {
chen xu3e303942018-11-28 00:23:01 -08001962 cv.put(EDITED_STATUS, CARRIER_EDITED);
Jordan Liuc591b112018-05-02 16:35:03 -07001963 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07001964
Jordan Liuc591b112018-05-02 16:35:03 -07001965 // New EDITED column. Default value (UNEDITED) will
1966 // be used for all rows except for non-mvno entries for plmns indicated
1967 // by resource: those will be set to CARRIER_EDITED to preserve
1968 // their current values
1969 val = c.getString(c.getColumnIndex(NUMERIC));
1970 for (String s : persistApnsForPlmns) {
1971 if (!TextUtils.isEmpty(val) && val.equals(s) &&
1972 (!cv.containsKey(MVNO_TYPE) ||
1973 TextUtils.isEmpty(cv.getAsString(MVNO_TYPE)))) {
1974 if (userEditedColumnIdx == -1) {
chen xu3e303942018-11-28 00:23:01 -08001975 cv.put(EDITED_STATUS, CARRIER_EDITED);
Jordan Liuc591b112018-05-02 16:35:03 -07001976 } else { // if (oldVersion == 14) -- if db had user_edited column
chen xu3e303942018-11-28 00:23:01 -08001977 if (cv.getAsInteger(EDITED_STATUS) == USER_EDITED) {
1978 cv.put(EDITED_STATUS, CARRIER_EDITED);
Jordan Liuc591b112018-05-02 16:35:03 -07001979 }
1980 }
1981
1982 break;
1983 }
1984 }
1985
1986 try {
1987 db.insertWithOnConflict(CARRIERS_TABLE_TMP, null, cv,
1988 SQLiteDatabase.CONFLICT_ABORT);
1989 if (VDBG) {
1990 log("dbh.copyPreservedApnsToNewTable: db.insert returned >= 0; " +
1991 "insert successful for cv " + cv);
1992 }
1993 } catch (SQLException e) {
1994 if (VDBG)
1995 log("dbh.copyPreservedApnsToNewTable insertWithOnConflict exception " +
1996 e + " for cv " + cv);
1997 // Insertion failed which could be due to a conflict. Check if that is
1998 // the case and merge the entries
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07001999 Cursor oldRow = selectConflictingRow(db,
Jordan Liuc591b112018-05-02 16:35:03 -07002000 CARRIERS_TABLE_TMP, cv);
2001 if (oldRow != null) {
2002 ContentValues mergedValues = new ContentValues();
2003 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE_TMP, oldRow, cv,
2004 mergedValues, true, mContext);
2005 oldRow.close();
2006 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002007 }
2008 }
Jordan Liuc591b112018-05-02 16:35:03 -07002009 } catch (Resources.NotFoundException e) {
2010 loge("array.persist_apns_for_plmn is not found");
2011 return;
Amit Mahajanb80f7332015-04-16 10:02:52 -07002012 }
2013 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07002014 }
2015
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002016 private void getStringValueFromCursor(ContentValues cv, Cursor c, String key) {
Amit Mahajan47688232017-04-09 16:08:19 -07002017 int columnIndex = c.getColumnIndex(key);
2018 if (columnIndex != -1) {
2019 String fromCursor = c.getString(columnIndex);
2020 if (!TextUtils.isEmpty(fromCursor)) {
2021 cv.put(key, fromCursor);
2022 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002023 }
2024 }
2025
Cassiea58ce712017-12-06 16:21:50 -08002026 /**
2027 * If NETWORK_TYPE_BITMASK does not exist (upgrade from version 23 to version 24), generate
2028 * NETWORK_TYPE_BITMASK with the use of BEARER_BITMASK. If NETWORK_TYPE_BITMASK existed
2029 * (upgrade from version 24 to forward), always map NETWORK_TYPE_BITMASK to BEARER_BITMASK.
2030 */
2031 private void getNetworkTypeBitmaskFromCursor(ContentValues cv, Cursor c) {
2032 int columnIndex = c.getColumnIndex(NETWORK_TYPE_BITMASK);
2033 if (columnIndex != -1) {
2034 getStringValueFromCursor(cv, c, NETWORK_TYPE_BITMASK);
2035 // Map NETWORK_TYPE_BITMASK to BEARER_BITMASK if NETWORK_TYPE_BITMASK existed;
2036 String fromCursor = c.getString(columnIndex);
2037 if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) {
2038 int networkBitmask = Integer.valueOf(fromCursor);
SongFerngWang64fb3dd2019-12-02 20:59:47 +08002039 int bearerBitmask = convertNetworkTypeBitmaskToBearerBitmask(networkBitmask);
Cassiea58ce712017-12-06 16:21:50 -08002040 cv.put(BEARER_BITMASK, String.valueOf(bearerBitmask));
2041 }
2042 return;
2043 }
2044 columnIndex = c.getColumnIndex(BEARER_BITMASK);
2045 if (columnIndex != -1) {
2046 String fromCursor = c.getString(columnIndex);
2047 if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) {
2048 int bearerBitmask = Integer.valueOf(fromCursor);
SongFerngWang64fb3dd2019-12-02 20:59:47 +08002049 int networkBitmask = convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
Cassiea58ce712017-12-06 16:21:50 -08002050 cv.put(NETWORK_TYPE_BITMASK, String.valueOf(networkBitmask));
2051 }
2052 }
2053 }
2054
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002055 private void getIntValueFromCursor(ContentValues cv, Cursor c, String key) {
Amit Mahajan47688232017-04-09 16:08:19 -07002056 int columnIndex = c.getColumnIndex(key);
2057 if (columnIndex != -1) {
2058 String fromCursor = c.getString(columnIndex);
2059 if (!TextUtils.isEmpty(fromCursor)) {
2060 try {
2061 cv.put(key, new Integer(fromCursor));
2062 } catch (NumberFormatException nfe) {
2063 // do nothing
2064 }
Amit Mahajan24223db2015-04-21 14:22:40 -07002065 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002066 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002067 }
2068
yinxu3d98b6c2018-01-05 16:27:30 -08002069 private void getBlobValueFromCursor(ContentValues cv, Cursor c, String key) {
2070 int columnIndex = c.getColumnIndex(key);
2071 if (columnIndex != -1) {
2072 byte[] fromCursor = c.getBlob(columnIndex);
2073 if (fromCursor != null) {
2074 cv.put(key, fromCursor);
2075 }
2076 }
2077 }
2078
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002079 /**
2080 * Gets the next row of apn values.
2081 *
2082 * @param parser the parser
2083 * @return the row or null if it's not an apn
2084 */
2085 private ContentValues getRow(XmlPullParser parser) {
2086 if (!"apn".equals(parser.getName())) {
2087 return null;
2088 }
2089
2090 ContentValues map = new ContentValues();
2091
2092 String mcc = parser.getAttributeValue(null, "mcc");
2093 String mnc = parser.getAttributeValue(null, "mnc");
2094 String numeric = mcc + mnc;
2095
Amit Mahajan28a5d002016-03-02 11:34:28 -08002096 map.put(NUMERIC, numeric);
2097 map.put(MCC, mcc);
2098 map.put(MNC, mnc);
2099 map.put(NAME, parser.getAttributeValue(null, "carrier"));
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002100
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002101 // do not add NULL to the map so that default values can be inserted in db
Amit Mahajan28a5d002016-03-02 11:34:28 -08002102 addStringAttribute(parser, "apn", map, APN);
2103 addStringAttribute(parser, "user", map, USER);
2104 addStringAttribute(parser, "server", map, SERVER);
2105 addStringAttribute(parser, "password", map, PASSWORD);
2106 addStringAttribute(parser, "proxy", map, PROXY);
2107 addStringAttribute(parser, "port", map, PORT);
2108 addStringAttribute(parser, "mmsproxy", map, MMSPROXY);
2109 addStringAttribute(parser, "mmsport", map, MMSPORT);
2110 addStringAttribute(parser, "mmsc", map, MMSC);
Naveen Kalla14154db2016-12-05 16:07:03 -08002111
2112 String apnType = parser.getAttributeValue(null, "type");
2113 if (apnType != null) {
2114 // Remove spaces before putting it in the map.
2115 apnType = apnType.replaceAll("\\s+", "");
2116 map.put(TYPE, apnType);
2117 }
2118
Amit Mahajan28a5d002016-03-02 11:34:28 -08002119 addStringAttribute(parser, "protocol", map, PROTOCOL);
2120 addStringAttribute(parser, "roaming_protocol", map, ROAMING_PROTOCOL);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002121
Amit Mahajan28a5d002016-03-02 11:34:28 -08002122 addIntAttribute(parser, "authtype", map, AUTH_TYPE);
2123 addIntAttribute(parser, "bearer", map, BEARER);
2124 addIntAttribute(parser, "profile_id", map, PROFILE_ID);
chen xu3e303942018-11-28 00:23:01 -08002125 addIntAttribute(parser, "max_conns", map, MAX_CONNECTIONS);
2126 addIntAttribute(parser, "wait_time", map, WAIT_TIME_RETRY);
2127 addIntAttribute(parser, "max_conns_time", map, TIME_LIMIT_FOR_MAX_CONNECTIONS);
Amit Mahajan28a5d002016-03-02 11:34:28 -08002128 addIntAttribute(parser, "mtu", map, MTU);
Jordan Liu92da8c82018-04-10 16:00:06 -07002129 addIntAttribute(parser, "apn_set_id", map, APN_SET_ID);
calvinpanf83cb472018-12-20 16:31:02 +08002130 addIntAttribute(parser, "carrier_id", map, CARRIER_ID);
Yuuki Habu95aacb12019-02-22 10:49:06 +09002131 addIntAttribute(parser, "skip_464xlat", map, SKIP_464XLAT);
Amit Mahajanda607212015-10-08 09:13:00 -07002132
Amit Mahajan28a5d002016-03-02 11:34:28 -08002133 addBoolAttribute(parser, "carrier_enabled", map, CARRIER_ENABLED);
chen xu3e303942018-11-28 00:23:01 -08002134 addBoolAttribute(parser, "modem_cognitive", map, MODEM_PERSIST);
Amit Mahajan28a5d002016-03-02 11:34:28 -08002135 addBoolAttribute(parser, "user_visible", map, USER_VISIBLE);
Amit Mahajan460d7032017-07-17 14:42:33 -07002136 addBoolAttribute(parser, "user_editable", map, USER_EDITABLE);
Sungmin Choi27045ef2013-01-25 17:48:06 +09002137
Cassiea58ce712017-12-06 16:21:50 -08002138 int networkTypeBitmask = 0;
2139 String networkTypeList = parser.getAttributeValue(null, "network_type_bitmask");
2140 if (networkTypeList != null) {
SongFerngWang64fb3dd2019-12-02 20:59:47 +08002141 networkTypeBitmask = getBitmaskFromString(networkTypeList);
Cassiea58ce712017-12-06 16:21:50 -08002142 }
2143 map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
2144
Amit Mahajaned3e7472016-04-13 17:46:42 -07002145 int bearerBitmask = 0;
Cassiea58ce712017-12-06 16:21:50 -08002146 if (networkTypeList != null) {
SongFerngWang64fb3dd2019-12-02 20:59:47 +08002147 bearerBitmask = convertNetworkTypeBitmaskToBearerBitmask(networkTypeBitmask);
Cassiea58ce712017-12-06 16:21:50 -08002148 } else {
2149 String bearerList = parser.getAttributeValue(null, "bearer_bitmask");
2150 if (bearerList != null) {
SongFerngWang64fb3dd2019-12-02 20:59:47 +08002151 bearerBitmask = getBitmaskFromString(bearerList);
Cassiea58ce712017-12-06 16:21:50 -08002152 }
2153 // Update the network type bitmask to keep them sync.
SongFerngWang64fb3dd2019-12-02 20:59:47 +08002154 networkTypeBitmask = convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
Mengjun Leng374ce6d2019-04-22 13:59:59 +08002155 // Legacy bearer is deprecated, in order to be compatible with bearer_bitmask till
2156 // both are removed (bearer_bitmask is marked as deprecated now), just appends
2157 // bearer into bearer_bitmask only.
2158 // Use the constant string BEARER instead of the "bearer" by hard code.
2159 final String apnBearer = parser.getAttributeValue(null, BEARER);
2160 if (apnBearer != null) {
2161 final int legacyBearerBitmask =
Steven Laver915f5562020-01-17 18:07:46 -08002162 getBitmaskForTech(Integer.parseInt(apnBearer));
2163 networkTypeBitmask |=
2164 convertBearerBitmaskToNetworkTypeBitmask(legacyBearerBitmask);
Mengjun Leng374ce6d2019-04-22 13:59:59 +08002165 }
Cassiea58ce712017-12-06 16:21:50 -08002166 map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
Amit Mahajanb80f7332015-04-16 10:02:52 -07002167 }
Amit Mahajaned3e7472016-04-13 17:46:42 -07002168 map.put(BEARER_BITMASK, bearerBitmask);
Amit Mahajanb80f7332015-04-16 10:02:52 -07002169
Sungmin Choi27045ef2013-01-25 17:48:06 +09002170 String mvno_type = parser.getAttributeValue(null, "mvno_type");
2171 if (mvno_type != null) {
2172 String mvno_match_data = parser.getAttributeValue(null, "mvno_match_data");
2173 if (mvno_match_data != null) {
Amit Mahajan28a5d002016-03-02 11:34:28 -08002174 map.put(MVNO_TYPE, mvno_type);
2175 map.put(MVNO_MATCH_DATA, mvno_match_data);
Sungmin Choi27045ef2013-01-25 17:48:06 +09002176 }
2177 }
Amit Mahajanb0688862014-08-13 16:53:51 +00002178
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002179 return map;
2180 }
2181
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002182 private void addStringAttribute(XmlPullParser parser, String att,
2183 ContentValues map, String key) {
2184 String val = parser.getAttributeValue(null, att);
2185 if (val != null) {
2186 map.put(key, val);
2187 }
2188 }
2189
2190 private void addIntAttribute(XmlPullParser parser, String att,
2191 ContentValues map, String key) {
2192 String val = parser.getAttributeValue(null, att);
2193 if (val != null) {
2194 map.put(key, Integer.parseInt(val));
2195 }
2196 }
2197
2198 private void addBoolAttribute(XmlPullParser parser, String att,
2199 ContentValues map, String key) {
2200 String val = parser.getAttributeValue(null, att);
2201 if (val != null) {
2202 map.put(key, Boolean.parseBoolean(val));
2203 }
2204 }
2205
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002206 /*
2207 * Loads apns from xml file into the database
2208 *
2209 * @param db the sqlite database to write to
2210 * @param parser the xml parser
2211 *
2212 */
2213 private void loadApns(SQLiteDatabase db, XmlPullParser parser) {
2214 if (parser != null) {
2215 try {
jewon.lee4167fcc2013-01-17 13:10:37 +09002216 db.beginTransaction();
Hyejin Kim7e7c2742013-02-11 20:02:18 +09002217 XmlUtils.nextElement(parser);
2218 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002219 ContentValues row = getRow(parser);
Hyejin Kim7e7c2742013-02-11 20:02:18 +09002220 if (row == null) {
2221 throw new XmlPullParserException("Expected 'apn' tag", parser, null);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002222 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002223 insertAddingDefaults(db, row);
Hyejin Kim7e7c2742013-02-11 20:02:18 +09002224 XmlUtils.nextElement(parser);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002225 }
jewon.lee4167fcc2013-01-17 13:10:37 +09002226 db.setTransactionSuccessful();
Hyejin Kim7e7c2742013-02-11 20:02:18 +09002227 } catch (XmlPullParserException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002228 loge("Got XmlPullParserException while loading apns." + e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002229 } catch (IOException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002230 loge("Got IOException while loading apns." + e);
Hyejin Kim7e7c2742013-02-11 20:02:18 +09002231 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002232 loge("Got SQLException while loading apns." + e);
jewon.lee4167fcc2013-01-17 13:10:37 +09002233 } finally {
2234 db.endTransaction();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002235 }
2236 }
2237 }
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07002238
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002239 private void insertAddingDefaults(SQLiteDatabase db, ContentValues row) {
Amit Mahajanb0688862014-08-13 16:53:51 +00002240 row = setDefaultValue(row);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002241 try {
Amit Mahajan28a5d002016-03-02 11:34:28 -08002242 db.insertWithOnConflict(CARRIERS_TABLE, null, row, SQLiteDatabase.CONFLICT_ABORT);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002243 if (VDBG) log("dbh.insertAddingDefaults: db.insert returned >= 0; insert " +
2244 "successful for cv " + row);
2245 } catch (SQLException e) {
2246 if (VDBG) log("dbh.insertAddingDefaults: exception " + e);
2247 // Insertion failed which could be due to a conflict. Check if that is the case and
Amit Mahajanb80f7332015-04-16 10:02:52 -07002248 // update edited field accordingly.
2249 // Search for the exact same entry and update edited field.
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002250 // If it is USER_EDITED/CARRIER_EDITED change it to UNEDITED,
2251 // and if USER/CARRIER_DELETED change it to USER/CARRIER_DELETED_BUT_PRESENT_IN_XML.
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002252 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, row);
2253 if (oldRow != null) {
2254 // Update the row
2255 ContentValues mergedValues = new ContentValues();
chen xu3e303942018-11-28 00:23:01 -08002256 int edited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS));
Amit Mahajanb80f7332015-04-16 10:02:52 -07002257 int old_edited = edited;
Amit Mahajan28a5d002016-03-02 11:34:28 -08002258 if (edited != UNEDITED) {
2259 if (edited == USER_DELETED) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002260 // USER_DELETED_BUT_PRESENT_IN_XML indicates entry has been deleted
2261 // by user but present in apn xml file.
Amit Mahajan28a5d002016-03-02 11:34:28 -08002262 edited = USER_DELETED_BUT_PRESENT_IN_XML;
2263 } else if (edited == CARRIER_DELETED) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002264 // CARRIER_DELETED_BUT_PRESENT_IN_XML indicates entry has been deleted
2265 // by user but present in apn xml file.
Amit Mahajan28a5d002016-03-02 11:34:28 -08002266 edited = CARRIER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002267 }
chen xu3e303942018-11-28 00:23:01 -08002268 mergedValues.put(EDITED_STATUS, edited);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002269 }
2270
Amit Mahajanb80f7332015-04-16 10:02:52 -07002271 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, row, mergedValues, false,
2272 mContext);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002273
Amit Mahajanb80f7332015-04-16 10:02:52 -07002274 if (VDBG) log("dbh.insertAddingDefaults: old edited = " + old_edited
2275 + " new edited = " + edited);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002276
2277 oldRow.close();
2278 }
2279 }
2280 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002281 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002282
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002283 public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow,
2284 ContentValues newRow, ContentValues mergedValues,
2285 boolean onUpgrade, Context context) {
2286 if (newRow.containsKey(TYPE)) {
2287 // Merge the types
2288 String oldType = oldRow.getString(oldRow.getColumnIndex(TYPE));
2289 String newType = newRow.getAsString(TYPE);
Amit Mahajanb80f7332015-04-16 10:02:52 -07002290
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002291 if (!oldType.equalsIgnoreCase(newType)) {
2292 if (oldType.equals("") || newType.equals("")) {
2293 newRow.put(TYPE, "");
2294 } else {
2295 String[] oldTypes = oldType.toLowerCase().split(",");
2296 String[] newTypes = newType.toLowerCase().split(",");
Amit Mahajanb80f7332015-04-16 10:02:52 -07002297
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002298 if (VDBG) {
2299 log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
2300 oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
2301 BEARER_BITMASK)) + " old networkType=" +
2302 oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) +
2303 " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
2304 PROFILE_ID)) + " newRow " + newRow);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002305 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002306
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002307 // If separate rows are needed, do not need to merge any further
2308 if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes,
2309 newTypes)) {
2310 if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " +
2311 "true");
2312 return;
Amit Mahajanb80f7332015-04-16 10:02:52 -07002313 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07002314
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002315 // Merge the 2 types
2316 ArrayList<String> mergedTypes = new ArrayList<String>();
2317 mergedTypes.addAll(Arrays.asList(oldTypes));
2318 for (String s : newTypes) {
2319 if (!mergedTypes.contains(s.trim())) {
2320 mergedTypes.add(s);
2321 }
Cassiea58ce712017-12-06 16:21:50 -08002322 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002323 StringBuilder mergedType = new StringBuilder();
2324 for (int i = 0; i < mergedTypes.size(); i++) {
2325 mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i));
Jordan Liu31b99ad2018-01-08 13:38:38 -08002326 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002327 newRow.put(TYPE, mergedType.toString());
Jordan Liu31b99ad2018-01-08 13:38:38 -08002328 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002329 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002330 mergedValues.put(TYPE, newRow.getAsString(TYPE));
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002331 }
2332
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002333 if (newRow.containsKey(BEARER_BITMASK)) {
2334 int oldBearer = oldRow.getInt(oldRow.getColumnIndex(BEARER_BITMASK));
2335 int newBearer = newRow.getAsInteger(BEARER_BITMASK);
2336 if (oldBearer != newBearer) {
2337 if (oldBearer == 0 || newBearer == 0) {
2338 newRow.put(BEARER_BITMASK, 0);
2339 } else {
2340 newRow.put(BEARER_BITMASK, (oldBearer | newBearer));
Amit Mahajanb80f7332015-04-16 10:02:52 -07002341 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002342 }
2343 mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK));
2344 }
2345
2346 if (newRow.containsKey(NETWORK_TYPE_BITMASK)) {
2347 int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK));
2348 int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK);
2349 if (oldBitmask != newBitmask) {
2350 if (oldBitmask == 0 || newBitmask == 0) {
2351 newRow.put(NETWORK_TYPE_BITMASK, 0);
2352 } else {
2353 newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask));
2354 }
2355 }
2356 mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK));
2357 }
2358
2359 if (newRow.containsKey(BEARER_BITMASK)
2360 && newRow.containsKey(NETWORK_TYPE_BITMASK)) {
2361 syncBearerBitmaskAndNetworkTypeBitmask(mergedValues);
2362 }
2363
2364 if (!onUpgrade) {
2365 // Do not overwrite a carrier or user edit with EDITED=UNEDITED
2366 if (newRow.containsKey(EDITED_STATUS)) {
2367 int oldEdited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS));
2368 int newEdited = newRow.getAsInteger(EDITED_STATUS);
2369 if (newEdited == UNEDITED && (oldEdited == CARRIER_EDITED
2370 || oldEdited == CARRIER_DELETED
2371 || oldEdited == CARRIER_DELETED_BUT_PRESENT_IN_XML
2372 || oldEdited == USER_EDITED
2373 || oldEdited == USER_DELETED
2374 || oldEdited == USER_DELETED_BUT_PRESENT_IN_XML)) {
2375 newRow.remove(EDITED_STATUS);
2376 }
2377 }
2378 mergedValues.putAll(newRow);
2379 }
2380
2381 if (mergedValues.size() > 0) {
2382 db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")),
2383 null);
2384 }
2385 }
2386
2387 private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow,
2388 ContentValues newRow, Context context,
2389 String[] oldTypes, String[] newTypes) {
2390 // If this APN falls under persist_apns_for_plmn, and the
2391 // only difference between old type and new type is that one has dun, and
2392 // the APNs have profile_id 0 or not set, then set the profile_id to 1 for
2393 // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist
2394 // separately in db.
2395
2396 boolean match = false;
2397
2398 // Check if APN falls under persist_apns_for_plmn
2399 if (context.getResources() != null) {
2400 String[] persistApnsForPlmns = context.getResources().getStringArray(
2401 R.array.persist_apns_for_plmn);
2402 for (String s : persistApnsForPlmns) {
2403 if (s.equalsIgnoreCase(newRow.getAsString(NUMERIC))) {
2404 match = true;
2405 break;
2406 }
2407 }
2408 } else {
2409 loge("separateRowsNeeded: resources=null");
2410 }
2411
2412 if (!match) return false;
2413
2414 // APN falls under persist_apns_for_plmn
2415 // Check if only difference between old type and new type is that
2416 // one has dun
2417 ArrayList<String> oldTypesAl = new ArrayList<String>(Arrays.asList(oldTypes));
2418 ArrayList<String> newTypesAl = new ArrayList<String>(Arrays.asList(newTypes));
2419 ArrayList<String> listWithDun = null;
2420 ArrayList<String> listWithoutDun = null;
2421 boolean dunInOld = false;
2422 if (oldTypesAl.size() == newTypesAl.size() + 1) {
2423 listWithDun = oldTypesAl;
2424 listWithoutDun = newTypesAl;
2425 dunInOld = true;
2426 } else if (oldTypesAl.size() + 1 == newTypesAl.size()) {
2427 listWithDun = newTypesAl;
2428 listWithoutDun = oldTypesAl;
2429 } else {
2430 return false;
2431 }
2432
2433 if (listWithDun.contains("dun") && !listWithoutDun.contains("dun")) {
2434 listWithoutDun.add("dun");
2435 if (!listWithDun.containsAll(listWithoutDun)) {
2436 return false;
Amit Mahajanb80f7332015-04-16 10:02:52 -07002437 }
2438
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002439 // Only difference between old type and new type is that
Amit Mahajanb80f7332015-04-16 10:02:52 -07002440 // one has dun
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002441 // Check if profile_id is 0/not set
2442 if (oldRow.getInt(oldRow.getColumnIndex(PROFILE_ID)) == 0) {
2443 if (dunInOld) {
2444 // Update oldRow to remove dun from its type field
2445 ContentValues updateOldRow = new ContentValues();
2446 StringBuilder sb = new StringBuilder();
2447 boolean first = true;
2448 for (String s : listWithDun) {
2449 if (!s.equalsIgnoreCase("dun")) {
2450 sb.append(first ? s : "," + s);
2451 first = false;
2452 }
2453 }
2454 String updatedType = sb.toString();
2455 if (VDBG) {
2456 log("separateRowsNeeded: updating type in oldRow to " + updatedType);
2457 }
2458 updateOldRow.put(TYPE, updatedType);
2459 db.update(table, updateOldRow,
2460 "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null);
2461 return true;
2462 } else {
2463 if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow");
2464 // Update newRow to set profile_id to 1
2465 newRow.put(PROFILE_ID, new Integer(1));
2466 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07002467 } else {
2468 return false;
2469 }
2470
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002471 // If match was found, both oldRow and newRow need to exist
2472 // separately in db. Add newRow to db.
2473 try {
2474 db.insertWithOnConflict(table, null, newRow, SQLiteDatabase.CONFLICT_REPLACE);
2475 if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db");
2476 return true;
2477 } catch (SQLException e) {
2478 loge("Exception on trying to add new row after updating profile_id");
Amit Mahajanb80f7332015-04-16 10:02:52 -07002479 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07002480 }
2481
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002482 return false;
2483 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002484
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002485 public static Cursor selectConflictingRow(SQLiteDatabase db, String table,
2486 ContentValues row) {
2487 // Conflict is possible only when numeric, mcc, mnc (fields without any default value)
2488 // are set in the new row
2489 if (!row.containsKey(NUMERIC) || !row.containsKey(MCC) || !row.containsKey(MNC)) {
2490 loge("dbh.selectConflictingRow: called for non-conflicting row: " + row);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002491 return null;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07002492 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002493
2494 String[] columns = { "_id",
2495 TYPE,
2496 EDITED_STATUS,
2497 BEARER_BITMASK,
2498 NETWORK_TYPE_BITMASK,
2499 PROFILE_ID };
2500 String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?";
2501 int i = 0;
2502 String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
2503 for (String field : CARRIERS_UNIQUE_FIELDS) {
2504 if (!row.containsKey(field)) {
2505 selectionArgs[i++] = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field);
2506 } else {
2507 if (CARRIERS_BOOLEAN_FIELDS.contains(field)) {
2508 // for boolean fields we overwrite the strings "true" and "false" with "1"
2509 // and "0"
2510 selectionArgs[i++] = convertStringToIntString(row.getAsString(field));
2511 } else {
2512 selectionArgs[i++] = row.getAsString(field);
2513 }
2514 }
2515 }
2516
2517 Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
2518
2519 if (c != null) {
2520 if (c.getCount() == 1) {
2521 if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " +
2522 "row found");
2523 if (c.moveToFirst()) {
2524 return c;
2525 } else {
2526 loge("dbh.selectConflictingRow: moveToFirst() failed");
2527 }
2528 } else {
2529 loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() +
2530 " matching rows found for cv " + row);
2531 }
2532 c.close();
2533 } else {
2534 loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " +
2535 "cv " + row);
2536 }
2537
2538 return null;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002539 }
2540
Jordan Liue6f0bce2016-09-21 18:31:43 -07002541 /**
Jordan Liu8b78f712018-05-21 11:10:48 -07002542 * Convert "true" and "false" to "1" and "0".
2543 * If the passed in string is already "1" or "0" returns the passed in string.
2544 */
2545 private static String convertStringToIntString(String boolString) {
2546 if ("0".equals(boolString) || "false".equalsIgnoreCase(boolString)) return "0";
2547 return "1";
2548 }
2549
2550 /**
2551 * Convert "1" and "0" to "true" and "false".
2552 * If the passed in string is already "true" or "false" returns the passed in string.
2553 */
2554 private static String convertStringToBoolString(String intString) {
2555 if ("0".equals(intString) || "false".equalsIgnoreCase(intString)) return "false";
2556 return "true";
2557 }
2558
2559 /**
Jordan Liue6f0bce2016-09-21 18:31:43 -07002560 * These methods can be overridden in a subclass for testing TelephonyProvider using an
2561 * in-memory database.
2562 */
2563 SQLiteDatabase getReadableDatabase() {
2564 return mOpenHelper.getReadableDatabase();
2565 }
2566 SQLiteDatabase getWritableDatabase() {
2567 return mOpenHelper.getWritableDatabase();
2568 }
2569 void initDatabaseWithDatabaseHelper(SQLiteDatabase db) {
2570 mOpenHelper.initDatabase(db);
2571 }
2572 boolean needApnDbUpdate() {
2573 return mOpenHelper.apnDbUpdateNeeded();
2574 }
2575
Jordan Liu3de76f82017-05-15 15:21:01 -07002576 private static boolean apnSourceServiceExists(Context context) {
2577 if (s_apnSourceServiceExists != null) {
2578 return s_apnSourceServiceExists;
2579 }
2580 try {
2581 String service = context.getResources().getString(R.string.apn_source_service);
2582 if (TextUtils.isEmpty(service)) {
2583 s_apnSourceServiceExists = false;
2584 } else {
2585 s_apnSourceServiceExists = context.getPackageManager().getServiceInfo(
2586 ComponentName.unflattenFromString(service), 0)
2587 != null;
2588 }
2589 } catch (PackageManager.NameNotFoundException e) {
2590 s_apnSourceServiceExists = false;
2591 }
2592 return s_apnSourceServiceExists;
2593 }
2594
Jordan Liu11c113e2018-11-13 12:19:11 -08002595 private void restoreApnsWithService(int subId) {
Jordan Liu3de76f82017-05-15 15:21:01 -07002596 Context context = getContext();
2597 Resources r = context.getResources();
James.cf Lin90f42ec2020-04-21 22:23:31 +08002598 AtomicBoolean connectionBindingInvalid = new AtomicBoolean(false);
Jordan Liu3de76f82017-05-15 15:21:01 -07002599 ServiceConnection connection = new ServiceConnection() {
2600 @Override
2601 public void onServiceConnected(ComponentName className,
2602 IBinder service) {
2603 log("restoreApnsWithService: onServiceConnected");
2604 synchronized (mLock) {
2605 mIApnSourceService = IApnSourceService.Stub.asInterface(service);
2606 mLock.notifyAll();
2607 }
2608 }
2609
2610 @Override
2611 public void onServiceDisconnected(ComponentName arg0) {
2612 loge("mIApnSourceService has disconnected unexpectedly");
2613 synchronized (mLock) {
2614 mIApnSourceService = null;
2615 }
2616 }
James.cf Lin90f42ec2020-04-21 22:23:31 +08002617
2618 @Override
2619 public void onBindingDied(ComponentName name) {
2620 loge("The binding to the apn service connection is dead: " + name);
2621 synchronized (mLock) {
2622 connectionBindingInvalid.set(true);
2623 mLock.notifyAll();
2624 }
2625 }
2626
2627 @Override
2628 public void onNullBinding(ComponentName name) {
2629 loge("Null binding: " + name);
2630 synchronized (mLock) {
2631 connectionBindingInvalid.set(true);
2632 mLock.notifyAll();
2633 }
2634 }
Jordan Liu3de76f82017-05-15 15:21:01 -07002635 };
2636
2637 Intent intent = new Intent(IApnSourceService.class.getName());
2638 intent.setComponent(ComponentName.unflattenFromString(
2639 r.getString(R.string.apn_source_service)));
2640 log("binding to service to restore apns, intent=" + intent);
2641 try {
Jordan Liu198704f2018-09-19 16:34:25 -07002642 if (context.bindService(intent, connection, Context.BIND_IMPORTANT |
2643 Context.BIND_AUTO_CREATE)) {
Jordan Liu3de76f82017-05-15 15:21:01 -07002644 synchronized (mLock) {
James.cf Lin90f42ec2020-04-21 22:23:31 +08002645 while (mIApnSourceService == null && !connectionBindingInvalid.get()) {
Jordan Liu3de76f82017-05-15 15:21:01 -07002646 try {
2647 mLock.wait();
2648 } catch (InterruptedException e) {
2649 loge("Error while waiting for service connection: " + e);
2650 }
2651 }
James.cf Lin90f42ec2020-04-21 22:23:31 +08002652 if (connectionBindingInvalid.get()) {
2653 loge("The binding is invalid.");
2654 return;
2655 }
Jordan Liu3de76f82017-05-15 15:21:01 -07002656 try {
Jordan Liu11c113e2018-11-13 12:19:11 -08002657 ContentValues[] values = mIApnSourceService.getApns(subId);
Jordan Liu3de76f82017-05-15 15:21:01 -07002658 if (values != null) {
2659 // we use the unsynchronized insert because this function is called
2660 // within the syncrhonized function delete()
2661 unsynchronizedBulkInsert(CONTENT_URI, values);
2662 log("restoreApnsWithService: restored");
2663 }
2664 } catch (RemoteException e) {
2665 loge("Error applying apns from service: " + e);
2666 }
2667 }
2668 } else {
2669 loge("unable to bind to service from intent=" + intent);
2670 }
2671 } catch (SecurityException e) {
2672 loge("Error applying apns from service: " + e);
2673 } finally {
2674 if (connection != null) {
2675 context.unbindService(connection);
2676 }
2677 synchronized (mLock) {
2678 mIApnSourceService = null;
2679 }
2680 }
2681 }
2682
Jordan Liue6f0bce2016-09-21 18:31:43 -07002683
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002684 @Override
2685 public boolean onCreate() {
2686 mOpenHelper = new DatabaseHelper(getContext());
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002687
Amit Mahajan0c1d0dd2020-04-21 20:38:29 +00002688 try {
2689 PhoneFactory.addLocalLog(TAG, 100);
2690 } catch (IllegalArgumentException e) {
2691 // ignore
2692 }
2693
Amit Mahajanf5eae592019-05-22 12:27:51 -07002694 boolean isNewBuild = false;
2695 String newBuildId = SystemProperties.get("ro.build.id", null);
2696 if (!TextUtils.isEmpty(newBuildId)) {
2697 // Check if build id has changed
2698 SharedPreferences sp = getContext().getSharedPreferences(BUILD_ID_FILE,
2699 Context.MODE_PRIVATE);
2700 String oldBuildId = sp.getString(RO_BUILD_ID, "");
2701 if (!newBuildId.equals(oldBuildId)) {
2702 localLog("onCreate: build id changed from " + oldBuildId + " to " + newBuildId);
2703 isNewBuild = true;
2704 } else {
2705 if (VDBG) log("onCreate: build id did not change: " + oldBuildId);
2706 }
2707 sp.edit().putString(RO_BUILD_ID, newBuildId).apply();
2708 } else {
2709 if (VDBG) log("onCreate: newBuildId is empty");
2710 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002711
Amit Mahajanf5eae592019-05-22 12:27:51 -07002712 if (isNewBuild) {
2713 if (!apnSourceServiceExists(getContext())) {
Amit Mahajanf5eae592019-05-22 12:27:51 -07002714 // Update APN DB
2715 updateApnDb();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002716 }
Amit Mahajanf5eae592019-05-22 12:27:51 -07002717
2718 // Add all APN related shared prefs to local log for dumpsys
2719 if (DBG) addAllApnSharedPrefToLocalLog();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002720 }
2721
yuemingwc41e5c82017-11-09 13:30:33 +00002722 SharedPreferences sp = getContext().getSharedPreferences(ENFORCED_FILE,
2723 Context.MODE_PRIVATE);
2724 mManagedApnEnforced = sp.getBoolean(ENFORCED_KEY, false);
2725
Wink Saville6de10272014-06-22 07:38:43 -07002726 if (VDBG) log("onCreate:- ret true");
yuemingwc41e5c82017-11-09 13:30:33 +00002727
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002728 return true;
2729 }
2730
Amit Mahajanf5eae592019-05-22 12:27:51 -07002731 private void addAllApnSharedPrefToLocalLog() {
2732 localLog("addAllApnSharedPrefToLocalLog");
2733 SharedPreferences spApn = getContext().getSharedPreferences(PREF_FILE_APN,
2734 Context.MODE_PRIVATE);
2735
2736 Map<String, ?> allPrefApnId = spApn.getAll();
2737 for (String key : allPrefApnId.keySet()) {
2738 try {
2739 localLog(key + ":" + allPrefApnId.get(key).toString());
2740 } catch (Exception e) {
2741 localLog("Skipping over key " + key + " due to exception " + e);
2742 }
2743 }
2744
2745 SharedPreferences spFullApn = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
2746 Context.MODE_PRIVATE);
2747
2748 Map<String, ?> allPrefFullApn = spFullApn.getAll();
2749 for (String key : allPrefFullApn.keySet()) {
2750 try {
2751 localLog(key + ":" + allPrefFullApn.get(key).toString());
2752 } catch (Exception e) {
2753 localLog("Skipping over key " + key + " due to exception " + e);
2754 }
2755 }
2756 }
2757
2758 private static void localLog(String logMsg) {
2759 Log.d(TAG, logMsg);
Amit Mahajan0c1d0dd2020-04-21 20:38:29 +00002760 PhoneFactory.localLog(TAG, logMsg);
Amit Mahajanf5eae592019-05-22 12:27:51 -07002761 }
2762
yuemingwc41e5c82017-11-09 13:30:33 +00002763 private synchronized boolean isManagedApnEnforced() {
2764 return mManagedApnEnforced;
2765 }
2766
2767 private void setManagedApnEnforced(boolean enforced) {
2768 SharedPreferences sp = getContext().getSharedPreferences(ENFORCED_FILE,
2769 Context.MODE_PRIVATE);
2770 SharedPreferences.Editor editor = sp.edit();
2771 editor.putBoolean(ENFORCED_KEY, enforced);
2772 editor.apply();
2773 synchronized (this) {
2774 mManagedApnEnforced = enforced;
2775 }
2776 }
2777
Amit Mahajanbf7144e2017-08-29 11:39:48 -07002778 private void setPreferredApnId(Long id, int subId, boolean saveApn) {
Amit Mahajan28a5d002016-03-02 11:34:28 -08002779 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN,
2780 Context.MODE_PRIVATE);
John Huangb1bc16d2009-03-24 18:26:28 -07002781 SharedPreferences.Editor editor = sp.edit();
Amit Mahajanbf7144e2017-08-29 11:39:48 -07002782 editor.putLong(COLUMN_APN_ID + subId, id != null ? id : INVALID_APN_ID);
Amit Mahajanf5eae592019-05-22 12:27:51 -07002783 localLog("setPreferredApnId: " + COLUMN_APN_ID + subId + ":"
2784 + (id != null ? id : INVALID_APN_ID));
Amit Mahajanbf7144e2017-08-29 11:39:48 -07002785 // This is for debug purposes. It indicates if this APN was set by DcTracker or user (true)
2786 // or if this was restored from APN saved in PREF_FILE_FULL_APN (false).
2787 editor.putBoolean(EXPLICIT_SET_CALLED + subId, saveApn);
Amit Mahajanf5eae592019-05-22 12:27:51 -07002788 localLog("setPreferredApnId: " + EXPLICIT_SET_CALLED + subId + ":" + saveApn);
Brad Fitzpatrick2227c4a2010-08-30 17:42:39 -07002789 editor.apply();
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002790 if (id == null || id.longValue() == INVALID_APN_ID) {
2791 deletePreferredApn(subId);
Amit Mahajanbf7144e2017-08-29 11:39:48 -07002792 } else {
2793 // If id is not invalid, and saveApn is true, save the actual APN in PREF_FILE_FULL_APN
2794 // too.
2795 if (saveApn) {
2796 setPreferredApn(id, subId);
2797 }
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002798 }
John Huangb1bc16d2009-03-24 18:26:28 -07002799 }
2800
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002801 private long getPreferredApnId(int subId, boolean checkApnSp) {
Amit Mahajan28a5d002016-03-02 11:34:28 -08002802 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN,
2803 Context.MODE_PRIVATE);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002804 long apnId = sp.getLong(COLUMN_APN_ID + subId, INVALID_APN_ID);
2805 if (apnId == INVALID_APN_ID && checkApnSp) {
2806 apnId = getPreferredApnIdFromApn(subId);
2807 if (apnId != INVALID_APN_ID) {
Amit Mahajanbf7144e2017-08-29 11:39:48 -07002808 setPreferredApnId(apnId, subId, false);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002809 }
2810 }
2811 return apnId;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002812 }
2813
Jordan Liuc6078b72018-05-01 11:34:21 -07002814 private int getPreferredApnSetId(int subId) {
2815 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
2816 Context.MODE_PRIVATE);
2817 try {
2818 return Integer.parseInt(sp.getString(APN_SET_ID + subId, null));
2819 } catch (NumberFormatException e) {
chen xu3e303942018-11-28 00:23:01 -08002820 return NO_APN_SET_ID;
Jordan Liuc6078b72018-05-01 11:34:21 -07002821 }
2822 }
2823
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002824 private void deletePreferredApnId(Context context) {
2825 SharedPreferences sp = context.getSharedPreferences(PREF_FILE_APN,
Amit Mahajan28a5d002016-03-02 11:34:28 -08002826 Context.MODE_PRIVATE);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002827 SharedPreferences.Editor editor = sp.edit();
2828 editor.clear();
2829 editor.apply();
John Huangb1bc16d2009-03-24 18:26:28 -07002830 }
2831
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002832 private void setPreferredApn(Long id, int subId) {
Amit Mahajanf5eae592019-05-22 12:27:51 -07002833 localLog("setPreferredApn: _id " + id + " subId " + subId);
Jordan Liue6f0bce2016-09-21 18:31:43 -07002834 SQLiteDatabase db = getWritableDatabase();
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002835 // query all unique fields from id
2836 String[] proj = CARRIERS_UNIQUE_FIELDS.toArray(new String[CARRIERS_UNIQUE_FIELDS.size()]);
yuemingwe0101b82017-12-13 21:49:09 +00002837
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002838 Cursor c = db.query(CARRIERS_TABLE, proj, "_id=" + id, null, null, null, null);
2839 if (c != null) {
2840 if (c.getCount() == 1) {
2841 c.moveToFirst();
2842 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
2843 Context.MODE_PRIVATE);
2844 SharedPreferences.Editor editor = sp.edit();
2845 // store values of all unique fields to SP
2846 for (String key : CARRIERS_UNIQUE_FIELDS) {
2847 editor.putString(key + subId, c.getString(c.getColumnIndex(key)));
Amit Mahajanf5eae592019-05-22 12:27:51 -07002848 localLog("setPreferredApn: " + key + subId + ":"
2849 + c.getString(c.getColumnIndex(key)));
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002850 }
2851 // also store the version number
2852 editor.putString(DB_VERSION_KEY + subId, "" + DATABASE_VERSION);
Amit Mahajanf5eae592019-05-22 12:27:51 -07002853 localLog("setPreferredApn: " + DB_VERSION_KEY + subId + ":" + DATABASE_VERSION);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002854 editor.apply();
2855 } else {
2856 log("setPreferredApn: # matching APNs found " + c.getCount());
2857 }
2858 c.close();
2859 } else {
2860 log("setPreferredApn: No matching APN found");
2861 }
2862 }
2863
2864 private long getPreferredApnIdFromApn(int subId) {
2865 log("getPreferredApnIdFromApn: for subId " + subId);
Jordan Liu6500c402018-03-13 11:59:43 -07002866 SQLiteDatabase db = getReadableDatabase();
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002867
2868 List<String> whereList = new ArrayList<>();
2869 List<String> whereArgsList = new ArrayList<>();
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002870 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
2871 Context.MODE_PRIVATE);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002872 for (String key : CARRIERS_UNIQUE_FIELDS) {
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002873 String value = sp.getString(key + subId, null);
2874 if (value == null) {
2875 continue;
2876 } else {
2877 whereList.add(key);
2878 whereArgsList.add(value);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002879 }
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002880 }
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07002881 if (whereList.size() == 0) return INVALID_APN_ID;
2882
2883 String where = TextUtils.join("=? and ", whereList) + "=?";
2884 String[] whereArgs = new String[whereArgsList.size()];
2885 whereArgs = whereArgsList.toArray(whereArgs);
2886
2887 long apnId = INVALID_APN_ID;
Amit Mahajan28a5d002016-03-02 11:34:28 -08002888 Cursor c = db.query(CARRIERS_TABLE, new String[]{"_id"}, where, whereArgs, null, null,
2889 null);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002890 if (c != null) {
2891 if (c.getCount() == 1) {
2892 c.moveToFirst();
2893 apnId = c.getInt(c.getColumnIndex("_id"));
2894 } else {
2895 log("getPreferredApnIdFromApn: returning INVALID. # matching APNs found " +
2896 c.getCount());
2897 }
2898 c.close();
2899 } else {
2900 log("getPreferredApnIdFromApn: returning INVALID. No matching APN found");
2901 }
2902 return apnId;
2903 }
2904
2905 private void deletePreferredApn(int subId) {
2906 log("deletePreferredApn: for subId " + subId);
2907 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
2908 Context.MODE_PRIVATE);
2909 if (sp.contains(DB_VERSION_KEY + subId)) {
2910 log("deletePreferredApn: apn is stored. Deleting it now for subId " + subId);
2911 SharedPreferences.Editor editor = sp.edit();
2912 editor.remove(DB_VERSION_KEY + subId);
2913 for (String key : CARRIERS_UNIQUE_FIELDS) {
2914 editor.remove(key + subId);
2915 }
Amit Mahajan91c5dff2015-10-20 11:13:19 -07002916 editor.apply();
2917 }
2918 }
2919
yuemingwcd80d172018-01-15 14:08:55 +00002920 boolean isCallingFromSystemOrPhoneUid() {
2921 return mInjector.binderGetCallingUid() == Process.SYSTEM_UID ||
2922 mInjector.binderGetCallingUid() == Process.PHONE_UID;
yuemingwc41e5c82017-11-09 13:30:33 +00002923 }
2924
yuemingwcd80d172018-01-15 14:08:55 +00002925 void ensureCallingFromSystemOrPhoneUid(String message) {
2926 if (!isCallingFromSystemOrPhoneUid()) {
yuemingwc41e5c82017-11-09 13:30:33 +00002927 throw new SecurityException(message);
2928 }
2929 }
2930
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002931 @Override
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002932 public synchronized Cursor query(Uri url, String[] projectionIn, String selection,
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002933 String[] selectionArgs, String sort) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002934 if (VDBG) log("query: url=" + url + ", projectionIn=" + projectionIn + ", selection="
calvinpan2b419442018-10-23 15:05:11 +08002935 + selection + "selectionArgs=" + selectionArgs + ", sort=" + sort);
Shishir Agrawalde98fc12016-01-25 14:06:08 -08002936 int subId = SubscriptionManager.getDefaultSubscriptionId();
Wink Savillee84c0a82014-06-09 21:04:39 -07002937 String subIdString;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002938 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
Robert Greenwalt429cf072013-05-21 17:04:09 -07002939 qb.setStrict(true); // a little protection from injection attacks
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002940 qb.setTables(CARRIERS_TABLE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002941
Jordan Liu9a7cea12017-11-16 14:45:07 -08002942 List<String> constraints = new ArrayList<String>();
2943
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002944 int match = s_urlMatcher.match(url);
Hall Liu018f8b12020-02-25 15:58:56 -08002945 checkPermissionCompat(match, projectionIn);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002946 switch (match) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002947 case URL_TELEPHONY_USING_SUBID: {
2948 subIdString = url.getLastPathSegment();
2949 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002950 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002951 } catch (NumberFormatException e) {
2952 loge("NumberFormatException" + e);
2953 return null;
2954 }
2955 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
changbettyfaa1d7a2019-11-26 18:06:24 +08002956 TelephonyManager telephonyManager = getContext()
2957 .getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
2958 constraints.add(NUMERIC + " = '" + telephonyManager.getSimOperator() + "'");
Jordan Liub8fec052018-03-14 10:42:06 -07002959 // TODO b/74213956 turn this back on once insertion includes correct sub id
2960 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002961 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002962 // intentional fall through from above case
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002963 case URL_TELEPHONY: {
yuemingwc41e5c82017-11-09 13:30:33 +00002964 constraints.add(IS_NOT_OWNED_BY_DPC);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002965 break;
2966 }
2967
Wink Savillee84c0a82014-06-09 21:04:39 -07002968 case URL_CURRENT_USING_SUBID: {
2969 subIdString = url.getLastPathSegment();
2970 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002971 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002972 } catch (NumberFormatException e) {
2973 loge("NumberFormatException" + e);
2974 return null;
2975 }
2976 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
Jordan Liub8fec052018-03-14 10:42:06 -07002977 // TODO b/74213956 turn this back on once insertion includes correct sub id
2978 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002979 }
2980 //intentional fall through from above case
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002981 case URL_CURRENT: {
Jordan Liu9a7cea12017-11-16 14:45:07 -08002982 constraints.add("current IS NOT NULL");
yuemingwc41e5c82017-11-09 13:30:33 +00002983 constraints.add(IS_NOT_OWNED_BY_DPC);
Sangcheol Lee4e180882011-04-01 19:24:52 -07002984 // do not ignore the selection since MMS may use it.
2985 //selection = null;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002986 break;
2987 }
2988
2989 case URL_ID: {
Jordan Liu9a7cea12017-11-16 14:45:07 -08002990 constraints.add("_id = " + url.getPathSegments().get(1));
yuemingwc41e5c82017-11-09 13:30:33 +00002991 constraints.add(IS_NOT_OWNED_BY_DPC);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002992 break;
2993 }
2994
Wink Savillee84c0a82014-06-09 21:04:39 -07002995 case URL_PREFERAPN_USING_SUBID:
2996 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: {
2997 subIdString = url.getLastPathSegment();
2998 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002999 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003000 } catch (NumberFormatException e) {
3001 loge("NumberFormatException" + e);
3002 return null;
3003 }
3004 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
Jordan Liub8fec052018-03-14 10:42:06 -07003005 // TODO b/74213956 turn this back on once insertion includes correct sub id
3006 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003007 }
3008 //intentional fall through from above case
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06003009 case URL_PREFERAPN:
3010 case URL_PREFERAPN_NO_UPDATE: {
Jordan Liu9a7cea12017-11-16 14:45:07 -08003011 constraints.add("_id = " + getPreferredApnId(subId, true));
Wink Savillee84c0a82014-06-09 21:04:39 -07003012 break;
3013 }
3014
Jordan Liuc6078b72018-05-01 11:34:21 -07003015 case URL_PREFERAPNSET_USING_SUBID: {
3016 subIdString = url.getLastPathSegment();
3017 try {
3018 subId = Integer.parseInt(subIdString);
3019 } catch (NumberFormatException e) {
3020 loge("NumberFormatException" + e);
3021 return null;
3022 }
3023 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3024 // TODO b/74213956 turn this back on once insertion includes correct sub id
3025 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
3026 }
3027 // intentional fall through from above case
3028 case URL_PREFERAPNSET: {
3029 final int set = getPreferredApnSetId(subId);
Jordan Liu748c8322020-07-15 15:09:12 -07003030 if (set == NO_APN_SET_ID) {
3031 return null;
Jordan Liuc6078b72018-05-01 11:34:21 -07003032 }
Jordan Liu748c8322020-07-15 15:09:12 -07003033 constraints.add(APN_SET_ID + "=" + set);
3034 qb.appendWhere(TextUtils.join(" AND ", constraints));
3035 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs,
3036 sort, subId);
Jordan Liuc6078b72018-05-01 11:34:21 -07003037 }
3038
yuemingwc41e5c82017-11-09 13:30:33 +00003039 case URL_DPC: {
yuemingwcd80d172018-01-15 14:08:55 +00003040 ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID.");
yuemingwc41e5c82017-11-09 13:30:33 +00003041 // DPC query only returns DPC records.
3042 constraints.add(IS_OWNED_BY_DPC);
3043 break;
3044 }
3045
Malcolm Chen09ebf8d2018-12-07 13:45:54 -08003046 case URL_FILTERED_ID:
3047 case URL_FILTERED_USING_SUBID: {
3048 String idString = url.getLastPathSegment();
3049 if (match == URL_FILTERED_ID) {
Josh Hou42049bb2018-12-10 22:22:05 +08003050 constraints.add("_id = " + idString);
Malcolm Chen09ebf8d2018-12-07 13:45:54 -08003051 } else {
3052 try {
3053 subId = Integer.parseInt(idString);
Josh Hou42049bb2018-12-10 22:22:05 +08003054 // TODO b/74213956 turn this back on once insertion includes correct sub id
3055 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
Malcolm Chen09ebf8d2018-12-07 13:45:54 -08003056 } catch (NumberFormatException e) {
3057 loge("NumberFormatException" + e);
3058 return null;
3059 }
3060 }
yuemingwcd80d172018-01-15 14:08:55 +00003061 }
3062 //intentional fall through from above case
yuemingwc41e5c82017-11-09 13:30:33 +00003063 case URL_FILTERED: {
calvinpan2b419442018-10-23 15:05:11 +08003064 if (isManagedApnEnforced()) {
yuemingwc41e5c82017-11-09 13:30:33 +00003065 // If enforced, return DPC records only.
Josh Hou42049bb2018-12-10 22:22:05 +08003066 constraints.add(IS_OWNED_BY_DPC);
yuemingwc41e5c82017-11-09 13:30:33 +00003067 } else {
3068 // Otherwise return non-DPC records only.
Josh Hou42049bb2018-12-10 22:22:05 +08003069 constraints.add(IS_NOT_OWNED_BY_DPC);
yuemingwc41e5c82017-11-09 13:30:33 +00003070 }
Josh Hou42049bb2018-12-10 22:22:05 +08003071 break;
yuemingwc41e5c82017-11-09 13:30:33 +00003072 }
3073
3074 case URL_ENFORCE_MANAGED: {
yuemingwcd80d172018-01-15 14:08:55 +00003075 ensureCallingFromSystemOrPhoneUid(
3076 "URL_ENFORCE_MANAGED called from non SYSTEM_UID.");
yuemingwc41e5c82017-11-09 13:30:33 +00003077 MatrixCursor cursor = new MatrixCursor(new String[]{ENFORCED_KEY});
3078 cursor.addRow(new Object[]{isManagedApnEnforced() ? 1 : 0});
3079 return cursor;
3080 }
3081
Wink Savillee84c0a82014-06-09 21:04:39 -07003082 case URL_SIMINFO: {
3083 qb.setTables(SIMINFO_TABLE);
John Huangb1bc16d2009-03-24 18:26:28 -07003084 break;
3085 }
calvinpanba94b592018-11-01 09:09:30 +08003086 case URL_SIM_APN_LIST_ID: {
3087 subIdString = url.getLastPathSegment();
3088 try {
3089 subId = Integer.parseInt(subIdString);
3090 } catch (NumberFormatException e) {
3091 loge("NumberFormatException" + e);
3092 return null;
3093 }
3094 }
3095 //intentional fall through from above case
3096 case URL_SIM_APN_LIST: {
calvinpanc4bff402018-11-12 15:57:19 +08003097 qb.appendWhere(IS_NOT_OWNED_BY_DPC);
3098 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs,
3099 sort, subId);
calvinpanba94b592018-11-01 09:09:30 +08003100 }
John Huangb1bc16d2009-03-24 18:26:28 -07003101
Josh Hou42049bb2018-12-10 22:22:05 +08003102 case URL_SIM_APN_LIST_FILTERED_ID: {
3103 subIdString = url.getLastPathSegment();
3104 try {
3105 subId = Integer.parseInt(subIdString);
3106 } catch (NumberFormatException e) {
3107 loge("NumberFormatException" + e);
3108 return null;
3109 }
3110 }
3111 //intentional fall through from above case
3112 case URL_SIM_APN_LIST_FILTERED: {
3113 if (isManagedApnEnforced()) {
3114 // If enforced, return DPC records only.
3115 qb.appendWhereStandalone(IS_OWNED_BY_DPC);
3116 } else {
3117 // Otherwise return non-DPC records only.
3118 qb.appendWhereStandalone(IS_NOT_OWNED_BY_DPC);
3119 }
3120 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs,
3121 sort, subId);
3122 }
3123
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003124 default: {
3125 return null;
3126 }
3127 }
3128
Jordan Liu9a7cea12017-11-16 14:45:07 -08003129 // appendWhere doesn't add ANDs so we do it ourselves
3130 if (constraints.size() > 0) {
3131 qb.appendWhere(TextUtils.join(" AND ", constraints));
3132 }
3133
Jordan Liue6f0bce2016-09-21 18:31:43 -07003134 SQLiteDatabase db = getReadableDatabase();
Hyejin Kimcfdb7432013-02-16 00:58:37 +09003135 Cursor ret = null;
3136 try {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003137 // Exclude entries marked deleted
3138 if (CARRIERS_TABLE.equals(qb.getTables())) {
3139 if (TextUtils.isEmpty(selection)) {
3140 selection = "";
3141 } else {
3142 selection += " and ";
3143 }
Amit Mahajan28a5d002016-03-02 11:34:28 -08003144 selection += IS_NOT_USER_DELETED + " and " +
3145 IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " +
3146 IS_NOT_CARRIER_DELETED + " and " +
3147 IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003148 if (VDBG) log("query: selection modified to " + selection);
3149 }
Amit Mahajan7b50f242016-08-14 19:47:49 +00003150 ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09003151 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07003152 loge("got exception when querying: " + e);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09003153 }
3154 if (ret != null)
3155 ret.setNotificationUri(getContext().getContentResolver(), url);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003156 return ret;
3157 }
3158
calvinpanba94b592018-11-01 09:09:30 +08003159 /**
calvinpan33a10a02019-11-04 21:36:12 +08003160 * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} and {Carrier_ID}.
calvinpanba94b592018-11-01 09:09:30 +08003161 *
3162 * There has three steps:
calvinpan33a10a02019-11-04 21:36:12 +08003163 * 1. Query the APN based on { MCC, MNC, MVNO } and if has results jump to step 3, else jump to
3164 * step 2.
3165 * 2. Fallback to query the parent APN that query based on { MCC, MNC }.
3166 * 3. Append the result with the APN that query based on { Carrier_ID }
calvinpanba94b592018-11-01 09:09:30 +08003167 */
3168 private Cursor getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn,
calvinpanc4bff402018-11-12 15:57:19 +08003169 String selection, String[] selectionArgs, String sort, int subId) {
calvinpanba94b592018-11-01 09:09:30 +08003170 Cursor ret;
Nazaninb2a16282020-07-07 15:41:28 -07003171 Context context = getContext();
3172 SubscriptionManager subscriptionManager = (SubscriptionManager) context
3173 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
3174 if (!subscriptionManager.isActiveSubscriptionId(subId)) {
3175 return null;
3176 }
3177
3178 final TelephonyManager tm = ((TelephonyManager) context
calvinpan33a10a02019-11-04 21:36:12 +08003179 .getSystemService(Context.TELEPHONY_SERVICE))
calvinpanba94b592018-11-01 09:09:30 +08003180 .createForSubscriptionId(subId);
3181 SQLiteDatabase db = getReadableDatabase();
calvinpanba94b592018-11-01 09:09:30 +08003182 String mccmnc = tm.getSimOperator();
calvinpan33a10a02019-11-04 21:36:12 +08003183 int carrierId = tm.getSimCarrierId();
calvinpanba94b592018-11-01 09:09:30 +08003184
calvinpan3d8a61e2019-03-12 12:46:42 +08003185 qb.appendWhereStandalone(IS_NOT_USER_DELETED + " and " +
3186 IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " +
3187 IS_NOT_CARRIER_DELETED + " and " +
3188 IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML);
3189
calvinpan33a10a02019-11-04 21:36:12 +08003190 // For query db one time, append all conditions in one selection and separate results after
3191 // the query is completed. IMSI has special match rule, so just query the MCC / MNC and
3192 // filter the MVNO by ourselves
xiangyu.deng233d88c2021-07-16 14:09:40 +08003193 if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
3194 qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' OR " +
calvinpan33a10a02019-11-04 21:36:12 +08003195 CARRIER_ID + " = '" + carrierId + "'");
xiangyu.deng233d88c2021-07-16 14:09:40 +08003196 }
3197 else {
3198 qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "'");
3199 }
calvinpanba94b592018-11-01 09:09:30 +08003200
calvinpanc4bff402018-11-12 15:57:19 +08003201 ret = qb.query(db, null, selection, selectionArgs, null, null, sort);
calvinpan066ce1d2018-12-05 16:21:26 +08003202 if (ret == null) {
3203 loge("query current APN but cursor is null.");
3204 return null;
3205 }
calvinpanba94b592018-11-01 09:09:30 +08003206
3207 if (DBG) log("match current APN size: " + ret.getCount());
3208
xiangyu.deng233d88c2021-07-16 14:09:40 +08003209 IccRecords iccRecords = UiccController.getInstance().getIccRecords(
3210 SubscriptionManager.getPhoneId(subId), UiccController.APP_FAM_3GPP);
3211 if (iccRecords == null) {
3212 loge("iccRecords is null");
3213 return null;
3214 }
3215
calvinpan33a10a02019-11-04 21:36:12 +08003216 String[] columnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
3217 MatrixCursor currentCursor = new MatrixCursor(columnNames);
3218 MatrixCursor parentCursor = new MatrixCursor(columnNames);
3219 MatrixCursor carrierIdCursor = new MatrixCursor(columnNames);
calvinpanba94b592018-11-01 09:09:30 +08003220
calvinpanba94b592018-11-01 09:09:30 +08003221 int numericIndex = ret.getColumnIndex(NUMERIC);
3222 int mvnoIndex = ret.getColumnIndex(MVNO_TYPE);
3223 int mvnoDataIndex = ret.getColumnIndex(MVNO_MATCH_DATA);
calvinpan33a10a02019-11-04 21:36:12 +08003224 int carrierIdIndex = ret.getColumnIndex(CARRIER_ID);
calvinpanba94b592018-11-01 09:09:30 +08003225
calvinpan0fb0efc2020-01-06 16:17:40 +08003226 // Separate the result into MatrixCursor
calvinpanba94b592018-11-01 09:09:30 +08003227 while (ret.moveToNext()) {
3228 List<String> data = new ArrayList<>();
calvinpan33a10a02019-11-04 21:36:12 +08003229 for (String column : columnNames) {
calvinpanba94b592018-11-01 09:09:30 +08003230 data.add(ret.getString(ret.getColumnIndex(column)));
3231 }
3232
calvinpan0fb0efc2020-01-06 16:17:40 +08003233 boolean isMVNOAPN = !TextUtils.isEmpty(ret.getString(numericIndex))
xiangyu.deng233d88c2021-07-16 14:09:40 +08003234 && ApnSettingUtils.mvnoMatches(iccRecords,
3235 ret.getString(mvnoIndex), ret.getString(mvnoDataIndex), subId);
calvinpan0fb0efc2020-01-06 16:17:40 +08003236 boolean isMNOAPN = !TextUtils.isEmpty(ret.getString(numericIndex))
3237 && ret.getString(numericIndex).equals(mccmnc)
3238 && TextUtils.isEmpty(ret.getString(mvnoIndex));
3239 boolean isCarrierIdAPN = !TextUtils.isEmpty(ret.getString(carrierIdIndex))
3240 && ret.getString(carrierIdIndex).equals(String.valueOf(carrierId))
3241 && carrierId != TelephonyManager.UNKNOWN_CARRIER_ID;
3242
3243 if (isMVNOAPN) {
calvinpan33a10a02019-11-04 21:36:12 +08003244 // 1. The APN that query based on legacy SIM MCC/MCC and MVNO
calvinpanba94b592018-11-01 09:09:30 +08003245 currentCursor.addRow(data);
calvinpan0fb0efc2020-01-06 16:17:40 +08003246 } else if (isMNOAPN) {
calvinpan33a10a02019-11-04 21:36:12 +08003247 // 2. The APN that query based on SIM MCC/MNC
calvinpanba94b592018-11-01 09:09:30 +08003248 parentCursor.addRow(data);
calvinpan0fb0efc2020-01-06 16:17:40 +08003249 } else if (isCarrierIdAPN) {
calvinpan33a10a02019-11-04 21:36:12 +08003250 // The APN that query based on carrier Id (not include the MVNO or MNO APN)
3251 carrierIdCursor.addRow(data);
calvinpanba94b592018-11-01 09:09:30 +08003252 }
3253 }
calvinpan066ce1d2018-12-05 16:21:26 +08003254 ret.close();
calvinpanba94b592018-11-01 09:09:30 +08003255
calvinpan33a10a02019-11-04 21:36:12 +08003256 MatrixCursor result;
calvinpanba94b592018-11-01 09:09:30 +08003257 if (currentCursor.getCount() > 0) {
calvinpan3d8a61e2019-03-12 12:46:42 +08003258 if (DBG) log("match MVNO APN: " + currentCursor.getCount());
calvinpan33a10a02019-11-04 21:36:12 +08003259 result = currentCursor;
calvinpanba94b592018-11-01 09:09:30 +08003260 } else if (parentCursor.getCount() > 0) {
calvinpan3d8a61e2019-03-12 12:46:42 +08003261 if (DBG) log("match MNO APN: " + parentCursor.getCount());
calvinpan33a10a02019-11-04 21:36:12 +08003262 result = parentCursor;
calvinpanba94b592018-11-01 09:09:30 +08003263 } else {
calvinpan33a10a02019-11-04 21:36:12 +08003264 if (DBG) log("can't find the MVNO and MNO APN");
3265 result = new MatrixCursor(columnNames);
3266 }
3267
3268 if (DBG) log("match carrier id APN: " + carrierIdCursor.getCount());
3269 appendCursorData(result, carrierIdCursor);
3270 return result;
3271 }
3272
3273 private static void appendCursorData(@NonNull MatrixCursor from, @NonNull MatrixCursor to) {
3274 while (to.moveToNext()) {
3275 List<Object> data = new ArrayList<>();
3276 for (String column : to.getColumnNames()) {
3277 int index = to.getColumnIndex(column);
3278 switch (to.getType(index)) {
calvinpan33a10a02019-11-04 21:36:12 +08003279 case Cursor.FIELD_TYPE_INTEGER:
3280 data.add(to.getInt(index));
3281 break;
3282 case Cursor.FIELD_TYPE_FLOAT:
3283 data.add(to.getFloat(index));
3284 break;
3285 case Cursor.FIELD_TYPE_BLOB:
3286 data.add(to.getBlob(index));
3287 break;
3288 case Cursor.FIELD_TYPE_STRING:
calvinpan04ece1e2020-01-06 16:17:40 +08003289 case Cursor.FIELD_TYPE_NULL:
calvinpan33a10a02019-11-04 21:36:12 +08003290 data.add(to.getString(index));
3291 break;
3292 }
3293 }
3294 from.addRow(data);
calvinpanba94b592018-11-01 09:09:30 +08003295 }
3296 }
3297
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003298 @Override
3299 public String getType(Uri url)
3300 {
3301 switch (s_urlMatcher.match(url)) {
3302 case URL_TELEPHONY:
Wink Savillee84c0a82014-06-09 21:04:39 -07003303 case URL_TELEPHONY_USING_SUBID:
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003304 return "vnd.android.cursor.dir/telephony-carrier";
3305
3306 case URL_ID:
yuemingwcd80d172018-01-15 14:08:55 +00003307 case URL_FILTERED_ID:
Malcolm Chen09ebf8d2018-12-07 13:45:54 -08003308 case URL_FILTERED_USING_SUBID:
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003309 return "vnd.android.cursor.item/telephony-carrier";
3310
Wink Savillee84c0a82014-06-09 21:04:39 -07003311 case URL_PREFERAPN_USING_SUBID:
3312 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
John Huangb1bc16d2009-03-24 18:26:28 -07003313 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06003314 case URL_PREFERAPN_NO_UPDATE:
Jordan Liuc6078b72018-05-01 11:34:21 -07003315 case URL_PREFERAPNSET:
3316 case URL_PREFERAPNSET_USING_SUBID:
John Huangb1bc16d2009-03-24 18:26:28 -07003317 return "vnd.android.cursor.item/telephony-carrier";
3318
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003319 default:
3320 throw new IllegalArgumentException("Unknown URL " + url);
3321 }
3322 }
3323
Jordan Liu3de76f82017-05-15 15:21:01 -07003324 /**
3325 * Insert an array of ContentValues and call notifyChange at the end.
3326 */
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003327 @Override
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003328 public synchronized int bulkInsert(Uri url, ContentValues[] values) {
Jordan Liu3de76f82017-05-15 15:21:01 -07003329 return unsynchronizedBulkInsert(url, values);
3330 }
3331
3332 /**
3333 * Do a bulk insert while inside a synchronized function. This is typically not safe and should
3334 * only be done when you are sure there will be no conflict.
3335 */
3336 private int unsynchronizedBulkInsert(Uri url, ContentValues[] values) {
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003337 int count = 0;
3338 boolean notify = false;
3339 for (ContentValues value : values) {
3340 Pair<Uri, Boolean> rowAndNotify = insertSingleRow(url, value);
3341 if (rowAndNotify.first != null) {
3342 count++;
3343 }
3344 if (rowAndNotify.second == true) {
3345 notify = true;
3346 }
3347 }
3348 if (notify) {
3349 getContext().getContentResolver().notifyChange(CONTENT_URI, null,
3350 true, UserHandle.USER_ALL);
3351 }
3352 return count;
3353 }
3354
3355 @Override
3356 public synchronized Uri insert(Uri url, ContentValues initialValues) {
3357 Pair<Uri, Boolean> rowAndNotify = insertSingleRow(url, initialValues);
3358 if (rowAndNotify.second) {
3359 getContext().getContentResolver().notifyChange(CONTENT_URI, null,
3360 true, UserHandle.USER_ALL);
3361 }
3362 return rowAndNotify.first;
3363 }
3364
yuemingwc41e5c82017-11-09 13:30:33 +00003365 /**
3366 * Internal insert function to prevent code duplication for URL_TELEPHONY and URL_DPC.
3367 *
3368 * @param values the value that caller wants to insert
3369 * @return a pair in which the first element refers to the Uri for the row inserted, the second
3370 * element refers to whether sends out nofitication.
3371 */
3372 private Pair<Uri, Boolean> insertRowWithValue(ContentValues values) {
3373 Uri result = null;
3374 boolean notify = false;
3375 SQLiteDatabase db = getWritableDatabase();
3376
3377 try {
Jordan Liuc655dec2018-02-13 11:16:53 -08003378 // Abort on conflict of unique fields and attempt merge
yuemingwc41e5c82017-11-09 13:30:33 +00003379 long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
3380 SQLiteDatabase.CONFLICT_ABORT);
3381 if (rowID >= 0) {
3382 result = ContentUris.withAppendedId(CONTENT_URI, rowID);
3383 notify = true;
3384 }
3385 if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
3386 } catch (SQLException e) {
3387 log("insert: exception " + e);
3388 // Insertion failed which could be due to a conflict. Check if that is the case
3389 // and merge the entries
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07003390 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values);
yuemingwc41e5c82017-11-09 13:30:33 +00003391 if (oldRow != null) {
3392 ContentValues mergedValues = new ContentValues();
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07003393 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
yuemingwc41e5c82017-11-09 13:30:33 +00003394 mergedValues, false, getContext());
3395 oldRow.close();
3396 notify = true;
3397 }
3398 }
3399 return Pair.create(result, notify);
3400 }
3401
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003402 private Pair<Uri, Boolean> insertSingleRow(Uri url, ContentValues initialValues) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003403 Uri result = null;
Shishir Agrawalde98fc12016-01-25 14:06:08 -08003404 int subId = SubscriptionManager.getDefaultSubscriptionId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003405
3406 checkPermission();
Cassiea58ce712017-12-06 16:21:50 -08003407 syncBearerBitmaskAndNetworkTypeBitmask(initialValues);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003408
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003409 boolean notify = false;
Jordan Liue6f0bce2016-09-21 18:31:43 -07003410 SQLiteDatabase db = getWritableDatabase();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003411 int match = s_urlMatcher.match(url);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003412 switch (match)
3413 {
Wink Savillee84c0a82014-06-09 21:04:39 -07003414 case URL_TELEPHONY_USING_SUBID:
3415 {
3416 String subIdString = url.getLastPathSegment();
3417 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003418 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003419 } catch (NumberFormatException e) {
3420 loge("NumberFormatException" + e);
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003421 return Pair.create(result, notify);
Wink Savillee84c0a82014-06-09 21:04:39 -07003422 }
3423 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3424 }
3425 //intentional fall through from above case
3426
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003427 case URL_TELEPHONY:
3428 {
3429 ContentValues values;
3430 if (initialValues != null) {
3431 values = new ContentValues(initialValues);
3432 } else {
3433 values = new ContentValues();
3434 }
3435
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07003436 values = setDefaultValue(values);
chen xu3e303942018-11-28 00:23:01 -08003437 if (!values.containsKey(EDITED_STATUS)) {
3438 values.put(EDITED_STATUS, CARRIER_EDITED);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07003439 }
yuemingwc4d40a72017-11-08 14:14:37 +00003440 // Owned_by should be others if inserted via general uri.
3441 values.put(OWNED_BY, OWNED_BY_OTHERS);
3442
yuemingwc41e5c82017-11-09 13:30:33 +00003443 Pair<Uri, Boolean> ret = insertRowWithValue(values);
3444 result = ret.first;
3445 notify = ret.second;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003446 break;
3447 }
3448
Wink Savillee84c0a82014-06-09 21:04:39 -07003449 case URL_CURRENT_USING_SUBID:
3450 {
3451 String subIdString = url.getLastPathSegment();
3452 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003453 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003454 } catch (NumberFormatException e) {
3455 loge("NumberFormatException" + e);
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003456 return Pair.create(result, notify);
Wink Savillee84c0a82014-06-09 21:04:39 -07003457 }
3458 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3459 // FIXME use subId in the query
3460 }
3461 //intentional fall through from above case
3462
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003463 case URL_CURRENT:
3464 {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003465 // zero out the previous operator
Amit Mahajan28a5d002016-03-02 11:34:28 -08003466 db.update(CARRIERS_TABLE, s_currentNullMap, CURRENT + "!=0", null);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003467
Amit Mahajan28a5d002016-03-02 11:34:28 -08003468 String numeric = initialValues.getAsString(NUMERIC);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003469 int updated = db.update(CARRIERS_TABLE, s_currentSetMap,
Amit Mahajan28a5d002016-03-02 11:34:28 -08003470 NUMERIC + " = '" + numeric + "'", null);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003471
3472 if (updated > 0)
3473 {
Wink Savillee84c0a82014-06-09 21:04:39 -07003474 if (VDBG) log("Setting numeric '" + numeric + "' to be the current operator");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003475 }
3476 else
3477 {
Wink Savillee84c0a82014-06-09 21:04:39 -07003478 loge("Failed setting numeric '" + numeric + "' to the current operator");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003479 }
3480 break;
3481 }
John Huangb1bc16d2009-03-24 18:26:28 -07003482
Wink Savillee84c0a82014-06-09 21:04:39 -07003483 case URL_PREFERAPN_USING_SUBID:
3484 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
3485 {
3486 String subIdString = url.getLastPathSegment();
3487 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003488 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003489 } catch (NumberFormatException e) {
3490 loge("NumberFormatException" + e);
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003491 return Pair.create(result, notify);
Wink Savillee84c0a82014-06-09 21:04:39 -07003492 }
3493 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3494 }
3495 //intentional fall through from above case
3496
John Huangb1bc16d2009-03-24 18:26:28 -07003497 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06003498 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07003499 {
3500 if (initialValues != null) {
3501 if(initialValues.containsKey(COLUMN_APN_ID)) {
Amit Mahajanbf7144e2017-08-29 11:39:48 -07003502 setPreferredApnId(initialValues.getAsLong(COLUMN_APN_ID), subId, true);
John Huangb1bc16d2009-03-24 18:26:28 -07003503 }
3504 }
3505 break;
3506 }
Wink Savillee84c0a82014-06-09 21:04:39 -07003507
yuemingwc41e5c82017-11-09 13:30:33 +00003508 case URL_DPC: {
yuemingwcd80d172018-01-15 14:08:55 +00003509 ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID.");
yuemingwc41e5c82017-11-09 13:30:33 +00003510
3511 ContentValues values;
3512 if (initialValues != null) {
3513 values = new ContentValues(initialValues);
3514 } else {
3515 values = new ContentValues();
3516 }
3517
3518 // Owned_by should be DPC if inserted via URL_DPC.
3519 values.put(OWNED_BY, OWNED_BY_DPC);
3520 // DPC records should not be user editable.
3521 values.put(USER_EDITABLE, false);
yuemingwda96ee62018-02-21 14:58:04 +00003522
3523 final long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
3524 SQLiteDatabase.CONFLICT_IGNORE);
3525 if (rowID >= 0) {
3526 result = ContentUris.withAppendedId(CONTENT_URI, rowID);
3527 notify = true;
3528 }
3529 if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
3530
yuemingwc41e5c82017-11-09 13:30:33 +00003531 break;
3532 }
3533
Wink Savillee84c0a82014-06-09 21:04:39 -07003534 case URL_SIMINFO: {
3535 long id = db.insert(SIMINFO_TABLE, null, initialValues);
changbetty004eceb2019-12-02 15:53:49 +08003536 result = ContentUris.withAppendedId(Telephony.SimInfo.CONTENT_URI, id);
Wink Savillee84c0a82014-06-09 21:04:39 -07003537 break;
3538 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003539 }
3540
Jordan Liu6cf9bda2017-05-19 11:42:55 -07003541 return Pair.create(result, notify);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003542 }
3543
3544 @Override
yuemingwc41e5c82017-11-09 13:30:33 +00003545 public synchronized int delete(Uri url, String where, String[] whereArgs) {
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06003546 int count = 0;
Shishir Agrawalde98fc12016-01-25 14:06:08 -08003547 int subId = SubscriptionManager.getDefaultSubscriptionId();
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003548 String userOrCarrierEdited = ") and (" +
Amit Mahajan7005be82017-04-26 10:35:18 -07003549 IS_USER_EDITED + " or " +
3550 IS_CARRIER_EDITED + ")";
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003551 String notUserOrCarrierEdited = ") and (" +
Amit Mahajan7005be82017-04-26 10:35:18 -07003552 IS_NOT_USER_EDITED + " and " +
3553 IS_NOT_CARRIER_EDITED + ")";
3554 String unedited = ") and " + IS_UNEDITED;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003555 ContentValues cv = new ContentValues();
chen xu3e303942018-11-28 00:23:01 -08003556 cv.put(EDITED_STATUS, USER_DELETED);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003557
3558 checkPermission();
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07003559
Jordan Liue6f0bce2016-09-21 18:31:43 -07003560 SQLiteDatabase db = getWritableDatabase();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003561 int match = s_urlMatcher.match(url);
3562 switch (match)
3563 {
Amit Mahajan7005be82017-04-26 10:35:18 -07003564 case URL_DELETE:
3565 {
Amit Mahajanbf7144e2017-08-29 11:39:48 -07003566 // Delete preferred APN for all subIds
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07003567 deletePreferredApnId(getContext());
Amit Mahajan7005be82017-04-26 10:35:18 -07003568 // Delete unedited entries
yuemingwc4d40a72017-11-08 14:14:37 +00003569 count = db.delete(CARRIERS_TABLE, "(" + where + unedited + " and " +
yuemingwc41e5c82017-11-09 13:30:33 +00003570 IS_NOT_OWNED_BY_DPC, whereArgs);
Amit Mahajan7005be82017-04-26 10:35:18 -07003571 break;
3572 }
3573
Wink Savillee84c0a82014-06-09 21:04:39 -07003574 case URL_TELEPHONY_USING_SUBID:
3575 {
3576 String subIdString = url.getLastPathSegment();
3577 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003578 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003579 } catch (NumberFormatException e) {
3580 loge("NumberFormatException" + e);
3581 throw new IllegalArgumentException("Invalid subId " + url);
3582 }
3583 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3584 // FIXME use subId in query
3585 }
3586 //intentional fall through from above case
3587
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003588 case URL_TELEPHONY:
3589 {
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003590 // Delete user/carrier edited entries
yuemingwc4d40a72017-11-08 14:14:37 +00003591 count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited
yuemingwc41e5c82017-11-09 13:30:33 +00003592 + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003593 // Otherwise mark as user deleted instead of deleting
yuemingwc4d40a72017-11-08 14:14:37 +00003594 count += db.update(CARRIERS_TABLE, cv, "(" + where +
yuemingwc41e5c82017-11-09 13:30:33 +00003595 notUserOrCarrierEdited + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003596 break;
3597 }
3598
Wink Savillee84c0a82014-06-09 21:04:39 -07003599 case URL_CURRENT_USING_SUBID: {
3600 String subIdString = url.getLastPathSegment();
3601 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003602 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003603 } catch (NumberFormatException e) {
3604 loge("NumberFormatException" + e);
3605 throw new IllegalArgumentException("Invalid subId " + url);
3606 }
3607 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3608 // FIXME use subId in query
3609 }
3610 //intentional fall through from above case
3611
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003612 case URL_CURRENT:
3613 {
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003614 // Delete user/carrier edited entries
yuemingwc4d40a72017-11-08 14:14:37 +00003615 count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited
yuemingwc41e5c82017-11-09 13:30:33 +00003616 + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003617 // Otherwise mark as user deleted instead of deleting
yuemingwc4d40a72017-11-08 14:14:37 +00003618 count += db.update(CARRIERS_TABLE, cv, "(" + where +
yuemingwc41e5c82017-11-09 13:30:33 +00003619 notUserOrCarrierEdited + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003620 break;
3621 }
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07003622
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003623 case URL_ID:
3624 {
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003625 // Delete user/carrier edited entries
3626 count = db.delete(CARRIERS_TABLE,
yuemingwc4d40a72017-11-08 14:14:37 +00003627 "(" + _ID + "=?" + userOrCarrierEdited +
yuemingwc41e5c82017-11-09 13:30:33 +00003628 " and " + IS_NOT_OWNED_BY_DPC,
Amit Mahajan7b8040a2015-06-15 18:11:01 -07003629 new String[] { url.getLastPathSegment() });
3630 // Otherwise mark as user deleted instead of deleting
3631 count += db.update(CARRIERS_TABLE, cv,
yuemingwc4d40a72017-11-08 14:14:37 +00003632 "(" + _ID + "=?" + notUserOrCarrierEdited +
yuemingwc41e5c82017-11-09 13:30:33 +00003633 " and " + IS_NOT_OWNED_BY_DPC,
Amit Mahajan28a5d002016-03-02 11:34:28 -08003634 new String[]{url.getLastPathSegment() });
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003635 break;
3636 }
3637
Wink Savillee84c0a82014-06-09 21:04:39 -07003638 case URL_RESTOREAPN_USING_SUBID: {
3639 String subIdString = url.getLastPathSegment();
3640 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003641 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003642 } catch (NumberFormatException e) {
3643 loge("NumberFormatException" + e);
3644 throw new IllegalArgumentException("Invalid subId " + url);
3645 }
3646 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
Wink Savillee84c0a82014-06-09 21:04:39 -07003647 }
Jordan Liuc2b52472018-03-05 15:44:01 -08003648 // intentional fall through from above case
3649
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003650 case URL_RESTOREAPN: {
3651 count = 1;
Wink Savillee84c0a82014-06-09 21:04:39 -07003652 restoreDefaultAPN(subId);
Jordan Liuc2b52472018-03-05 15:44:01 -08003653 getContext().getContentResolver().notifyChange(
3654 Uri.withAppendedPath(CONTENT_URI, "restore/subId/" + subId), null,
3655 true, UserHandle.USER_ALL);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003656 break;
3657 }
3658
Wink Savillee84c0a82014-06-09 21:04:39 -07003659 case URL_PREFERAPN_USING_SUBID:
3660 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: {
3661 String subIdString = url.getLastPathSegment();
3662 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003663 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003664 } catch (NumberFormatException e) {
3665 loge("NumberFormatException" + e);
3666 throw new IllegalArgumentException("Invalid subId " + url);
3667 }
3668 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3669 }
3670 //intentional fall through from above case
3671
John Huangb1bc16d2009-03-24 18:26:28 -07003672 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06003673 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07003674 {
Amit Mahajanbf7144e2017-08-29 11:39:48 -07003675 setPreferredApnId((long)INVALID_APN_ID, subId, true);
Wink Savillee84c0a82014-06-09 21:04:39 -07003676 if ((match == URL_PREFERAPN) || (match == URL_PREFERAPN_USING_SUBID)) count = 1;
3677 break;
3678 }
3679
yuemingwc41e5c82017-11-09 13:30:33 +00003680 case URL_DPC_ID: {
yuemingwcd80d172018-01-15 14:08:55 +00003681 ensureCallingFromSystemOrPhoneUid("URL_DPC_ID called from non SYSTEM_UID.");
yuemingwc41e5c82017-11-09 13:30:33 +00003682
3683 // Only delete if owned by DPC.
3684 count = db.delete(CARRIERS_TABLE, "(" + _ID + "=?)" + " and " + IS_OWNED_BY_DPC,
3685 new String[] { url.getLastPathSegment() });
3686 break;
3687 }
3688
Wink Savillee84c0a82014-06-09 21:04:39 -07003689 case URL_SIMINFO: {
3690 count = db.delete(SIMINFO_TABLE, where, whereArgs);
John Huangb1bc16d2009-03-24 18:26:28 -07003691 break;
3692 }
3693
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003694 case URL_UPDATE_DB: {
3695 updateApnDb();
3696 count = 1;
3697 break;
3698 }
3699
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003700 default: {
3701 throw new UnsupportedOperationException("Cannot delete that URL: " + url);
3702 }
3703 }
3704
3705 if (count > 0) {
Amit Mahajan28a5d002016-03-02 11:34:28 -08003706 getContext().getContentResolver().notifyChange(CONTENT_URI, null,
Amith Yamasani887288c2014-11-06 09:01:20 -08003707 true, UserHandle.USER_ALL);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003708 }
3709
3710 return count;
3711 }
3712
3713 @Override
Amit Mahajanbc1edc22015-04-09 13:53:33 -07003714 public synchronized int update(Uri url, ContentValues values, String where, String[] whereArgs)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003715 {
John Huangb1bc16d2009-03-24 18:26:28 -07003716 int count = 0;
Wink Savillee84c0a82014-06-09 21:04:39 -07003717 int uriType = URL_UNKNOWN;
Shishir Agrawalde98fc12016-01-25 14:06:08 -08003718 int subId = SubscriptionManager.getDefaultSubscriptionId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003719
3720 checkPermission();
Cassiea58ce712017-12-06 16:21:50 -08003721 syncBearerBitmaskAndNetworkTypeBitmask(values);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003722
Jordan Liue6f0bce2016-09-21 18:31:43 -07003723 SQLiteDatabase db = getWritableDatabase();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003724 int match = s_urlMatcher.match(url);
3725 switch (match)
3726 {
Wink Savillee84c0a82014-06-09 21:04:39 -07003727 case URL_TELEPHONY_USING_SUBID:
3728 {
3729 String subIdString = url.getLastPathSegment();
3730 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003731 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003732 } catch (NumberFormatException e) {
3733 loge("NumberFormatException" + e);
3734 throw new IllegalArgumentException("Invalid subId " + url);
3735 }
3736 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3737 //FIXME use subId in the query
3738 }
3739 //intentional fall through from above case
3740
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003741 case URL_TELEPHONY:
3742 {
chen xu3e303942018-11-28 00:23:01 -08003743 if (!values.containsKey(EDITED_STATUS)) {
3744 values.put(EDITED_STATUS, CARRIER_EDITED);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07003745 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003746
Amit Mahajanb80f7332015-04-16 10:02:52 -07003747 // Replace on conflict so that if same APN is present in db with edited
Amit Mahajan28a5d002016-03-02 11:34:28 -08003748 // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
Amit Mahajanb80f7332015-04-16 10:02:52 -07003749 // edited USER/CARRIER_EDITED
yuemingwc4d40a72017-11-08 14:14:37 +00003750 count = db.updateWithOnConflict(CARRIERS_TABLE, values, where +
yuemingwc41e5c82017-11-09 13:30:33 +00003751 " and " + IS_NOT_OWNED_BY_DPC, whereArgs,
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08003752 SQLiteDatabase.CONFLICT_REPLACE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003753 break;
3754 }
3755
Wink Savillee84c0a82014-06-09 21:04:39 -07003756 case URL_CURRENT_USING_SUBID:
3757 {
3758 String subIdString = url.getLastPathSegment();
3759 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003760 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003761 } catch (NumberFormatException e) {
3762 loge("NumberFormatException" + e);
3763 throw new IllegalArgumentException("Invalid subId " + url);
3764 }
3765 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3766 //FIXME use subId in the query
3767 }
3768 //intentional fall through from above case
3769
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003770 case URL_CURRENT:
3771 {
chen xu3e303942018-11-28 00:23:01 -08003772 if (!values.containsKey(EDITED_STATUS)) {
3773 values.put(EDITED_STATUS, CARRIER_EDITED);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07003774 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07003775 // Replace on conflict so that if same APN is present in db with edited
Amit Mahajan28a5d002016-03-02 11:34:28 -08003776 // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
Amit Mahajanb80f7332015-04-16 10:02:52 -07003777 // edited USER/CARRIER_EDITED
yuemingwc4d40a72017-11-08 14:14:37 +00003778 count = db.updateWithOnConflict(CARRIERS_TABLE, values, where +
yuemingwc41e5c82017-11-09 13:30:33 +00003779 " and " + IS_NOT_OWNED_BY_DPC,
yuemingwc4d40a72017-11-08 14:14:37 +00003780 whereArgs, SQLiteDatabase.CONFLICT_REPLACE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003781 break;
3782 }
3783
3784 case URL_ID:
3785 {
Jordan Liu18d0d932018-03-28 18:33:37 -07003786 String rowID = url.getLastPathSegment();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003787 if (where != null || whereArgs != null) {
3788 throw new UnsupportedOperationException(
3789 "Cannot update URL " + url + " with a where clause");
3790 }
chen xu3e303942018-11-28 00:23:01 -08003791 if (!values.containsKey(EDITED_STATUS)) {
3792 values.put(EDITED_STATUS, CARRIER_EDITED);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07003793 }
yuemingwc41e5c82017-11-09 13:30:33 +00003794
yuemingwe0101b82017-12-13 21:49:09 +00003795 try {
Jordan Liu18d0d932018-03-28 18:33:37 -07003796 count = db.updateWithOnConflict(CARRIERS_TABLE, values, _ID + "=?" + " and " +
3797 IS_NOT_OWNED_BY_DPC, new String[] { rowID },
3798 SQLiteDatabase.CONFLICT_ABORT);
yuemingwe0101b82017-12-13 21:49:09 +00003799 } catch (SQLException e) {
3800 // Update failed which could be due to a conflict. Check if that is
3801 // the case and merge the entries
Jordan Liu18d0d932018-03-28 18:33:37 -07003802 log("update: exception " + e);
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07003803 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values);
yuemingwe0101b82017-12-13 21:49:09 +00003804 if (oldRow != null) {
3805 ContentValues mergedValues = new ContentValues();
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07003806 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
yuemingwe0101b82017-12-13 21:49:09 +00003807 mergedValues, false, getContext());
3808 oldRow.close();
Jordan Liu18d0d932018-03-28 18:33:37 -07003809 db.delete(CARRIERS_TABLE, _ID + "=?" + " and " + IS_NOT_OWNED_BY_DPC,
3810 new String[] { rowID });
yuemingwe0101b82017-12-13 21:49:09 +00003811 }
3812 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003813 break;
3814 }
3815
Wink Savillee84c0a82014-06-09 21:04:39 -07003816 case URL_PREFERAPN_USING_SUBID:
3817 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
3818 {
3819 String subIdString = url.getLastPathSegment();
3820 try {
Wink Saville830a40f2014-10-23 10:16:47 -07003821 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07003822 } catch (NumberFormatException e) {
3823 loge("NumberFormatException" + e);
3824 throw new IllegalArgumentException("Invalid subId " + url);
3825 }
3826 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3827 }
3828
John Huangb1bc16d2009-03-24 18:26:28 -07003829 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06003830 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07003831 {
3832 if (values != null) {
3833 if (values.containsKey(COLUMN_APN_ID)) {
Amit Mahajanbf7144e2017-08-29 11:39:48 -07003834 setPreferredApnId(values.getAsLong(COLUMN_APN_ID), subId, true);
Wink Savillee84c0a82014-06-09 21:04:39 -07003835 if ((match == URL_PREFERAPN) ||
3836 (match == URL_PREFERAPN_USING_SUBID)) {
3837 count = 1;
3838 }
John Huangb1bc16d2009-03-24 18:26:28 -07003839 }
3840 }
3841 break;
3842 }
3843
yuemingwc41e5c82017-11-09 13:30:33 +00003844 case URL_DPC_ID:
3845 {
yuemingwcd80d172018-01-15 14:08:55 +00003846 ensureCallingFromSystemOrPhoneUid("URL_DPC_ID called from non SYSTEM_UID.");
yuemingwc41e5c82017-11-09 13:30:33 +00003847
3848 if (where != null || whereArgs != null) {
3849 throw new UnsupportedOperationException(
3850 "Cannot update URL " + url + " with a where clause");
3851 }
3852 count = db.updateWithOnConflict(CARRIERS_TABLE, values,
3853 _ID + "=?" + " and " + IS_OWNED_BY_DPC,
yuemingwda96ee62018-02-21 14:58:04 +00003854 new String[] { url.getLastPathSegment() }, SQLiteDatabase.CONFLICT_IGNORE);
yuemingwc41e5c82017-11-09 13:30:33 +00003855 break;
3856 }
3857
3858 case URL_ENFORCE_MANAGED: {
yuemingwcd80d172018-01-15 14:08:55 +00003859 ensureCallingFromSystemOrPhoneUid(
3860 "URL_ENFORCE_MANAGED called from non SYSTEM_UID.");
yuemingwc41e5c82017-11-09 13:30:33 +00003861 if (values != null) {
3862 if (values.containsKey(ENFORCED_KEY)) {
3863 setManagedApnEnforced(values.getAsBoolean(ENFORCED_KEY));
3864 count = 1;
3865 }
3866 }
3867 break;
3868 }
3869
chen xu195e2ec2018-10-02 18:42:41 -07003870 case URL_SIMINFO_USING_SUBID:
3871 String subIdString = url.getLastPathSegment();
3872 try {
3873 subId = Integer.parseInt(subIdString);
3874 } catch (NumberFormatException e) {
3875 loge("NumberFormatException" + e);
3876 throw new IllegalArgumentException("Invalid subId " + url);
3877 }
3878 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
3879 if (where != null || whereArgs != null) {
3880 throw new UnsupportedOperationException(
3881 "Cannot update URL " + url + " with a where clause");
3882 }
3883 count = db.update(SIMINFO_TABLE, values, _ID + "=?",
3884 new String[] { subIdString});
3885 uriType = URL_SIMINFO_USING_SUBID;
3886 break;
3887
Wink Savillee84c0a82014-06-09 21:04:39 -07003888 case URL_SIMINFO: {
3889 count = db.update(SIMINFO_TABLE, values, where, whereArgs);
3890 uriType = URL_SIMINFO;
3891 break;
3892 }
3893
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003894 default: {
3895 throw new UnsupportedOperationException("Cannot update that URL: " + url);
3896 }
3897 }
3898
3899 if (count > 0) {
chen xu1f8d5892018-11-01 00:13:42 -07003900 boolean usingSubId = false;
Wink Savillee84c0a82014-06-09 21:04:39 -07003901 switch (uriType) {
chen xu195e2ec2018-10-02 18:42:41 -07003902 case URL_SIMINFO_USING_SUBID:
chen xu1f8d5892018-11-01 00:13:42 -07003903 usingSubId = true;
chen xu195e2ec2018-10-02 18:42:41 -07003904 // intentional fall through from above case
Wink Savillee84c0a82014-06-09 21:04:39 -07003905 case URL_SIMINFO:
chen xu4590bd72018-10-18 14:07:02 -07003906 // skip notifying descendant URLs to avoid unneccessary wake up.
3907 // If not set, any change to SIMINFO will notify observers which listens to
3908 // specific field of SIMINFO.
Wink Savillee84c0a82014-06-09 21:04:39 -07003909 getContext().getContentResolver().notifyChange(
changbetty004eceb2019-12-02 15:53:49 +08003910 Telephony.SimInfo.CONTENT_URI, null,
chen xu4590bd72018-10-18 14:07:02 -07003911 ContentResolver.NOTIFY_SYNC_TO_NETWORK
3912 | ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS,
3913 UserHandle.USER_ALL);
chen xu195e2ec2018-10-02 18:42:41 -07003914 // notify observers on specific user settings changes.
Peter Wangb8e281d2020-01-31 18:50:00 -08003915 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED)) {
chen xu195e2ec2018-10-02 18:42:41 -07003916 getContext().getContentResolver().notifyChange(
chen xu1f8d5892018-11-01 00:13:42 -07003917 getNotifyContentUri(SubscriptionManager.WFC_ENABLED_CONTENT_URI,
3918 usingSubId, subId), null, true, UserHandle.USER_ALL);
chen xu195e2ec2018-10-02 18:42:41 -07003919 }
Peter Wangb8e281d2020-01-31 18:50:00 -08003920 if (values.containsKey(Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED)) {
chen xu195e2ec2018-10-02 18:42:41 -07003921 getContext().getContentResolver().notifyChange(
chen xu1f8d5892018-11-01 00:13:42 -07003922 getNotifyContentUri(SubscriptionManager
3923 .ADVANCED_CALLING_ENABLED_CONTENT_URI,
3924 usingSubId, subId), null, true, UserHandle.USER_ALL);
3925 }
Peter Wangb8e281d2020-01-31 18:50:00 -08003926 if (values.containsKey(Telephony.SimInfo.COLUMN_VT_IMS_ENABLED)) {
chen xu1f8d5892018-11-01 00:13:42 -07003927 getContext().getContentResolver().notifyChange(
3928 getNotifyContentUri(SubscriptionManager.VT_ENABLED_CONTENT_URI,
3929 usingSubId, subId), null, true, UserHandle.USER_ALL);
3930 }
Peter Wangb8e281d2020-01-31 18:50:00 -08003931 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_MODE)) {
chen xu1f8d5892018-11-01 00:13:42 -07003932 getContext().getContentResolver().notifyChange(
3933 getNotifyContentUri(SubscriptionManager.WFC_MODE_CONTENT_URI,
3934 usingSubId, subId), null, true, UserHandle.USER_ALL);
3935 }
Peter Wangb8e281d2020-01-31 18:50:00 -08003936 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE)) {
chen xu1f8d5892018-11-01 00:13:42 -07003937 getContext().getContentResolver().notifyChange(getNotifyContentUri(
3938 SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI,
3939 usingSubId, subId), null, true, UserHandle.USER_ALL);
3940 }
Peter Wangb8e281d2020-01-31 18:50:00 -08003941 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED)) {
chen xu1f8d5892018-11-01 00:13:42 -07003942 getContext().getContentResolver().notifyChange(getNotifyContentUri(
3943 SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI,
3944 usingSubId, subId), null, true, UserHandle.USER_ALL);
chen xu195e2ec2018-10-02 18:42:41 -07003945 }
Peter Wangb8e281d2020-01-31 18:50:00 -08003946 if (values.containsKey(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED)) {
Brad Ebinger748c7622020-01-22 16:12:04 -08003947 getContext().getContentResolver().notifyChange(getNotifyContentUri(
3948 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI,
Peter Wangb8e281d2020-01-31 18:50:00 -08003949 Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED), usingSubId, subId),
Brad Ebinger748c7622020-01-22 16:12:04 -08003950 null, true, UserHandle.USER_ALL);
3951 }
Wink Savillee84c0a82014-06-09 21:04:39 -07003952 break;
3953 default:
3954 getContext().getContentResolver().notifyChange(
Amit Mahajan28a5d002016-03-02 11:34:28 -08003955 CONTENT_URI, null, true, UserHandle.USER_ALL);
Wink Savillee84c0a82014-06-09 21:04:39 -07003956 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003957 }
3958
3959 return count;
3960 }
3961
chen xu1f8d5892018-11-01 00:13:42 -07003962 private static Uri getNotifyContentUri(Uri uri, boolean usingSubId, int subId) {
3963 return (usingSubId) ? Uri.withAppendedPath(uri, "" + subId) : uri;
3964 }
3965
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003966 private void checkPermission() {
Shishir Agrawalacf787b2014-07-14 17:13:51 -07003967 int status = getContext().checkCallingOrSelfPermission(
3968 "android.permission.WRITE_APN_SETTINGS");
3969 if (status == PackageManager.PERMISSION_GRANTED) {
3970 return;
3971 }
3972
3973 PackageManager packageManager = getContext().getPackageManager();
3974 String[] packages = packageManager.getPackagesForUid(Binder.getCallingUid());
3975
3976 TelephonyManager telephonyManager =
3977 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
3978 for (String pkg : packages) {
Cassie29b3b292018-09-24 09:26:51 -07003979 if (telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(pkg) ==
Shishir Agrawalacf787b2014-07-14 17:13:51 -07003980 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
3981 return;
3982 }
3983 }
Hall Liu7ee663d2019-11-21 16:30:47 -08003984
Hall Liu7ee663d2019-11-21 16:30:47 -08003985
3986 throw new SecurityException("No permission to access APN settings");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08003987 }
3988
Hall Liu018f8b12020-02-25 15:58:56 -08003989 /**
3990 * Check permission to query the database based on PlatformCompat settings -- if the compat
3991 * change is enabled, check WRITE_APN_SETTINGS or carrier privs for all queries. Otherwise,
3992 * use the legacy checkQueryPermission method to see if the query should be allowed.
3993 */
3994 private void checkPermissionCompat(int match, String[] projectionIn) {
3995 boolean useNewBehavior = CompatChanges.isChangeEnabled(
3996 Telephony.Carriers.APN_READING_PERMISSION_CHANGE_ID,
3997 Binder.getCallingUid());
3998
3999 if (!useNewBehavior) {
4000 log("Using old permission behavior for telephony provider compat");
4001 checkQueryPermission(match, projectionIn);
4002 } else {
4003 checkPermission();
4004 }
4005 }
4006
4007 private void checkQueryPermission(int match, String[] projectionIn) {
4008 if (match != URL_SIMINFO) {
4009 if (projectionIn != null) {
4010 for (String column : projectionIn) {
4011 if (TYPE.equals(column) ||
4012 MMSC.equals(column) ||
4013 MMSPROXY.equals(column) ||
4014 MMSPORT.equals(column) ||
4015 MVNO_TYPE.equals(column) ||
4016 MVNO_MATCH_DATA.equals(column) ||
4017 APN.equals(column)) {
4018 // noop
4019 } else {
4020 checkPermission();
4021 break;
4022 }
4023 }
4024 } else {
4025 // null returns all columns, so need permission check
4026 checkPermission();
4027 }
4028 }
4029 }
4030
Wink Savilled7c93502011-06-04 07:17:01 -07004031 private DatabaseHelper mOpenHelper;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08004032
Wink Saville830a40f2014-10-23 10:16:47 -07004033 private void restoreDefaultAPN(int subId) {
Jordan Liue6f0bce2016-09-21 18:31:43 -07004034 SQLiteDatabase db = getWritableDatabase();
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004035 TelephonyManager telephonyManager =
4036 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
4037 String where = null;
4038 if (telephonyManager.getPhoneCount() > 1) {
4039 where = getWhereClauseForRestoreDefaultApn(db, subId);
4040 }
4041 if (TextUtils.isEmpty(where)) {
4042 where = IS_NOT_OWNED_BY_DPC;
4043 }
4044 log("restoreDefaultAPN: where: " + where);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08004045
Hyejin Kimcfdb7432013-02-16 00:58:37 +09004046 try {
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004047 db.delete(CARRIERS_TABLE, where, null);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09004048 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07004049 loge("got exception when deleting to restore: " + e);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09004050 }
Amit Mahajan262ed502016-05-12 16:01:43 -07004051
4052 // delete preferred apn ids and preferred apns (both stored in diff SharedPref) for all
4053 // subIds
4054 SharedPreferences spApnId = getContext().getSharedPreferences(PREF_FILE_APN,
4055 Context.MODE_PRIVATE);
4056 SharedPreferences.Editor editorApnId = spApnId.edit();
4057 editorApnId.clear();
4058 editorApnId.apply();
4059
4060 SharedPreferences spApn = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
4061 Context.MODE_PRIVATE);
4062 SharedPreferences.Editor editorApn = spApn.edit();
4063 editorApn.clear();
4064 editorApn.apply();
4065
Jordan Liu3de76f82017-05-15 15:21:01 -07004066 if (apnSourceServiceExists(getContext())) {
Jordan Liu11c113e2018-11-13 12:19:11 -08004067 restoreApnsWithService(subId);
Jordan Liu3de76f82017-05-15 15:21:01 -07004068 } else {
4069 initDatabaseWithDatabaseHelper(db);
4070 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08004071 }
Wink Savillee84c0a82014-06-09 21:04:39 -07004072
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004073 private String getWhereClauseForRestoreDefaultApn(SQLiteDatabase db, int subId) {
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004074 TelephonyManager telephonyManager =
changbettyfaa1d7a2019-11-26 18:06:24 +08004075 getContext().getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
4076 String simOperator = telephonyManager.getSimOperator();
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004077 Cursor cursor = db.query(CARRIERS_TABLE, new String[] {MVNO_TYPE, MVNO_MATCH_DATA},
4078 NUMERIC + "='" + simOperator + "'", null, null, null, DEFAULT_SORT_ORDER);
4079 String where = null;
4080
4081 if (cursor != null) {
4082 cursor.moveToFirst();
4083 while (!cursor.isAfterLast()) {
4084 String mvnoType = cursor.getString(0 /* MVNO_TYPE index */);
4085 String mvnoMatchData = cursor.getString(1 /* MVNO_MATCH_DATA index */);
4086 if (!TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)
changbetty2351c172020-02-25 18:25:44 +08004087 && telephonyManager.matchesCurrentSimOperator(simOperator,
changbettya98edab2019-12-06 18:26:12 +08004088 getMvnoTypeIntFromString(mvnoType), mvnoMatchData)) {
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004089 where = NUMERIC + "='" + simOperator + "'"
4090 + " AND " + MVNO_TYPE + "='" + mvnoType + "'"
4091 + " AND " + MVNO_MATCH_DATA + "='" + mvnoMatchData + "'"
4092 + " AND " + IS_NOT_OWNED_BY_DPC;
4093 break;
4094 }
4095 cursor.moveToNext();
4096 }
4097 cursor.close();
4098
4099 if (TextUtils.isEmpty(where)) {
4100 where = NUMERIC + "='" + simOperator + "'"
4101 + " AND (" + MVNO_TYPE + "='' OR " + MVNO_MATCH_DATA + "='')"
4102 + " AND " + IS_NOT_OWNED_BY_DPC;
4103 }
4104 }
xiangyu.deng233d88c2021-07-16 14:09:40 +08004105
4106 where = NUMERIC + "='" + simOperator + "'"
4107 + " AND " + IS_NOT_OWNED_BY_DPC;
Chaitanya Saggurthi58ab3ad2017-12-05 22:09:09 +09004108 return where;
4109 }
4110
Amit Mahajanbc1edc22015-04-09 13:53:33 -07004111 private synchronized void updateApnDb() {
Jordan Liu3de76f82017-05-15 15:21:01 -07004112 if (apnSourceServiceExists(getContext())) {
4113 loge("called updateApnDb when apn source service exists");
4114 return;
4115 }
4116
Jordan Liue6f0bce2016-09-21 18:31:43 -07004117 if (!needApnDbUpdate()) {
Amit Mahajan28a5d002016-03-02 11:34:28 -08004118 log("Skipping apn db update since apn-conf has not changed.");
4119 return;
4120 }
4121
Jordan Liue6f0bce2016-09-21 18:31:43 -07004122 SQLiteDatabase db = getWritableDatabase();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08004123
Amit Mahajanbc1edc22015-04-09 13:53:33 -07004124 // Delete preferred APN for all subIds
Amit Mahajan9e7e3bb2019-08-26 12:35:32 -07004125 deletePreferredApnId(getContext());
Amit Mahajanbc1edc22015-04-09 13:53:33 -07004126
4127 // Delete entries in db
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08004128 try {
Amit Mahajan28a5d002016-03-02 11:34:28 -08004129 if (VDBG) log("updateApnDb: deleting edited=UNEDITED entries");
yuemingwc41e5c82017-11-09 13:30:33 +00004130 db.delete(CARRIERS_TABLE, IS_UNEDITED + " and " + IS_NOT_OWNED_BY_DPC, null);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08004131 } catch (SQLException e) {
4132 loge("got exception when deleting to update: " + e);
4133 }
4134
Jordan Liue6f0bce2016-09-21 18:31:43 -07004135 initDatabaseWithDatabaseHelper(db);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08004136
Hall Liu5479f4d2018-07-14 00:31:13 +00004137 // Notify listeners of DB change since DB has been updated
Amit Mahajanbc1edc22015-04-09 13:53:33 -07004138 getContext().getContentResolver().notifyChange(
Amit Mahajan28a5d002016-03-02 11:34:28 -08004139 CONTENT_URI, null, true, UserHandle.USER_ALL);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07004140
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08004141 }
4142
Hall Liu5479f4d2018-07-14 00:31:13 +00004143 public static void fillInMccMncStringAtCursor(Context context, SQLiteDatabase db, Cursor c) {
4144 int mcc, mnc;
4145 String subId;
4146 try {
Peter Wangb8e281d2020-01-31 18:50:00 -08004147 mcc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_MCC));
4148 mnc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_MNC));
Hall Liu5479f4d2018-07-14 00:31:13 +00004149 subId = c.getString(c.getColumnIndexOrThrow(
Peter Wangb8e281d2020-01-31 18:50:00 -08004150 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID));
Hall Liu5479f4d2018-07-14 00:31:13 +00004151 } catch (IllegalArgumentException e) {
4152 Log.e(TAG, "Possible database corruption -- some columns not found.");
4153 return;
4154 }
4155
4156 String mccString = String.format(Locale.getDefault(), "%03d", mcc);
4157 String mncString = getBestStringMnc(context, mccString, mnc);
4158 ContentValues cv = new ContentValues(2);
Peter Wangb8e281d2020-01-31 18:50:00 -08004159 cv.put(Telephony.SimInfo.COLUMN_MCC_STRING, mccString);
4160 cv.put(Telephony.SimInfo.COLUMN_MNC_STRING, mncString);
Hall Liu5479f4d2018-07-14 00:31:13 +00004161 db.update(SIMINFO_TABLE, cv,
Peter Wangb8e281d2020-01-31 18:50:00 -08004162 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
Hall Liu5479f4d2018-07-14 00:31:13 +00004163 new String[]{subId});
4164 }
4165
4166 /*
4167 * Find the best string-form mnc by looking up possibilities in the carrier id db.
4168 * Default to the three-digit version if neither/both are valid.
4169 */
4170 private static String getBestStringMnc(Context context, String mcc, int mnc) {
4171 if (mnc >= 100 && mnc <= 999) {
4172 return String.valueOf(mnc);
4173 }
4174 String twoDigitMnc = String.format(Locale.getDefault(), "%02d", mnc);
4175 String threeDigitMnc = "0" + twoDigitMnc;
4176
4177 try (
4178 Cursor twoDigitMncCursor = context.getContentResolver().query(
4179 Telephony.CarrierId.All.CONTENT_URI,
4180 /* projection */ null,
4181 /* selection */ Telephony.CarrierId.All.MCCMNC + "=?",
4182 /* selectionArgs */ new String[]{mcc + twoDigitMnc}, null)
4183 ) {
4184 if (twoDigitMncCursor.getCount() > 0) {
4185 return twoDigitMnc;
4186 }
4187 return threeDigitMnc;
4188 }
4189 }
4190
Wink Savillee84c0a82014-06-09 21:04:39 -07004191 /**
Cassiea58ce712017-12-06 16:21:50 -08004192 * Sync the bearer bitmask and network type bitmask when inserting and updating.
4193 * Since bearerBitmask is deprecating, map the networkTypeBitmask to bearerBitmask if
4194 * networkTypeBitmask was provided. But if networkTypeBitmask was not provided, map the
4195 * bearerBitmask to networkTypeBitmask.
4196 */
4197 private static void syncBearerBitmaskAndNetworkTypeBitmask(ContentValues values) {
4198 if (values.containsKey(NETWORK_TYPE_BITMASK)) {
SongFerngWang64fb3dd2019-12-02 20:59:47 +08004199 int convertedBitmask = convertNetworkTypeBitmaskToBearerBitmask(
Cassiea58ce712017-12-06 16:21:50 -08004200 values.getAsInteger(NETWORK_TYPE_BITMASK));
4201 if (values.containsKey(BEARER_BITMASK)
4202 && convertedBitmask != values.getAsInteger(BEARER_BITMASK)) {
4203 loge("Network type bitmask and bearer bitmask are not compatible.");
4204 }
SongFerngWang64fb3dd2019-12-02 20:59:47 +08004205 values.put(BEARER_BITMASK, convertNetworkTypeBitmaskToBearerBitmask(
Cassiea58ce712017-12-06 16:21:50 -08004206 values.getAsInteger(NETWORK_TYPE_BITMASK)));
4207 } else {
4208 if (values.containsKey(BEARER_BITMASK)) {
SongFerngWang64fb3dd2019-12-02 20:59:47 +08004209 int convertedBitmask = convertBearerBitmaskToNetworkTypeBitmask(
Cassiea58ce712017-12-06 16:21:50 -08004210 values.getAsInteger(BEARER_BITMASK));
4211 values.put(NETWORK_TYPE_BITMASK, convertedBitmask);
4212 }
4213 }
4214 }
4215
4216 /**
Wink Savillee84c0a82014-06-09 21:04:39 -07004217 * Log with debug
4218 *
4219 * @param s is string log
4220 */
4221 private static void log(String s) {
4222 Log.d(TAG, s);
4223 }
4224
4225 private static void loge(String s) {
4226 Log.e(TAG, s);
4227 }
zoey chen715880a2019-11-12 18:47:02 +08004228
4229 private static int getMvnoTypeIntFromString(String mvnoType) {
4230 String mvnoTypeString = TextUtils.isEmpty(mvnoType) ? mvnoType : mvnoType.toLowerCase();
4231 Integer mvnoTypeInt = MVNO_TYPE_STRING_MAP.get(mvnoTypeString);
4232 return mvnoTypeInt == null ? UNSPECIFIED_INT : mvnoTypeInt;
4233 }
SongFerngWang64fb3dd2019-12-02 20:59:47 +08004234
4235 private static int getBitmaskFromString(String bearerList) {
4236 String[] bearers = bearerList.split("\\|");
4237 int bearerBitmask = 0;
4238 for (String bearer : bearers) {
4239 int bearerInt = 0;
4240 try {
4241 bearerInt = Integer.parseInt(bearer.trim());
4242 } catch (NumberFormatException nfe) {
4243 return 0;
4244 }
4245
4246 if (bearerInt == 0) {
4247 return 0;
4248 }
4249 bearerBitmask |= getBitmaskForTech(bearerInt);
4250 }
4251 return bearerBitmask;
4252 }
4253
4254 /**
4255 * Transform RIL radio technology value to Network
4256 * type bitmask{@link android.telephony.TelephonyManager.NetworkTypeBitMask}.
4257 *
4258 * @param rat The RIL radio technology.
4259 * @return The network type
4260 * bitmask{@link android.telephony.TelephonyManager.NetworkTypeBitMask}.
4261 */
4262 private static int rilRadioTechnologyToNetworkTypeBitmask(int rat) {
4263 switch (rat) {
4264 case RIL_RADIO_TECHNOLOGY_GPRS:
4265 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
4266 case RIL_RADIO_TECHNOLOGY_EDGE:
4267 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
4268 case RIL_RADIO_TECHNOLOGY_UMTS:
4269 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
4270 case RIL_RADIO_TECHNOLOGY_HSDPA:
4271 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
4272 case RIL_RADIO_TECHNOLOGY_HSUPA:
4273 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
4274 case RIL_RADIO_TECHNOLOGY_HSPA:
4275 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
4276 case RIL_RADIO_TECHNOLOGY_IS95A:
4277 case RIL_RADIO_TECHNOLOGY_IS95B:
4278 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
4279 case RIL_RADIO_TECHNOLOGY_1xRTT:
4280 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
4281 case RIL_RADIO_TECHNOLOGY_EVDO_0:
4282 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
4283 case RIL_RADIO_TECHNOLOGY_EVDO_A:
4284 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
4285 case RIL_RADIO_TECHNOLOGY_EVDO_B:
4286 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
4287 case RIL_RADIO_TECHNOLOGY_EHRPD:
4288 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
4289 case RIL_RADIO_TECHNOLOGY_LTE:
4290 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
4291 case RIL_RADIO_TECHNOLOGY_HSPAP:
4292 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
4293 case RIL_RADIO_TECHNOLOGY_GSM:
4294 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
4295 case RIL_RADIO_TECHNOLOGY_TD_SCDMA:
4296 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
4297 case RIL_RADIO_TECHNOLOGY_IWLAN:
4298 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN;
4299 case RIL_RADIO_TECHNOLOGY_LTE_CA:
4300 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
4301 case RIL_RADIO_TECHNOLOGY_NR:
4302 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_NR;
4303 default:
4304 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
4305 }
4306 }
4307
4308 /**
4309 * Convert network type bitmask to bearer bitmask.
4310 *
4311 * @param networkTypeBitmask The network type bitmask value
4312 * @return The bearer bitmask value.
4313 */
4314 private static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) {
4315 if (networkTypeBitmask == 0) {
4316 return 0;
4317 }
4318
4319 int bearerBitmask = 0;
4320 for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) {
4321 if (bitmaskHasTarget(networkTypeBitmask,
4322 rilRadioTechnologyToNetworkTypeBitmask(bearerInt))) {
4323 bearerBitmask |= getBitmaskForTech(bearerInt);
4324 }
4325 }
4326 return bearerBitmask;
4327 }
4328
4329 /**
4330 * Convert bearer bitmask to network type bitmask.
4331 *
4332 * @param bearerBitmask The bearer bitmask value.
4333 * @return The network type bitmask value.
4334 */
4335 private static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) {
4336 if (bearerBitmask == 0) {
4337 return 0;
4338 }
4339
4340 int networkTypeBitmask = 0;
4341 for (int bearerUnitInt = 0; bearerUnitInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerUnitInt++) {
4342 int bearerUnitBitmask = getBitmaskForTech(bearerUnitInt);
4343 if (bitmaskHasTarget(bearerBitmask, bearerUnitBitmask)) {
4344 networkTypeBitmask |= rilRadioTechnologyToNetworkTypeBitmask(bearerUnitInt);
4345 }
4346 }
4347 return networkTypeBitmask;
4348 }
4349
4350 private static boolean bitmaskHasTarget(int bearerBitmask, int targetBitmask) {
4351 if (bearerBitmask == 0) {
4352 return true;
4353 } else if (targetBitmask != 0) {
4354 return ((bearerBitmask & targetBitmask) != 0);
4355 }
4356 return false;
4357 }
4358
4359 private static int getBitmaskForTech(int radioTech) {
4360 if (radioTech >= 1) {
4361 return (1 << (radioTech - 1));
4362 }
4363 return 0;
4364 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08004365}