blob: 1a50d3dd91ebf8c3c940741d15bb840cba64091b [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
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070020import android.content.ContentProvider;
21import android.content.ContentUris;
22import android.content.ContentValues;
23import android.content.Context;
24import android.content.SharedPreferences;
25import android.content.UriMatcher;
Shishir Agrawalacf787b2014-07-14 17:13:51 -070026import android.content.pm.PackageManager;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080027import android.content.res.Resources;
28import android.content.res.XmlResourceParser;
29import android.database.Cursor;
jewon.lee4167fcc2013-01-17 13:10:37 +090030import android.database.SQLException;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080031import android.database.sqlite.SQLiteDatabase;
Wink Saville6de10272014-06-22 07:38:43 -070032import android.database.sqlite.SQLiteException;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080033import android.database.sqlite.SQLiteOpenHelper;
34import android.database.sqlite.SQLiteQueryBuilder;
35import android.net.Uri;
Shishir Agrawalacf787b2014-07-14 17:13:51 -070036import android.os.Binder;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080037import android.os.Environment;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080038import android.os.SystemProperties;
Amith Yamasani887288c2014-11-06 09:01:20 -080039import android.os.UserHandle;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080040import android.provider.Telephony;
Amit Mahajanb80f7332015-04-16 10:02:52 -070041import android.telephony.ServiceState;
Amit Mahajanbc1edc22015-04-09 13:53:33 -070042import android.telephony.SubscriptionInfo;
Wink Savillee84c0a82014-06-09 21:04:39 -070043import android.telephony.SubscriptionManager;
44import android.telephony.TelephonyManager;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080045import android.text.TextUtils;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080046import android.util.Log;
47import android.util.Xml;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070048
Dianne Hackborn49f22d32010-02-24 19:58:29 -080049import com.android.internal.util.XmlUtils;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080050
51import org.xmlpull.v1.XmlPullParser;
52import org.xmlpull.v1.XmlPullParserException;
53
54import java.io.File;
55import java.io.FileNotFoundException;
56import java.io.FileReader;
57import java.io.IOException;
w19976e9a6c452014-07-18 16:43:00 -070058import java.lang.NumberFormatException;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080059import java.util.ArrayList;
60import java.util.Arrays;
Amit Mahajanbc1edc22015-04-09 13:53:33 -070061import java.util.List;
Amit Mahajan91c5dff2015-10-20 11:13:19 -070062import java.util.Map;
Wink Savilled7c93502011-06-04 07:17:01 -070063
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080064public class TelephonyProvider extends ContentProvider
65{
66 private static final String DATABASE_NAME = "telephony.db";
Wink Savilled7c93502011-06-04 07:17:01 -070067 private static final boolean DBG = true;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080068 private static final boolean VDBG = false; // STOPSHIP if true
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070069
Amit Mahajanda607212015-10-08 09:13:00 -070070 private static final int DATABASE_VERSION = 17 << 16;
Wink Savillee84c0a82014-06-09 21:04:39 -070071 private static final int URL_UNKNOWN = 0;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080072 private static final int URL_TELEPHONY = 1;
73 private static final int URL_CURRENT = 2;
74 private static final int URL_ID = 3;
75 private static final int URL_RESTOREAPN = 4;
John Huangb1bc16d2009-03-24 18:26:28 -070076 private static final int URL_PREFERAPN = 5;
Kazuhiro Ondod616ee62012-01-10 17:12:59 -060077 private static final int URL_PREFERAPN_NO_UPDATE = 6;
Wink Savillee84c0a82014-06-09 21:04:39 -070078 private static final int URL_SIMINFO = 7;
79 private static final int URL_TELEPHONY_USING_SUBID = 8;
80 private static final int URL_CURRENT_USING_SUBID = 9;
81 private static final int URL_RESTOREAPN_USING_SUBID = 10;
82 private static final int URL_PREFERAPN_USING_SUBID = 11;
83 private static final int URL_PREFERAPN_NO_UPDATE_USING_SUBID = 12;
84 private static final int URL_SIMINFO_USING_SUBID = 13;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080085 private static final int URL_UPDATE_DB = 14;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080086
87 private static final String TAG = "TelephonyProvider";
88 private static final String CARRIERS_TABLE = "carriers";
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080089 private static final String CARRIERS_TABLE_TMP = "carriers_tmp";
Wink Savillee84c0a82014-06-09 21:04:39 -070090 private static final String SIMINFO_TABLE = "siminfo";
John Huangb1bc16d2009-03-24 18:26:28 -070091
92 private static final String PREF_FILE = "preferred-apn";
93 private static final String COLUMN_APN_ID = "apn_id";
94
Amit Mahajan91c5dff2015-10-20 11:13:19 -070095 private static final String PREF_FILE_FULL_APN = "preferred-full-apn";
96 private static final String DB_VERSION_KEY = "version";
97
Amit Mahajan3f2e68a2015-02-27 15:40:41 -080098 private static final String BUILD_ID_FILE = "build-id";
99 private static final String RO_BUILD_ID = "ro_build_id";
100
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800101 private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";
Legler Wub16a1202014-12-29 13:20:29 +0800102 private static final String OEM_APNS_PATH = "telephony/apns-conf.xml";
Amit Mahajanb80f7332015-04-16 10:02:52 -0700103 private static final String OTA_UPDATED_APNS_PATH = "misc/apns-conf.xml";
Amit Mahajan899cc602015-05-14 17:22:09 -0700104 private static final String OLD_APNS_PATH = "etc/old-apns-conf.xml";
Susheel nyamala132b0432015-05-08 17:57:50 +0530105 private static final String REGIONAL_APNS_PATH = "etc/regional-apns-conf.xml";
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800106
kaiyize93034a2014-07-31 15:50:20 +0800107 private static final String READ_ONLY = "read_only";
108
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800109 private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
110
111 private static final ContentValues s_currentNullMap;
112 private static final ContentValues s_currentSetMap;
113
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700114 private static final int INVALID_APN_ID = -1;
115 private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>();
116
117 static {
118 // Columns not included in UNIQUE constraint: name, current, edited, user, server, password,
119 // authtype, type, protocol, roaming_protocol, sub_id, modem_cognitive, max_conns, wait_time,
120 // max_conns_time, mtu, bearer_bitmask, user_visible
121 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.NUMERIC);
122 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MCC);
123 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MNC);
124 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.APN);
125 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.PROXY);
126 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.PORT);
127 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MMSPROXY);
128 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MMSPORT);
129 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MMSC);
130 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.CARRIER_ENABLED);
131 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.BEARER);
132 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MVNO_TYPE);
133 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.MVNO_MATCH_DATA);
134 CARRIERS_UNIQUE_FIELDS.add(Telephony.Carriers.PROFILE_ID);
135 }
136
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800137 static {
138 s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY);
139 s_urlMatcher.addURI("telephony", "carriers/current", URL_CURRENT);
140 s_urlMatcher.addURI("telephony", "carriers/#", URL_ID);
141 s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN);
John Huangb1bc16d2009-03-24 18:26:28 -0700142 s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN);
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600143 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800144
Wink Savillee84c0a82014-06-09 21:04:39 -0700145 s_urlMatcher.addURI("telephony", "siminfo", URL_SIMINFO);
146
147 s_urlMatcher.addURI("telephony", "carriers/subId/*", URL_TELEPHONY_USING_SUBID);
148 s_urlMatcher.addURI("telephony", "carriers/current/subId/*", URL_CURRENT_USING_SUBID);
149 s_urlMatcher.addURI("telephony", "carriers/restore/subId/*", URL_RESTOREAPN_USING_SUBID);
150 s_urlMatcher.addURI("telephony", "carriers/preferapn/subId/*", URL_PREFERAPN_USING_SUBID);
151 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update/subId/*",
152 URL_PREFERAPN_NO_UPDATE_USING_SUBID);
153
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800154 s_urlMatcher.addURI("telephony", "carriers/update_db", URL_UPDATE_DB);
Wink Savillee84c0a82014-06-09 21:04:39 -0700155
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800156 s_currentNullMap = new ContentValues(1);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800157 s_currentNullMap.put(Telephony.Carriers.CURRENT, "0");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800158
159 s_currentSetMap = new ContentValues(1);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800160 s_currentSetMap.put(Telephony.Carriers.CURRENT, "1");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800161 }
162
163 private static class DatabaseHelper extends SQLiteOpenHelper {
164 // Context to access resources with
165 private Context mContext;
166
167 /**
168 * DatabaseHelper helper class for loading apns into a database.
169 *
Wink Savilled7c93502011-06-04 07:17:01 -0700170 * @param context of the user.
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800171 */
172 public DatabaseHelper(Context context) {
173 super(context, DATABASE_NAME, null, getVersion(context));
174 mContext = context;
175 }
176
177 private static int getVersion(Context context) {
Wink Saville6de10272014-06-22 07:38:43 -0700178 if (VDBG) log("getVersion:+");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800179 // Get the database version, combining a static schema version and the XML version
180 Resources r = context.getResources();
181 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
182 try {
183 XmlUtils.beginDocument(parser, "apns");
184 int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
Wink Saville6de10272014-06-22 07:38:43 -0700185 int version = DATABASE_VERSION | publicversion;
186 if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
187 return version;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800188 } catch (Exception e) {
Wink Saville6de10272014-06-22 07:38:43 -0700189 loge("Can't get version of APN database" + e + " return version=" +
190 Integer.toHexString(DATABASE_VERSION));
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800191 return DATABASE_VERSION;
192 } finally {
193 parser.close();
194 }
195 }
196
197 @Override
198 public void onCreate(SQLiteDatabase db) {
Wink Saville6de10272014-06-22 07:38:43 -0700199 if (DBG) log("dbh.onCreate:+ db=" + db);
200 createSimInfoTable(db);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800201 createCarriersTable(db, CARRIERS_TABLE);
Wink Saville6de10272014-06-22 07:38:43 -0700202 initDatabase(db);
203 if (DBG) log("dbh.onCreate:- db=" + db);
204 }
205
206 @Override
207 public void onOpen(SQLiteDatabase db) {
208 if (VDBG) log("dbh.onOpen:+ db=" + db);
209 try {
210 // Try to access the table and create it if "no such table"
211 db.query(SIMINFO_TABLE, null, null, null, null, null, null);
212 if (DBG) log("dbh.onOpen: ok, queried table=" + SIMINFO_TABLE);
213 } catch (SQLiteException e) {
214 loge("Exception " + SIMINFO_TABLE + "e=" + e);
215 if (e.getMessage().startsWith("no such table")) {
216 createSimInfoTable(db);
217 }
218 }
219 try {
220 db.query(CARRIERS_TABLE, null, null, null, null, null, null);
221 if (DBG) log("dbh.onOpen: ok, queried table=" + CARRIERS_TABLE);
222 } catch (SQLiteException e) {
223 loge("Exception " + CARRIERS_TABLE + " e=" + e);
224 if (e.getMessage().startsWith("no such table")) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800225 createCarriersTable(db, CARRIERS_TABLE);
Wink Saville6de10272014-06-22 07:38:43 -0700226 }
227 }
228 if (VDBG) log("dbh.onOpen:- db=" + db);
229 }
230
231 private void createSimInfoTable(SQLiteDatabase db) {
232 if (DBG) log("dbh.createSimInfoTable:+");
Wink Savillee84c0a82014-06-09 21:04:39 -0700233 db.execSQL("CREATE TABLE " + SIMINFO_TABLE + "("
Wink Saville72b14732014-11-20 13:06:04 -0800234 + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
Wink Savillee84c0a82014-06-09 21:04:39 -0700235 + SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
Wink Saville72b14732014-11-20 13:06:04 -0800236 + SubscriptionManager.SIM_SLOT_INDEX + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
Wink Savillee84c0a82014-06-09 21:04:39 -0700237 + SubscriptionManager.DISPLAY_NAME + " TEXT,"
Sanket Padawe7e633bd2014-11-06 11:50:40 -0800238 + SubscriptionManager.CARRIER_NAME + " TEXT,"
Wink Savilled3b87ec2014-09-02 22:45:38 -0700239 + SubscriptionManager.NAME_SOURCE + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
Wink Savillee84c0a82014-06-09 21:04:39 -0700240 + SubscriptionManager.COLOR + " INTEGER DEFAULT " + SubscriptionManager.COLOR_DEFAULT + ","
241 + SubscriptionManager.NUMBER + " TEXT,"
Stuart Scottf5b56e32014-10-31 14:36:28 -0700242 + SubscriptionManager.DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700243 + SubscriptionManager.DATA_ROAMING + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
244 + SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700245 + SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
246 + SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
247 + SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
248 + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
249 + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
250 + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
251 + SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
252 + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
253 + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
254 + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
255 + SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
Sridhar Dubbaka0398c4f2015-09-22 22:23:59 +0530256 + SubscriptionManager.CB_CHANNEL_60_ALERT + " INTEGER DEFAULT 1,"
Sridhar Dubbaka1da42e52015-10-21 14:16:44 +0530257 + SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 1,"
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700258 + SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1"
Wink Savillee84c0a82014-06-09 21:04:39 -0700259 + ");");
Wink Saville6de10272014-06-22 07:38:43 -0700260 if (DBG) log("dbh.createSimInfoTable:-");
261 }
262
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800263 private void createCarriersTable(SQLiteDatabase db, String tableName) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800264 // Set up the database schema
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800265 if (DBG) log("dbh.createCarriersTable: " + tableName);
266 db.execSQL("CREATE TABLE " + tableName +
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700267 "(_id INTEGER PRIMARY KEY," +
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800268 "name TEXT DEFAULT ''," +
269 "numeric TEXT DEFAULT ''," +
270 "mcc TEXT DEFAULT ''," +
271 "mnc TEXT DEFAULT ''," +
272 "apn TEXT DEFAULT ''," +
273 "user TEXT DEFAULT ''," +
274 "server TEXT DEFAULT ''," +
275 "password TEXT DEFAULT ''," +
276 "proxy TEXT DEFAULT ''," +
277 "port TEXT DEFAULT ''," +
278 "mmsproxy TEXT DEFAULT ''," +
279 "mmsport TEXT DEFAULT ''," +
280 "mmsc TEXT DEFAULT ''," +
281 "authtype INTEGER DEFAULT -1," +
282 "type TEXT DEFAULT ''," +
Lorenzo Colitti9dd054f2010-12-29 15:54:00 -0800283 "current INTEGER," +
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800284 "protocol TEXT DEFAULT 'IP'," +
285 "roaming_protocol TEXT DEFAULT 'IP'," +
286 "carrier_enabled BOOLEAN DEFAULT 1," +
287 "bearer INTEGER DEFAULT 0," +
Amit Mahajanb80f7332015-04-16 10:02:52 -0700288 "bearer_bitmask INTEGER DEFAULT 0," +
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800289 "mvno_type TEXT DEFAULT ''," +
290 "mvno_match_data TEXT DEFAULT ''," +
Wink Saville72b14732014-11-20 13:06:04 -0800291 "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + "," +
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800292 "profile_id INTEGER DEFAULT 0," +
293 "modem_cognitive BOOLEAN DEFAULT 0," +
294 "max_conns INTEGER DEFAULT 0," +
295 "wait_time INTEGER DEFAULT 0," +
296 "max_conns_time INTEGER DEFAULT 0," +
297 "mtu INTEGER DEFAULT 0," +
Amit Mahajanb80f7332015-04-16 10:02:52 -0700298 "edited INTEGER DEFAULT " + Telephony.Carriers.UNEDITED + "," +
Amit Mahajanda607212015-10-08 09:13:00 -0700299 "user_visible BOOLEAN DEFAULT 1," +
kaiyize93034a2014-07-31 15:50:20 +0800300 "read_only BOOLEAN DEFAULT 0," +
kaiyizdeeba8b2014-07-31 15:25:30 +0800301 "ppp_number TEXT DEFAULT ''," +
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700302 // Uniqueness collisions are used to trigger merge code so if a field is listed
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800303 // here it means we will accept both (user edited + new apn_conf definition)
Amit Mahajanb80f7332015-04-16 10:02:52 -0700304 // Columns not included in UNIQUE constraint: name, current, edited,
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800305 // user, server, password, authtype, type, protocol, roaming_protocol, sub_id,
Amit Mahajan91c5dff2015-10-20 11:13:19 -0700306 // modem_cognitive, max_conns, wait_time, max_conns_time, mtu, bearer_bitmask,
307 // user_visible
Susheel nyamalaa63611b2015-11-05 13:35:59 +0530308 "UNIQUE (name, numeric, mcc, mnc, apn, proxy, port, mmsproxy, mmsport, mmsc," +
309 "type, carrier_enabled, bearer, mvno_type, mvno_match_data, profile_id));");
Wink Saville6de10272014-06-22 07:38:43 -0700310 if (DBG) log("dbh.createCarriersTable:-");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800311 }
Shri Borde7ed9c332014-09-15 13:46:01 -0700312
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700313 /**
314 * This function adds APNs from xml file(s) to db. The db may or may not be empty to begin
315 * with.
316 */
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800317 private void initDatabase(SQLiteDatabase db) {
Wink Saville6de10272014-06-22 07:38:43 -0700318 if (VDBG) log("dbh.initDatabase:+ db=" + db);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800319 // Read internal APNS data
320 Resources r = mContext.getResources();
321 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
322 int publicversion = -1;
323 try {
324 XmlUtils.beginDocument(parser, "apns");
325 publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
326 loadApns(db, parser);
327 } catch (Exception e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700328 loge("Got exception while loading APN database." + e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800329 } finally {
330 parser.close();
331 }
332
Sungmin Choi22b63062013-01-25 15:53:15 +0900333 // Read external APNS data (partner-provided)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800334 XmlPullParser confparser = null;
335 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
336 File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);
Legler Wub16a1202014-12-29 13:20:29 +0800337 File oemConfFile = new File(Environment.getOemDirectory(), OEM_APNS_PATH);
Amit Mahajanb80f7332015-04-16 10:02:52 -0700338 File updatedConfFile = new File(Environment.getDataDirectory(), OTA_UPDATED_APNS_PATH);
339 confFile = getNewerFile(confFile, oemConfFile);
340 confFile = getNewerFile(confFile, updatedConfFile);
Legler Wub16a1202014-12-29 13:20:29 +0800341
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800342 FileReader confreader = null;
Legler Wub16a1202014-12-29 13:20:29 +0800343 if (DBG) log("confFile = " + confFile);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800344 try {
Susheel nyamala132b0432015-05-08 17:57:50 +0530345 // Read external APNS data (partner-provided)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800346 confreader = new FileReader(confFile);
Susheel nyamala132b0432015-05-08 17:57:50 +0530347 confparser = getXmlParser(confreader);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800348
Susheel nyamala132b0432015-05-08 17:57:50 +0530349 if (confparser != null) {
350 // Sanity check. Force internal version and confidential versions to agree
351 int confversion = Integer.parseInt(confparser.
352 getAttributeValue(null, "version"));
353 if (publicversion != confversion) {
354 log("initDatabase: throwing exception due to version mismatch");
355 throw new IllegalStateException("Internal APNS file version doesn't match "
356 + confFile.getAbsolutePath());
357 }
358
359 loadApns(db, confparser);
360
361 try {
362 if (confreader != null) {
363 confreader.close();
364 confreader = null;
365 }
366 confparser = null;
367 } catch (IOException e) { }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800368 }
369
Susheel nyamala132b0432015-05-08 17:57:50 +0530370 confFile = new File(Environment.getRootDirectory(), REGIONAL_APNS_PATH);
371 if (confFile.exists()) {
372 confreader = new FileReader(confFile);
373 confparser = getXmlParser(confreader);
374 if (confparser != null) {
375 loadRegionalApns(db, confparser);
376 }
377 } else {
378 if (DBG) log("Regional apns file not found");
379 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800380 } catch (FileNotFoundException e) {
381 // It's ok if the file isn't found. It means there isn't a confidential file
382 // Log.e(TAG, "File not found: '" + confFile.getAbsolutePath() + "'");
383 } catch (Exception e) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800384 loge("initDatabase: Exception while parsing '" + confFile.getAbsolutePath() + "'" +
385 e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800386 } finally {
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700387 // Get rid of user/carrier deleted entries that are not present in apn xml file.
Amit Mahajanb80f7332015-04-16 10:02:52 -0700388 // Those entries have edited value USER_DELETED/CARRIER_DELETED.
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800389 if (VDBG) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700390 log("initDatabase: deleting USER_DELETED and replacing "
391 + "DELETED_BUT_PRESENT_IN_XML with DELETED");
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800392 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700393
394 // Delete USER_DELETED
Amit Mahajanb80f7332015-04-16 10:02:52 -0700395 db.delete(CARRIERS_TABLE, "edited=" + Telephony.Carriers.USER_DELETED + " or " +
396 "edited=" + Telephony.Carriers.CARRIER_DELETED, null);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700397
398 // Change USER_DELETED_BUT_PRESENT_IN_XML to USER_DELETED
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800399 ContentValues cv = new ContentValues();
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700400 cv.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_DELETED);
Amit Mahajanb80f7332015-04-16 10:02:52 -0700401 db.update(CARRIERS_TABLE, cv, "edited=" + Telephony.Carriers.USER_DELETED_BUT_PRESENT_IN_XML,
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800402 null);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700403
404 // Change CARRIER_DELETED_BUT_PRESENT_IN_XML to CARRIER_DELETED
405 cv = new ContentValues();
406 cv.put(Telephony.Carriers.EDITED, Telephony.Carriers.CARRIER_DELETED);
Amit Mahajanb80f7332015-04-16 10:02:52 -0700407 db.update(CARRIERS_TABLE, cv, "edited=" + Telephony.Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML,
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700408 null);
409
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800410 if (confreader != null) {
411 try {
412 confreader.close();
413 } catch (IOException e) {
414 // do nothing
415 }
416 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800417 }
Amit Mahajanb0688862014-08-13 16:53:51 +0000418
Susheel nyamala132b0432015-05-08 17:57:50 +0530419 if (VDBG) log("dbh.initDatabase:- db=" + db);
420 }
421
422 private XmlPullParser getXmlParser(FileReader confreader) {
423 XmlPullParser confparser = null;
424 try {
425 confparser = Xml.newPullParser();
426 confparser.setInput(confreader);
427 XmlUtils.beginDocument(confparser, "apns");
428
429 } catch (Exception e) {
430 loge("Exception while parsing apns xml file" + e);
431 }
432
433 return confparser;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800434 }
435
Amit Mahajanb80f7332015-04-16 10:02:52 -0700436 private File getNewerFile(File sysApnFile, File altApnFile) {
437 if (altApnFile.exists()) {
438 // Alternate file exists. Use the newer one.
439 long altFileTime = altApnFile.lastModified();
440 long currFileTime = sysApnFile.lastModified();
441 if (DBG) log("APNs Timestamp: altFileTime = " + altFileTime + " currFileTime = "
442 + currFileTime);
443
444 // To get the latest version from OEM or System image
445 if (altFileTime > currFileTime) {
446 if (DBG) log("APNs Timestamp: Alternate image " + altApnFile.getPath() +
447 " is greater than System image");
448 return altApnFile;
449 }
450 } else {
451 // No Apn in alternate image, so load it from system image.
452 if (DBG) log("No APNs in OEM image = " + altApnFile.getPath() +
453 " Load APNs from system image");
454 }
455 return sysApnFile;
456 }
457
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800458 @Override
459 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Wink Saville6de10272014-06-22 07:38:43 -0700460 if (DBG) {
461 log("dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
462 }
463
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700464 if (oldVersion < (5 << 16 | 6)) {
465 // 5 << 16 is the Database version and 6 in the xml version.
466
467 // This change adds a new authtype column to the database.
468 // The auth type column can have 4 values: 0 (None), 1 (PAP), 2 (CHAP)
469 // 3 (PAP or CHAP). To avoid breaking compatibility, with already working
470 // APNs, the unset value (-1) will be used. If the value is -1.
471 // the authentication will default to 0 (if no user / password) is specified
472 // or to 3. Currently, there have been no reported problems with
473 // pre-configured APNs and hence it is set to -1 for them. Similarly,
474 // if the user, has added a new APN, we set the authentication type
475 // to -1.
476
477 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
478 " ADD COLUMN authtype INTEGER DEFAULT -1;");
479
480 oldVersion = 5 << 16 | 6;
481 }
Lorenzo Colitti9dd054f2010-12-29 15:54:00 -0800482 if (oldVersion < (6 << 16 | 6)) {
483 // Add protcol fields to the APN. The XML file does not change.
484 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
485 " ADD COLUMN protocol TEXT DEFAULT IP;");
486 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
487 " ADD COLUMN roaming_protocol TEXT DEFAULT IP;");
488 oldVersion = 6 << 16 | 6;
489 }
sinikangbae4b072011-09-02 09:49:37 +0900490 if (oldVersion < (7 << 16 | 6)) {
Sungmin Choi22b63062013-01-25 15:53:15 +0900491 // Add carrier_enabled, bearer fields to the APN. The XML file does not change.
sinikangbae4b072011-09-02 09:49:37 +0900492 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
493 " ADD COLUMN carrier_enabled BOOLEAN DEFAULT 1;");
494 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
495 " ADD COLUMN bearer INTEGER DEFAULT 0;");
496 oldVersion = 7 << 16 | 6;
497 }
Sungmin Choi27045ef2013-01-25 17:48:06 +0900498 if (oldVersion < (8 << 16 | 6)) {
499 // Add mvno_type, mvno_match_data fields to the APN.
500 // The XML file does not change.
501 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
502 " ADD COLUMN mvno_type TEXT DEFAULT '';");
503 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
504 " ADD COLUMN mvno_match_data TEXT DEFAULT '';");
505 oldVersion = 8 << 16 | 6;
506 }
Wink Savillee84c0a82014-06-09 21:04:39 -0700507 if (oldVersion < (9 << 16 | 6)) {
508 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
Tom Taylor1ad5f912014-10-28 13:35:34 -0700509 " ADD COLUMN sub_id INTEGER DEFAULT " +
Wink Saville72b14732014-11-20 13:06:04 -0800510 SubscriptionManager.INVALID_SUBSCRIPTION_ID + ";");
Wink Savillee84c0a82014-06-09 21:04:39 -0700511 oldVersion = 9 << 16 | 6;
512 }
Amit Mahajanb0688862014-08-13 16:53:51 +0000513 if (oldVersion < (10 << 16 | 6)) {
514 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
515 " ADD COLUMN profile_id INTEGER DEFAULT 0;");
516 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
517 " ADD COLUMN modem_cognitive BOOLEAN DEFAULT 0;");
518 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
519 " ADD COLUMN max_conns INTEGER DEFAULT 0;");
520 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
521 " ADD COLUMN wait_time INTEGER DEFAULT 0;");
522 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
523 " ADD COLUMN max_conns_time INTEGER DEFAULT 0;");
524 oldVersion = 10 << 16 | 6;
525 }
w19976e9a6c452014-07-18 16:43:00 -0700526 if (oldVersion < (11 << 16 | 6)) {
527 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
528 " ADD COLUMN mtu INTEGER DEFAULT 0;");
529 oldVersion = 11 << 16 | 6;
530 }
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700531 if (oldVersion < (12 << 16 | 6)) {
Tom Taylorc55054d2014-09-10 11:01:44 -0700532 try {
533 // Try to update the siminfo table. It might not be there.
534 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
535 " ADD COLUMN " + SubscriptionManager.MCC + " INTEGER DEFAULT 0;");
536 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
537 " ADD COLUMN " + SubscriptionManager.MNC + " INTEGER DEFAULT 0;");
538 } catch (SQLiteException e) {
539 if (DBG) {
540 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
541 " The table will get created in onOpen.");
542 }
543 }
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700544 oldVersion = 12 << 16 | 6;
545 }
Sanket Padawe7e633bd2014-11-06 11:50:40 -0800546 if (oldVersion < (13 << 16 | 6)) {
547 try {
548 // Try to update the siminfo table. It might not be there.
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800549 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " +
550 SubscriptionManager.CARRIER_NAME + " TEXT DEFAULT '';");
Sanket Padawe7e633bd2014-11-06 11:50:40 -0800551 } catch (SQLiteException e) {
552 if (DBG) {
553 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
554 " The table will get created in onOpen.");
555 }
556 }
557 oldVersion = 13 << 16 | 6;
558 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800559 if (oldVersion < (14 << 16 | 6)) {
Amit Mahajanb80f7332015-04-16 10:02:52 -0700560 // Do nothing. This is to avoid recreating table twice. Table is anyway recreated
561 // for next version and that takes care of updates for this version as well.
562 // This version added a new column user_edited to carriers db.
563 }
564 if (oldVersion < (15 << 16 | 6)) {
Amit Mahajan899cc602015-05-14 17:22:09 -0700565 // Most devices should be upgrading from version 13. On upgrade new db will be
566 // populated from the xml included in OTA but user and carrier edited/added entries
567 // need to be preserved. This new version also adds new columns EDITED and
568 // BEARER_BITMASK to the table. Upgrade steps from version 13 are:
569 // 1. preserve user and carrier added/edited APNs (by comparing against
570 // old-apns-conf.xml included in OTA) - done in preserveUserAndCarrierApns()
571 // 2. add new columns EDITED and BEARER_BITMASK (create a new table for that) - done
572 // in createCarriersTable()
573 // 3. copy over preserved APNs from old table to new table - done in
574 // copyPreservedApnsToNewTable()
575 // The only exception if upgrading from version 14 is that EDITED field is already
576 // present (but is called USER_EDITED)
Amit Mahajand4091e02015-10-28 12:32:28 -0700577 /*********************************************************************************
578 * IMPORTANT NOTE: SINCE CARRIERS TABLE IS RECREATED HERE, IT WILL BE THE LATEST
579 * VERSION AFTER THIS. AS A RESULT ANY SUBSEQUENT UPDATES TO THE TABLE WILL FAIL
580 * (DUE TO COLUMN-ALREADY-EXISTS KIND OF EXCEPTION). ALL SUBSEQUENT UPDATES SHOULD
581 * HANDLE THAT GRACEFULLY.
582 *********************************************************************************/
Amit Mahajan899cc602015-05-14 17:22:09 -0700583 Cursor c;
584 String[] proj = {"_id"};
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800585 if (VDBG) {
Amit Mahajan899cc602015-05-14 17:22:09 -0700586 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800587 log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount());
588 }
Amit Mahajan899cc602015-05-14 17:22:09 -0700589
590 // Compare db with old apns xml file so that any user or carrier edited/added
591 // entries can be preserved across upgrade
592 preserveUserAndCarrierApns(db);
593
594 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null);
595
596 if (VDBG) {
597 log("dbh.onUpgrade:- after preserveUserAndCarrierApns() total number of " +
598 "rows: " + ((c == null) ? 0 : c.getCount()));
599 }
600
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800601 createCarriersTable(db, CARRIERS_TABLE_TMP);
602
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700603 copyPreservedApnsToNewTable(db, c);
Amit Mahajan899cc602015-05-14 17:22:09 -0700604 c.close();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800605
606 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE);
607
608 db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE +
609 ";");
610
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800611 if (VDBG) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800612 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
613 log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount());
614 c.close();
Amit Mahajanb80f7332015-04-16 10:02:52 -0700615 c = db.query(CARRIERS_TABLE, proj, "edited=" + Telephony.Carriers.UNEDITED,
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800616 null, null, null, null);
Amit Mahajanb80f7332015-04-16 10:02:52 -0700617 log("dbh.onUpgrade:- after upgrading total number of rows with edited="
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700618 + Telephony.Carriers.UNEDITED + ": " + c.getCount());
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800619 c.close();
Amit Mahajanb80f7332015-04-16 10:02:52 -0700620 c = db.query(CARRIERS_TABLE, proj, "edited!=" + Telephony.Carriers.UNEDITED,
621 null, null, null, null);
622 log("dbh.onUpgrade:- after upgrading total number of rows with edited!="
623 + Telephony.Carriers.UNEDITED + ": " + c.getCount());
Amit Mahajan899cc602015-05-14 17:22:09 -0700624 c.close();
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800625 }
Amit Mahajanb80f7332015-04-16 10:02:52 -0700626
627 oldVersion = 15 << 16 | 6;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800628 }
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700629 if (oldVersion < (16 << 16 | 6)) {
630 try {
631 // Try to update the siminfo table. It might not be there.
632 // These columns may already be present in which case execSQL will throw an
633 // exception
634 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
635 + SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1;");
636 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
637 + SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1;");
638 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
639 + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1;");
640 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
641 + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;");
642 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
643 + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4;");
644 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
645 + SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0;");
646 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
647 + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;");
648 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
649 + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1;");
650 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
651 + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0;");
652 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
653 + SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1;");
654 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Sridhar Dubbaka0398c4f2015-09-22 22:23:59 +0530655 + SubscriptionManager.CB_CHANNEL_60_ALERT + " INTEGER DEFAULT 1;");
656 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
Sridhar Dubbaka1da42e52015-10-21 14:16:44 +0530657 + SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 1;");
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700658 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
659 + SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1;");
660 } catch (SQLiteException e) {
661 if (DBG) {
662 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
663 " The table will get created in onOpen.");
664 }
665 }
666 oldVersion = 16 << 16 | 6;
667 }
Amit Mahajanda607212015-10-08 09:13:00 -0700668 if (oldVersion < (17 << 16 | 6)) {
Amit Mahajand4091e02015-10-28 12:32:28 -0700669 Cursor c = null;
670 try {
671 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null,
672 String.valueOf(1));
673 if (c == null || c.getColumnIndex(Telephony.Carriers.USER_VISIBLE) == -1) {
674 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
675 Telephony.Carriers.USER_VISIBLE + " BOOLEAN DEFAULT 1;");
676 } else {
677 if (DBG) {
678 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. Column " +
679 Telephony.Carriers.USER_VISIBLE + " already exists.");
680 }
681 }
682 } finally {
683 if (c != null) {
684 c.close();
685 }
686 }
Amit Mahajanda607212015-10-08 09:13:00 -0700687 oldVersion = 17 << 16 | 6;
688 }
Wink Saville6de10272014-06-22 07:38:43 -0700689 if (DBG) {
690 log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
691 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800692 }
693
Amit Mahajan899cc602015-05-14 17:22:09 -0700694 private void preserveUserAndCarrierApns(SQLiteDatabase db) {
695 if (VDBG) log("preserveUserAndCarrierApns");
696 XmlPullParser confparser;
697 File confFile = new File(Environment.getRootDirectory(), OLD_APNS_PATH);
698 FileReader confreader = null;
699 try {
700 confreader = new FileReader(confFile);
701 confparser = Xml.newPullParser();
702 confparser.setInput(confreader);
703 XmlUtils.beginDocument(confparser, "apns");
704
705 deleteMatchingApns(db, confparser);
706 } catch (FileNotFoundException e) {
707 // This function is called only when upgrading db to version 15. Details about the
708 // upgrade are mentioned in onUpgrade(). This file missing means user/carrier added
709 // APNs cannot be preserved. Throw an exception so that OEMs know they need to
710 // include old apns file for comparison.
711 loge("preserveUserAndCarrierApns: FileNotFoundException");
712 throw new RuntimeException("preserveUserAndCarrierApns: " + OLD_APNS_PATH +
713 " not found. It is needed to upgrade from older versions of APN " +
714 "db while preserving user/carrier added/edited entries.");
715 } catch (Exception e) {
716 loge("preserveUserAndCarrierApns: Exception while parsing '" +
717 confFile.getAbsolutePath() + "'" + e);
718 } finally {
719 if (confreader != null) {
720 try {
721 confreader.close();
722 } catch (IOException e) {
723 // do nothing
724 }
725 }
726 }
727 }
728
729 private void deleteMatchingApns(SQLiteDatabase db, XmlPullParser parser) {
730 if (VDBG) log("deleteMatchingApns");
731 if (parser != null) {
732 if (VDBG) log("deleteMatchingApns: parser != null");
733 try {
734 XmlUtils.nextElement(parser);
735 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
736 ContentValues row = getRow(parser);
737 if (row == null) {
738 throw new XmlPullParserException("Expected 'apn' tag", parser, null);
739 }
740 deleteRow(db, row);
741 XmlUtils.nextElement(parser);
742 }
743 } catch (XmlPullParserException e) {
744 loge("deleteMatchingApns: Got XmlPullParserException while deleting apns." + e);
745 } catch (IOException e) {
746 loge("deleteMatchingApns: Got IOException while deleting apns." + e);
747 } catch (SQLException e) {
748 loge("deleteMatchingApns: Got SQLException while deleting apns." + e);
749 }
750 }
751 }
752
753 private void deleteRow(SQLiteDatabase db, ContentValues values) {
754 if (VDBG) log("deleteRow");
755 String where = "numeric=? and mcc=? and mnc=? and name=? and " +
756 "(apn=? or apn is null) and " +
757 "(user=? or user is null) and (server=? or server is null) and " +
758 "(password=? or password is null) and (proxy=? or proxy is null) and " +
759 "(port=? or port is null) and (mmsproxy=? or mmsproxy is null) and " +
760 "(mmsport=? or mmsport is null) and (mmsc=? or mmsc is null) and " +
761 "(authtype=? or authtype is null) and (type=? or type is null) and " +
762 "(protocol=? or protocol is null) and " +
763 "(roaming_protocol=? or roaming_protocol is null) and " +
764 "(carrier_enabled=? or carrier_enabled=? or carrier_enabled is null) and " +
765 "(bearer=? or bearer is null) and (mvno_type=? or mvno_type is null) and " +
766 "(mvno_match_data=? or mvno_match_data is null) and " +
767 "(profile_id=? or profile_id is null) and " +
768 "(modem_cognitive=? or modem_cognitive=? or modem_cognitive is null) and " +
769 "(max_conns=? or max_conns is null) and " +
770 "(wait_time=? or wait_time is null) and " +
771 "(max_conns_time=? or max_conns_time is null) and (mtu=? or mtu is null)";
772 String[] whereArgs = new String[29];
773 int i = 0;
774 whereArgs[i++] = values.getAsString(Telephony.Carriers.NUMERIC);
775 whereArgs[i++] = values.getAsString(Telephony.Carriers.MCC);
776 whereArgs[i++] = values.getAsString(Telephony.Carriers.MNC);
777 whereArgs[i++] = values.getAsString(Telephony.Carriers.NAME);
778 whereArgs[i++] = values.containsKey(Telephony.Carriers.APN) ?
779 values.getAsString(Telephony.Carriers.APN) : "";
780 whereArgs[i++] = values.containsKey(Telephony.Carriers.USER) ?
781 values.getAsString(Telephony.Carriers.USER) : "";
782 whereArgs[i++] = values.containsKey(Telephony.Carriers.SERVER) ?
783 values.getAsString(Telephony.Carriers.SERVER) : "";
784 whereArgs[i++] = values.containsKey(Telephony.Carriers.PASSWORD) ?
785 values.getAsString(Telephony.Carriers.PASSWORD) : "";
786 whereArgs[i++] = values.containsKey(Telephony.Carriers.PROXY) ?
787 values.getAsString(Telephony.Carriers.PROXY) : "";
788 whereArgs[i++] = values.containsKey(Telephony.Carriers.PORT) ?
789 values.getAsString(Telephony.Carriers.PORT) : "";
790 whereArgs[i++] = values.containsKey(Telephony.Carriers.MMSPROXY) ?
791 values.getAsString(Telephony.Carriers.MMSPROXY) : "";
792 whereArgs[i++] = values.containsKey(Telephony.Carriers.MMSPORT) ?
793 values.getAsString(Telephony.Carriers.MMSPORT) : "";
794 whereArgs[i++] = values.containsKey(Telephony.Carriers.MMSC) ?
795 values.getAsString(Telephony.Carriers.MMSC) : "";
796 whereArgs[i++] = values.containsKey(Telephony.Carriers.AUTH_TYPE) ?
797 values.getAsString(Telephony.Carriers.AUTH_TYPE) : "-1";
798 whereArgs[i++] = values.containsKey(Telephony.Carriers.TYPE) ?
799 values.getAsString(Telephony.Carriers.TYPE) : "";
800 whereArgs[i++] = values.containsKey(Telephony.Carriers.PROTOCOL) ?
801 values.getAsString(Telephony.Carriers.PROTOCOL) : "IP";
802 whereArgs[i++] = values.containsKey(Telephony.Carriers.ROAMING_PROTOCOL) ?
803 values.getAsString(Telephony.Carriers.ROAMING_PROTOCOL) : "IP";
804
805 if (values.containsKey(Telephony.Carriers.CARRIER_ENABLED) &&
806 (values.getAsString(Telephony.Carriers.CARRIER_ENABLED).
807 equalsIgnoreCase("false") ||
808 values.getAsString(Telephony.Carriers.CARRIER_ENABLED).equals("0"))) {
809 whereArgs[i++] = "false";
810 whereArgs[i++] = "0";
811 } else {
812 whereArgs[i++] = "true";
813 whereArgs[i++] = "1";
814 }
815
816 whereArgs[i++] = values.containsKey(Telephony.Carriers.BEARER) ?
817 values.getAsString(Telephony.Carriers.BEARER) : "0";
818 whereArgs[i++] = values.containsKey(Telephony.Carriers.MVNO_TYPE) ?
819 values.getAsString(Telephony.Carriers.MVNO_TYPE) : "";
820 whereArgs[i++] = values.containsKey(Telephony.Carriers.MVNO_MATCH_DATA) ?
821 values.getAsString(Telephony.Carriers.MVNO_MATCH_DATA) : "";
822 whereArgs[i++] = values.containsKey(Telephony.Carriers.PROFILE_ID) ?
823 values.getAsString(Telephony.Carriers.PROFILE_ID) : "0";
824
825 if (values.containsKey(Telephony.Carriers.MODEM_COGNITIVE) &&
826 (values.getAsString(Telephony.Carriers.MODEM_COGNITIVE).
827 equalsIgnoreCase("true") ||
828 values.getAsString(Telephony.Carriers.MODEM_COGNITIVE).equals("1"))) {
829 whereArgs[i++] = "true";
830 whereArgs[i++] = "1";
831 } else {
832 whereArgs[i++] = "false";
833 whereArgs[i++] = "0";
834 }
835
836 whereArgs[i++] = values.containsKey(Telephony.Carriers.MAX_CONNS) ?
837 values.getAsString(Telephony.Carriers.MAX_CONNS) : "0";
838 whereArgs[i++] = values.containsKey(Telephony.Carriers.WAIT_TIME) ?
839 values.getAsString(Telephony.Carriers.WAIT_TIME) : "0";
840 whereArgs[i++] = values.containsKey(Telephony.Carriers.MAX_CONNS_TIME) ?
841 values.getAsString(Telephony.Carriers.MAX_CONNS_TIME) : "0";
842 whereArgs[i++] = values.containsKey(Telephony.Carriers.MTU) ?
843 values.getAsString(Telephony.Carriers.MTU) : "0";
844
845 if (VDBG) {
846 log("deleteRow: where: " + where);
847
848 StringBuilder builder = new StringBuilder();
849 for (String s : whereArgs) {
850 builder.append(s + ", ");
851 }
852
853 log("deleteRow: whereArgs: " + builder.toString());
854 }
855 db.delete(CARRIERS_TABLE, where, whereArgs);
856 }
857
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700858 private void copyPreservedApnsToNewTable(SQLiteDatabase db, Cursor c) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700859 // Move entries from CARRIERS_TABLE to CARRIERS_TABLE_TMP
860 if (c != null) {
861 String[] persistApnsForPlmns = mContext.getResources().getStringArray(
862 R.array.persist_apns_for_plmn);
863 while (c.moveToNext()) {
Amit Mahajan899cc602015-05-14 17:22:09 -0700864 ContentValues cv = new ContentValues();
865 String val;
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700866
Amit Mahajan899cc602015-05-14 17:22:09 -0700867 // Include only non-null values in cv so that null values can be replaced
868 // with default if there's a default value for the field
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700869
Amit Mahajan899cc602015-05-14 17:22:09 -0700870 // String vals
871 getStringValueFromCursor(cv, c, Telephony.Carriers.NAME);
872 getStringValueFromCursor(cv, c, Telephony.Carriers.NUMERIC);
873 getStringValueFromCursor(cv, c, Telephony.Carriers.MCC);
874 getStringValueFromCursor(cv, c, Telephony.Carriers.MNC);
875 getStringValueFromCursor(cv, c, Telephony.Carriers.APN);
876 getStringValueFromCursor(cv, c, Telephony.Carriers.USER);
877 getStringValueFromCursor(cv, c, Telephony.Carriers.SERVER);
878 getStringValueFromCursor(cv, c, Telephony.Carriers.PASSWORD);
879 getStringValueFromCursor(cv, c, Telephony.Carriers.PROXY);
880 getStringValueFromCursor(cv, c, Telephony.Carriers.PORT);
881 getStringValueFromCursor(cv, c, Telephony.Carriers.MMSPROXY);
882 getStringValueFromCursor(cv, c, Telephony.Carriers.MMSPORT);
883 getStringValueFromCursor(cv, c, Telephony.Carriers.MMSC);
884 getStringValueFromCursor(cv, c, Telephony.Carriers.TYPE);
885 getStringValueFromCursor(cv, c, Telephony.Carriers.PROTOCOL);
886 getStringValueFromCursor(cv, c, Telephony.Carriers.ROAMING_PROTOCOL);
887 getStringValueFromCursor(cv, c, Telephony.Carriers.MVNO_TYPE);
888 getStringValueFromCursor(cv, c, Telephony.Carriers.MVNO_MATCH_DATA);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700889
Amit Mahajan899cc602015-05-14 17:22:09 -0700890 // bool/int vals
891 getIntValueFromCursor(cv, c, Telephony.Carriers.AUTH_TYPE);
892 getIntValueFromCursor(cv, c, Telephony.Carriers.CURRENT);
893 getIntValueFromCursor(cv, c, Telephony.Carriers.CARRIER_ENABLED);
894 getIntValueFromCursor(cv, c, Telephony.Carriers.BEARER);
895 getIntValueFromCursor(cv, c, Telephony.Carriers.SUBSCRIPTION_ID);
896 getIntValueFromCursor(cv, c, Telephony.Carriers.PROFILE_ID);
897 getIntValueFromCursor(cv, c, Telephony.Carriers.MODEM_COGNITIVE);
898 getIntValueFromCursor(cv, c, Telephony.Carriers.MAX_CONNS);
899 getIntValueFromCursor(cv, c, Telephony.Carriers.WAIT_TIME);
900 getIntValueFromCursor(cv, c, Telephony.Carriers.MAX_CONNS_TIME);
901 getIntValueFromCursor(cv, c, Telephony.Carriers.MTU);
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700902
Amit Mahajan899cc602015-05-14 17:22:09 -0700903 // Change bearer to a bitmask
904 String bearerStr = c.getString(c.getColumnIndex(Telephony.Carriers.BEARER));
905 if (!TextUtils.isEmpty(bearerStr)) {
906 int bearer_bitmask = ServiceState.getBitmaskForTech(
907 Integer.parseInt(bearerStr));
908 cv.put(Telephony.Carriers.BEARER_BITMASK, bearer_bitmask);
909 }
910
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700911 int userEditedColumnIdx = c.getColumnIndex("user_edited");
912 if (userEditedColumnIdx != -1) {
913 String user_edited = c.getString(userEditedColumnIdx);
Amit Mahajan899cc602015-05-14 17:22:09 -0700914 if (!TextUtils.isEmpty(user_edited)) {
915 cv.put(Telephony.Carriers.EDITED, new Integer(user_edited));
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700916 }
Amit Mahajan899cc602015-05-14 17:22:09 -0700917 } else {
918 cv.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
919 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700920
Amit Mahajan899cc602015-05-14 17:22:09 -0700921 // New EDITED column. Default value (Telephony.Carriers.UNEDITED) will
922 // be used for all rows except for non-mvno entries for plmns indicated
923 // by resource: those will be set to CARRIER_EDITED to preserve
924 // their current values
925 val = c.getString(c.getColumnIndex(Telephony.Carriers.NUMERIC));
926 for (String s : persistApnsForPlmns) {
927 if (!TextUtils.isEmpty(val) && val.equals(s) &&
928 (!cv.containsKey(Telephony.Carriers.MVNO_TYPE) ||
929 TextUtils.isEmpty(cv.getAsString(Telephony.Carriers.
930 MVNO_TYPE)))) {
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700931 if (userEditedColumnIdx == -1) {
Amit Mahajan899cc602015-05-14 17:22:09 -0700932 cv.put(Telephony.Carriers.EDITED,
933 Telephony.Carriers.CARRIER_EDITED);
Sanket Padaweb6fe0852015-07-13 13:37:48 -0700934 } else { // if (oldVersion == 14) -- if db had user_edited column
Amit Mahajan899cc602015-05-14 17:22:09 -0700935 if (cv.getAsInteger(Telephony.Carriers.EDITED) ==
936 Telephony.Carriers.USER_EDITED) {
Amit Mahajanb80f7332015-04-16 10:02:52 -0700937 cv.put(Telephony.Carriers.EDITED,
938 Telephony.Carriers.CARRIER_EDITED);
Amit Mahajanb80f7332015-04-16 10:02:52 -0700939 }
Amit Mahajan899cc602015-05-14 17:22:09 -0700940 }
Amit Mahajanb80f7332015-04-16 10:02:52 -0700941
Amit Mahajan899cc602015-05-14 17:22:09 -0700942 break;
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700943 }
944 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700945
Amit Mahajan899cc602015-05-14 17:22:09 -0700946 try {
947 db.insertWithOnConflict(CARRIERS_TABLE_TMP, null, cv,
948 SQLiteDatabase.CONFLICT_ABORT);
949 if (VDBG) {
950 log("dbh.copyPreservedApnsToNewTable: db.insert returned >= 0; " +
951 "insert successful for cv " + cv);
952 }
953 } catch (SQLException e) {
954 if (VDBG)
955 log("dbh.copyPreservedApnsToNewTable insertWithOnConflict exception " +
956 e + " for cv " + cv);
957 // Insertion failed which could be due to a conflict. Check if that is
958 // the case and merge the entries
959 Cursor oldRow = DatabaseHelper.selectConflictingRow(db,
960 CARRIERS_TABLE_TMP, cv);
961 if (oldRow != null) {
962 ContentValues mergedValues = new ContentValues();
963 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE_TMP, oldRow, cv,
964 mergedValues, true, mContext);
965 oldRow.close();
Amit Mahajanb80f7332015-04-16 10:02:52 -0700966 }
967 }
968 }
969 }
Amit Mahajanb80f7332015-04-16 10:02:52 -0700970 }
971
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700972 private void getStringValueFromCursor(ContentValues cv, Cursor c, String key) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800973 String fromCursor = c.getString(c.getColumnIndex(key));
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700974 if (!TextUtils.isEmpty(fromCursor)) {
975 cv.put(key, fromCursor);
976 }
977 }
978
979 private void getIntValueFromCursor(ContentValues cv, Cursor c, String key) {
980 String fromCursor = c.getString(c.getColumnIndex(key));
981 if (!TextUtils.isEmpty(fromCursor)) {
Amit Mahajan24223db2015-04-21 14:22:40 -0700982 try {
983 cv.put(key, new Integer(fromCursor));
984 } catch (NumberFormatException nfe) {
985 // do nothing
986 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -0700987 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -0800988 }
989
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800990 /**
991 * Gets the next row of apn values.
992 *
993 * @param parser the parser
994 * @return the row or null if it's not an apn
995 */
996 private ContentValues getRow(XmlPullParser parser) {
997 if (!"apn".equals(parser.getName())) {
998 return null;
999 }
1000
1001 ContentValues map = new ContentValues();
1002
1003 String mcc = parser.getAttributeValue(null, "mcc");
1004 String mnc = parser.getAttributeValue(null, "mnc");
1005 String numeric = mcc + mnc;
1006
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001007 map.put(Telephony.Carriers.NUMERIC, numeric);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001008 map.put(Telephony.Carriers.MCC, mcc);
1009 map.put(Telephony.Carriers.MNC, mnc);
1010 map.put(Telephony.Carriers.NAME, parser.getAttributeValue(null, "carrier"));
kaiyizdeeba8b2014-07-31 15:25:30 +08001011 map.put(mContext.getString(R.string.ppp_number),
1012 parser.getAttributeValue(null, "ppp_number"));
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001013
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001014 // do not add NULL to the map so that default values can be inserted in db
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001015 addStringAttribute(parser, "apn", map, Telephony.Carriers.APN);
1016 addStringAttribute(parser, "user", map, Telephony.Carriers.USER);
1017 addStringAttribute(parser, "server", map, Telephony.Carriers.SERVER);
1018 addStringAttribute(parser, "password", map, Telephony.Carriers.PASSWORD);
1019 addStringAttribute(parser, "proxy", map, Telephony.Carriers.PROXY);
1020 addStringAttribute(parser, "port", map, Telephony.Carriers.PORT);
1021 addStringAttribute(parser, "mmsproxy", map, Telephony.Carriers.MMSPROXY);
1022 addStringAttribute(parser, "mmsport", map, Telephony.Carriers.MMSPORT);
1023 addStringAttribute(parser, "mmsc", map, Telephony.Carriers.MMSC);
1024 addStringAttribute(parser, "type", map, Telephony.Carriers.TYPE);
1025 addStringAttribute(parser, "protocol", map, Telephony.Carriers.PROTOCOL);
1026 addStringAttribute(parser, "roaming_protocol", map, Telephony.Carriers.ROAMING_PROTOCOL);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001027
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001028 addIntAttribute(parser, "authtype", map, Telephony.Carriers.AUTH_TYPE);
1029 addIntAttribute(parser, "bearer", map, Telephony.Carriers.BEARER);
1030 addIntAttribute(parser, "profile_id", map, Telephony.Carriers.PROFILE_ID);
1031 addIntAttribute(parser, "max_conns", map, Telephony.Carriers.MAX_CONNS);
1032 addIntAttribute(parser, "wait_time", map, Telephony.Carriers.WAIT_TIME);
1033 addIntAttribute(parser, "max_conns_time", map, Telephony.Carriers.MAX_CONNS_TIME);
1034 addIntAttribute(parser, "mtu", map, Telephony.Carriers.MTU);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001035
Amit Mahajanda607212015-10-08 09:13:00 -07001036
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001037 addBoolAttribute(parser, "carrier_enabled", map, Telephony.Carriers.CARRIER_ENABLED);
1038 addBoolAttribute(parser, "modem_cognitive", map, Telephony.Carriers.MODEM_COGNITIVE);
Amit Mahajanda607212015-10-08 09:13:00 -07001039 addBoolAttribute(parser, "user_visible", map, Telephony.Carriers.USER_VISIBLE);
kaiyize93034a2014-07-31 15:50:20 +08001040 addBoolAttribute(parser, "read_only", map, mContext.getString(R.string.read_only));
Sungmin Choi27045ef2013-01-25 17:48:06 +09001041
Amit Mahajanb80f7332015-04-16 10:02:52 -07001042 String bearerList = parser.getAttributeValue(null, "bearer_bitmask");
1043 if (bearerList != null) {
1044 int bearerBitmask = ServiceState.getBitmaskFromString(bearerList);
1045 map.put(Telephony.Carriers.BEARER_BITMASK, bearerBitmask);
1046 }
1047
Sungmin Choi27045ef2013-01-25 17:48:06 +09001048 String mvno_type = parser.getAttributeValue(null, "mvno_type");
1049 if (mvno_type != null) {
1050 String mvno_match_data = parser.getAttributeValue(null, "mvno_match_data");
1051 if (mvno_match_data != null) {
1052 map.put(Telephony.Carriers.MVNO_TYPE, mvno_type);
1053 map.put(Telephony.Carriers.MVNO_MATCH_DATA, mvno_match_data);
1054 }
1055 }
Amit Mahajanb0688862014-08-13 16:53:51 +00001056
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001057 return map;
1058 }
1059
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001060 private void addStringAttribute(XmlPullParser parser, String att,
1061 ContentValues map, String key) {
1062 String val = parser.getAttributeValue(null, att);
1063 if (val != null) {
1064 map.put(key, val);
1065 }
1066 }
1067
1068 private void addIntAttribute(XmlPullParser parser, String att,
1069 ContentValues map, String key) {
1070 String val = parser.getAttributeValue(null, att);
1071 if (val != null) {
1072 map.put(key, Integer.parseInt(val));
1073 }
1074 }
1075
1076 private void addBoolAttribute(XmlPullParser parser, String att,
1077 ContentValues map, String key) {
1078 String val = parser.getAttributeValue(null, att);
1079 if (val != null) {
1080 map.put(key, Boolean.parseBoolean(val));
1081 }
1082 }
1083
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001084 /*
1085 * Loads apns from xml file into the database
1086 *
1087 * @param db the sqlite database to write to
1088 * @param parser the xml parser
1089 *
1090 */
1091 private void loadApns(SQLiteDatabase db, XmlPullParser parser) {
1092 if (parser != null) {
1093 try {
jewon.lee4167fcc2013-01-17 13:10:37 +09001094 db.beginTransaction();
Hyejin Kim7e7c2742013-02-11 20:02:18 +09001095 XmlUtils.nextElement(parser);
1096 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001097 ContentValues row = getRow(parser);
Hyejin Kim7e7c2742013-02-11 20:02:18 +09001098 if (row == null) {
1099 throw new XmlPullParserException("Expected 'apn' tag", parser, null);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001100 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001101 insertAddingDefaults(db, row);
Hyejin Kim7e7c2742013-02-11 20:02:18 +09001102 XmlUtils.nextElement(parser);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001103 }
jewon.lee4167fcc2013-01-17 13:10:37 +09001104 db.setTransactionSuccessful();
Hyejin Kim7e7c2742013-02-11 20:02:18 +09001105 } catch (XmlPullParserException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001106 loge("Got XmlPullParserException while loading apns." + e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001107 } catch (IOException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001108 loge("Got IOException while loading apns." + e);
Hyejin Kim7e7c2742013-02-11 20:02:18 +09001109 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001110 loge("Got SQLException while loading apns." + e);
jewon.lee4167fcc2013-01-17 13:10:37 +09001111 } finally {
1112 db.endTransaction();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001113 }
1114 }
1115 }
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07001116
Susheel nyamala132b0432015-05-08 17:57:50 +05301117 /*
1118 * Read apns from regional xml file one by one and update them to database
1119 * - Replace apn if a match is found from telephony database,
1120 * - Add apn if there is no match found from database
1121 * @param db the sqlite database to write to
1122 * @param parser the xml parser
1123 *
1124 */
1125 private void loadRegionalApns(SQLiteDatabase db, XmlPullParser parser) {
1126 if (DBG) log("Reading regional apns file");
1127
1128 try {
1129 String[] apnParams = {Telephony.Carriers.NUMERIC,
1130 Telephony.Carriers.APN,
1131 Telephony.Carriers.NAME,
1132 Telephony.Carriers.TYPE};
1133
1134 db.beginTransaction();
1135 XmlUtils.nextElement(parser);
1136 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
1137 boolean apnModified = false;
1138 ContentValues row = getRow(parser);
1139 if (row == null) {
1140 throw new XmlPullParserException("Expected 'apn' tag", parser, null);
1141 }
1142 row = setDefaultValue(row);
1143
1144 String apnOperation = parser.getAttributeValue(null, "operation");
1145 if (DBG) log("loadRegionalApns: operation on apn: " + apnOperation);
1146
1147 /* Construct sqlite query with numeric and apn of xml entry and
1148 * run it on telephony db.
1149 * If a unique match is found, replace it with the apn from xml file.
1150 * Else if multiple apn entries are found with this query,
1151 * re-execute query by adding name, type parameters as well.
1152 * If multiple apn entries are still found with all of these fields, just
1153 * add apn to db.
1154 */
1155 String selection = apnParams[0] + "=" + row.getAsString(apnParams[0]);
1156 for (int i = 0; i < apnParams.length-1; i++) {
1157 selection += " AND " + apnParams[i+1] + "=?";
1158 if (DBG) log("loadRegionalApns: selection: " + selection);
1159
1160 //Create a selectionArgs array with values to be passed to sqlite query
1161 String selectionArgs[] = new String[i+1];
1162 for (int j = 0; j <= i; j++) {
1163 selectionArgs[j] = (row.getAsString(apnParams[j+1])).trim();
1164 if (DBG) log("loadRegionalApns: selectionArgs: " + selectionArgs[j]);
1165 }
1166
1167 int result = formatApnsInDB(db, row, selection, selectionArgs,
1168 apnOperation);
1169 if (result <= 1) {
1170 apnModified = true;
1171 break;
1172 }
1173 }
1174
1175 if (!apnModified && (apnOperation != null &&
1176 !apnOperation.equalsIgnoreCase("delete"))) {
1177 if (DBG) log("loadRegionalApns: Multiple apns found" +
1178 " in Telephony Database." +
1179 " Adding regional apn as a new entry");
1180 db.insertWithOnConflict(CARRIERS_TABLE, null, row,
1181 SQLiteDatabase.CONFLICT_ABORT);
1182 }
1183 XmlUtils.nextElement(parser);
1184 }
1185 db.setTransactionSuccessful();
1186 } catch (XmlPullParserException e) {
1187 loge("Got XmlPullParserException while loading apns." + e);
1188 } catch (IOException e) {
1189 loge("Got IOException while loading apns." + e);
1190 } catch (SQLException e) {
1191 loge("Got SQLException while loading apns." + e);
1192 } finally {
1193 db.endTransaction();
1194 }
1195 }
1196
1197 private int formatApnsInDB(SQLiteDatabase db, ContentValues row,
1198 String selection, String[] selectionArgs, String operation) {
1199 int apnCount = 0;
1200 String apn = selectionArgs[0];
1201
1202 try {
1203 Cursor cursor = db.query(CARRIERS_TABLE, null, selection,
1204 selectionArgs, null, null, null);
1205 if (cursor != null) {
1206 apnCount = cursor.getCount();
1207 if (VDBG) log("apn count: " + apnCount);
1208 if (apnCount > 1) {
1209 if (DBG) log("Multiple apns found in db with same values");
1210 } else if (apnCount == 1) {
1211 if (operation != null) {
1212 if (operation.equalsIgnoreCase("delete")) {
1213 if (DBG) log("Deleting apn in db: " + apn);
1214 db.delete(CARRIERS_TABLE, selection, selectionArgs);
1215 } else if (operation.equalsIgnoreCase("add")) {
1216 if (DBG) log("Adding regional apn to db: " + apn);
1217 db.insertWithOnConflict(CARRIERS_TABLE, null, row,
1218 SQLiteDatabase.CONFLICT_REPLACE);
1219 }
1220 } else {
1221 if (DBG) log("Replacing apn in db with regional apn: " + apn);
1222 db.delete(CARRIERS_TABLE, selection, selectionArgs);
1223 db.insertWithOnConflict(CARRIERS_TABLE, null, row,
1224 SQLiteDatabase.CONFLICT_ABORT);
1225 }
1226 } else {
1227 if (!(operation != null &&
1228 operation.equalsIgnoreCase("delete"))) {
1229 if (DBG) log("Adding regional apn to db: " + apn);
1230 db.insertWithOnConflict(CARRIERS_TABLE, null, row,
1231 SQLiteDatabase.CONFLICT_REPLACE);
1232 }
1233 }
1234 cursor.close();
1235 }
1236 } catch (SQLException e) {
1237 loge("Got SQLException while loading apns." + e);
1238 }
1239
1240 return apnCount;
1241 }
1242
Amit Mahajanb0688862014-08-13 16:53:51 +00001243 static public ContentValues setDefaultValue(ContentValues values) {
Wink Saville72b14732014-11-20 13:06:04 -08001244 if (!values.containsKey(Telephony.Carriers.SUBSCRIPTION_ID)) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001245 int subId = SubscriptionManager.getDefaultSubId();
Wink Saville72b14732014-11-20 13:06:04 -08001246 values.put(Telephony.Carriers.SUBSCRIPTION_ID, subId);
Amit Mahajanb0688862014-08-13 16:53:51 +00001247 }
1248
Amit Mahajanb0688862014-08-13 16:53:51 +00001249 return values;
1250 }
1251
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001252 private void insertAddingDefaults(SQLiteDatabase db, ContentValues row) {
Amit Mahajanb0688862014-08-13 16:53:51 +00001253 row = setDefaultValue(row);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001254 try {
1255 db.insertWithOnConflict(CARRIERS_TABLE, null, row,
1256 SQLiteDatabase.CONFLICT_ABORT);
1257 if (VDBG) log("dbh.insertAddingDefaults: db.insert returned >= 0; insert " +
1258 "successful for cv " + row);
1259 } catch (SQLException e) {
1260 if (VDBG) log("dbh.insertAddingDefaults: exception " + e);
1261 // Insertion failed which could be due to a conflict. Check if that is the case and
Amit Mahajanb80f7332015-04-16 10:02:52 -07001262 // update edited field accordingly.
1263 // Search for the exact same entry and update edited field.
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001264 // If it is USER_EDITED/CARRIER_EDITED change it to UNEDITED,
1265 // and if USER/CARRIER_DELETED change it to USER/CARRIER_DELETED_BUT_PRESENT_IN_XML.
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001266 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, row);
1267 if (oldRow != null) {
1268 // Update the row
1269 ContentValues mergedValues = new ContentValues();
Amit Mahajanb80f7332015-04-16 10:02:52 -07001270 int edited = oldRow.getInt(oldRow.getColumnIndex(
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001271 Telephony.Carriers.EDITED));
Amit Mahajanb80f7332015-04-16 10:02:52 -07001272 int old_edited = edited;
1273 if (edited != Telephony.Carriers.UNEDITED) {
1274 if (edited == Telephony.Carriers.USER_DELETED) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001275 // USER_DELETED_BUT_PRESENT_IN_XML indicates entry has been deleted
1276 // by user but present in apn xml file.
Amit Mahajanb80f7332015-04-16 10:02:52 -07001277 edited = Telephony.Carriers.USER_DELETED_BUT_PRESENT_IN_XML;
1278 } else if (edited == Telephony.Carriers.CARRIER_DELETED) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001279 // CARRIER_DELETED_BUT_PRESENT_IN_XML indicates entry has been deleted
1280 // by user but present in apn xml file.
Amit Mahajanb80f7332015-04-16 10:02:52 -07001281 edited = Telephony.Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001282 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07001283 mergedValues.put(Telephony.Carriers.EDITED, edited);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001284 }
1285
Amit Mahajanb80f7332015-04-16 10:02:52 -07001286 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, row, mergedValues, false,
1287 mContext);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001288
Amit Mahajanb80f7332015-04-16 10:02:52 -07001289 if (VDBG) log("dbh.insertAddingDefaults: old edited = " + old_edited
1290 + " new edited = " + edited);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001291
1292 oldRow.close();
1293 }
1294 }
1295 }
1296
Amit Mahajanb80f7332015-04-16 10:02:52 -07001297 public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow,
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001298 ContentValues newRow, ContentValues mergedValues,
Amit Mahajanb80f7332015-04-16 10:02:52 -07001299 boolean onUpgrade, Context context) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001300 if (newRow.containsKey(Telephony.Carriers.TYPE)) {
1301 // Merge the types
1302 String oldType = oldRow.getString(oldRow.getColumnIndex(Telephony.Carriers.TYPE));
1303 String newType = newRow.getAsString(Telephony.Carriers.TYPE);
Amit Mahajanb80f7332015-04-16 10:02:52 -07001304
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001305 if (!oldType.equalsIgnoreCase(newType)) {
1306 if (oldType.equals("") || newType.equals("")) {
1307 newRow.put(Telephony.Carriers.TYPE, "");
1308 } else {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001309 String[] oldTypes = oldType.toLowerCase().split(",");
1310 String[] newTypes = newType.toLowerCase().split(",");
Amit Mahajanb80f7332015-04-16 10:02:52 -07001311
1312 if (VDBG) {
1313 log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
1314 oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
1315 Telephony.Carriers.BEARER_BITMASK)) +
1316 " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
1317 Telephony.Carriers.PROFILE_ID)) +
1318 " newRow " + newRow);
1319 }
1320
1321 // If separate rows are needed, do not need to merge any further
1322 if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes,
1323 newTypes)) {
1324 if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " +
1325 "true");
1326 return;
1327 }
1328
1329 // Merge the 2 types
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001330 ArrayList<String> mergedTypes = new ArrayList<String>();
1331 mergedTypes.addAll(Arrays.asList(oldTypes));
1332 for (String s : newTypes) {
1333 if (!mergedTypes.contains(s.trim())) {
1334 mergedTypes.add(s);
1335 }
1336 }
1337 StringBuilder mergedType = new StringBuilder();
1338 for (int i = 0; i < mergedTypes.size(); i++) {
1339 mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i));
1340 }
1341 newRow.put(Telephony.Carriers.TYPE, mergedType.toString());
1342 }
1343 }
1344 mergedValues.put(Telephony.Carriers.TYPE, newRow.getAsString(
1345 Telephony.Carriers.TYPE));
1346 }
1347
Amit Mahajanb80f7332015-04-16 10:02:52 -07001348 if (newRow.containsKey(Telephony.Carriers.BEARER_BITMASK)) {
1349 int oldBearer = oldRow.getInt(oldRow.getColumnIndex(Telephony.Carriers.
1350 BEARER_BITMASK));
1351 int newBearer = newRow.getAsInteger(Telephony.Carriers.BEARER_BITMASK);
1352 if (oldBearer != newBearer) {
1353 if (oldBearer == 0 || newBearer == 0) {
1354 newRow.put(Telephony.Carriers.BEARER_BITMASK, 0);
1355 } else {
1356 newRow.put(Telephony.Carriers.BEARER_BITMASK, (oldBearer | newBearer));
1357 }
1358 }
1359 mergedValues.put(Telephony.Carriers.BEARER_BITMASK, newRow.getAsInteger(
1360 Telephony.Carriers.BEARER_BITMASK));
1361 }
1362
1363 if (!onUpgrade) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001364 mergedValues.putAll(newRow);
1365 }
1366
Amit Mahajan3f637282015-04-30 16:30:21 -07001367 if (mergedValues.size() > 0) {
Amit Mahajana2f40df2015-04-30 14:03:07 -07001368 db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")),
1369 null);
Amit Mahajana2f40df2015-04-30 14:03:07 -07001370 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001371 }
1372
Amit Mahajanb80f7332015-04-16 10:02:52 -07001373 private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow,
1374 ContentValues newRow, Context context,
1375 String[] oldTypes, String[] newTypes) {
1376 // If this APN falls under persist_apns_for_plmn, and the
1377 // only difference between old type and new type is that one has dun, and
1378 // the APNs have profile_id 0 or not set, then set the profile_id to 1 for
1379 // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist
1380 // separately in db.
1381
1382 boolean match = false;
1383
1384 // Check if APN falls under persist_apns_for_plmn
1385 String[] persistApnsForPlmns = context.getResources().getStringArray(
1386 R.array.persist_apns_for_plmn);
1387 for (String s : persistApnsForPlmns) {
1388 if (s.equalsIgnoreCase(newRow.getAsString(Telephony.Carriers.
1389 NUMERIC))) {
1390 match = true;
1391 break;
1392 }
1393 }
1394
1395 if (!match) return false;
1396
1397 // APN falls under persist_apns_for_plmn
1398 // Check if only difference between old type and new type is that
1399 // one has dun
1400 ArrayList<String> oldTypesAl = new ArrayList<String>(
1401 Arrays.asList(oldTypes));
1402 ArrayList<String> newTypesAl = new ArrayList<String>(
1403 Arrays.asList(newTypes));
1404 ArrayList<String> listWithDun = null;
1405 ArrayList<String> listWithoutDun = null;
1406 boolean dunInOld = false;
1407 if (oldTypesAl.size() == newTypesAl.size() + 1) {
1408 listWithDun = oldTypesAl;
1409 listWithoutDun = newTypesAl;
1410 dunInOld = true;
1411 } else if (oldTypesAl.size() + 1 == newTypesAl.size()) {
1412 listWithDun = newTypesAl;
1413 listWithoutDun = oldTypesAl;
1414 } else {
1415 return false;
1416 }
1417
1418 if (listWithDun.contains("dun") &&
1419 !listWithoutDun.contains("dun")) {
1420 listWithoutDun.add("dun");
1421 if (!listWithDun.containsAll(listWithoutDun)) {
1422 return false;
1423 }
1424
1425 // Only difference between old type and new type is that
1426 // one has dun
1427 // Check if profile_id is 0/not set
1428 if (oldRow.getInt(oldRow.getColumnIndex(Telephony.Carriers.
1429 PROFILE_ID)) == 0) {
1430 if (dunInOld) {
1431 // Update oldRow to remove dun from its type field
1432 ContentValues updateOldRow = new ContentValues();
1433 StringBuilder sb = new StringBuilder();
1434 boolean first = true;
1435 for (String s : listWithDun) {
1436 if (!s.equalsIgnoreCase("dun")) {
1437 sb.append(first ? s : "," + s);
1438 first = false;
1439 }
1440 }
1441 String updatedType = sb.toString();
1442 if (VDBG) {
1443 log("separateRowsNeeded: updating type in oldRow to " +
1444 updatedType);
1445 }
1446 updateOldRow.put(Telephony.Carriers.TYPE, updatedType);
1447 db.update(table, updateOldRow,
1448 "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null);
1449 return true;
1450 } else {
1451 if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow");
1452 // Update newRow to set profile_id to 1
1453 newRow.put(Telephony.Carriers.PROFILE_ID,
1454 new Integer(1));
1455 }
1456 } else {
1457 return false;
1458 }
1459
1460 // If match was found, both oldRow and newRow need to exist
1461 // separately in db. Add newRow to db.
1462 try {
1463 db.insertWithOnConflict(table, null, newRow,
1464 SQLiteDatabase.CONFLICT_REPLACE);
1465 if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db");
1466 return true;
1467 } catch (SQLException e) {
1468 loge("Exception on trying to add new row after " +
1469 "updating profile_id");
1470 }
1471 }
1472
1473 return false;
1474 }
1475
1476 public static Cursor selectConflictingRow(SQLiteDatabase db, String table,
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001477 ContentValues row) {
Amit Mahajanbec84922015-04-13 10:16:43 -07001478 // Conflict is possible only when numeric, mcc, mnc (fields without any default value)
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001479 // are set in the new row
Amit Mahajanbec84922015-04-13 10:16:43 -07001480 if (!row.containsKey(Telephony.Carriers.NUMERIC) ||
1481 !row.containsKey(Telephony.Carriers.MCC) ||
1482 !row.containsKey(Telephony.Carriers.MNC)) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001483 loge("dbh.selectConflictingRow: called for non-conflicting row: " + row);
1484 return null;
1485 }
1486
Amit Mahajanb80f7332015-04-16 10:02:52 -07001487 String[] columns = { "_id",
1488 Telephony.Carriers.TYPE,
1489 Telephony.Carriers.EDITED,
1490 Telephony.Carriers.BEARER_BITMASK,
1491 Telephony.Carriers.PROFILE_ID };
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001492 String selection = "numeric=? AND mcc=? AND mnc=? AND apn=? AND proxy=? AND port=? "
1493 + "AND mmsproxy=? AND mmsport=? AND mmsc=? AND carrier_enabled=? AND bearer=? "
1494 + "AND mvno_type=? AND mvno_match_data=? AND profile_id=?";
1495 int i = 0;
1496 String[] selectionArgs = new String[14];
1497 selectionArgs[i++] = row.getAsString(Telephony.Carriers.NUMERIC);
1498 selectionArgs[i++] = row.getAsString(Telephony.Carriers.MCC);
1499 selectionArgs[i++] = row.getAsString(Telephony.Carriers.MNC);
1500 selectionArgs[i++] = row.containsKey(Telephony.Carriers.APN) ?
1501 row.getAsString(Telephony.Carriers.APN) : "";
1502 selectionArgs[i++] = row.containsKey(Telephony.Carriers.PROXY) ?
1503 row.getAsString(Telephony.Carriers.PROXY) : "";
1504 selectionArgs[i++] = row.containsKey(Telephony.Carriers.PORT) ?
1505 row.getAsString(Telephony.Carriers.PORT) : "";
1506 selectionArgs[i++] = row.containsKey(Telephony.Carriers.MMSPROXY) ?
1507 row.getAsString(Telephony.Carriers.MMSPROXY) : "";
1508 selectionArgs[i++] = row.containsKey(Telephony.Carriers.MMSPORT) ?
1509 row.getAsString(Telephony.Carriers.MMSPORT) : "";
1510 selectionArgs[i++] = row.containsKey(Telephony.Carriers.MMSC) ?
1511 row.getAsString(Telephony.Carriers.MMSC) : "";
1512 selectionArgs[i++] = row.containsKey(Telephony.Carriers.CARRIER_ENABLED) &&
1513 (row.getAsString(Telephony.Carriers.CARRIER_ENABLED).equals("0") ||
1514 row.getAsString(Telephony.Carriers.CARRIER_ENABLED).equals("false")) ?
1515 "0" : "1";
1516 selectionArgs[i++] = row.containsKey(Telephony.Carriers.BEARER) ?
1517 row.getAsString(Telephony.Carriers.BEARER) : "0";
1518 selectionArgs[i++] = row.containsKey(Telephony.Carriers.MVNO_TYPE) ?
1519 row.getAsString(Telephony.Carriers.MVNO_TYPE) : "";
1520 selectionArgs[i++] = row.containsKey(Telephony.Carriers.MVNO_MATCH_DATA) ?
1521 row.getAsString(Telephony.Carriers.MVNO_MATCH_DATA) : "";
1522 selectionArgs[i++] = row.containsKey(Telephony.Carriers.PROFILE_ID) ?
1523 row.getAsString(Telephony.Carriers.PROFILE_ID) : "0";
1524
1525 Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
1526
1527 if (c != null) {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001528 if (c.getCount() == 1) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001529 if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " +
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001530 "row found");
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001531 if (c.moveToFirst()) {
1532 return c;
1533 } else {
1534 loge("dbh.selectConflictingRow: moveToFirst() failed");
1535 }
1536 } else {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001537 loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() +
1538 " matching rows found for cv " + row);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001539 }
1540 c.close();
1541 } else {
1542 loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " +
1543 "cv " + row);
1544 }
1545
1546 return null;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07001547 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001548 }
1549
1550 @Override
1551 public boolean onCreate() {
1552 mOpenHelper = new DatabaseHelper(getContext());
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001553
1554 // Call getReadableDatabase() to make sure onUpgrade is called
1555 if (VDBG) log("onCreate: calling getReadableDatabase to trigger onUpgrade");
1556 SQLiteDatabase db = mOpenHelper.getReadableDatabase();
1557
1558 // Update APN db on build update
1559 String newBuildId = SystemProperties.get("ro.build.id", null);
1560 if (!TextUtils.isEmpty(newBuildId)) {
1561 // Check if build id has changed
1562 SharedPreferences sp = getContext().getSharedPreferences(BUILD_ID_FILE,
1563 Context.MODE_PRIVATE);
1564 String oldBuildId = sp.getString(RO_BUILD_ID, "");
1565 if (!newBuildId.equals(oldBuildId)) {
1566 if (DBG) log("onCreate: build id changed from " + oldBuildId + " to " +
1567 newBuildId);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001568
1569 // Get rid of old preferred apn shared preferences
1570 SubscriptionManager sm = SubscriptionManager.from(getContext());
1571 if (sm != null) {
1572 List<SubscriptionInfo> subInfoList = sm.getAllSubscriptionInfoList();
1573 for (SubscriptionInfo subInfo : subInfoList) {
1574 SharedPreferences spPrefFile = getContext().getSharedPreferences(
1575 PREF_FILE + subInfo.getSubscriptionId(), Context.MODE_PRIVATE);
1576 if (spPrefFile != null) {
1577 SharedPreferences.Editor editor = spPrefFile.edit();
1578 editor.clear();
1579 editor.apply();
1580 }
1581 }
1582 }
1583
1584 // Update APN DB
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001585 updateApnDb();
1586 } else {
1587 if (VDBG) log("onCreate: build id did not change: " + oldBuildId);
1588 }
1589 sp.edit().putString(RO_BUILD_ID, newBuildId).apply();
1590 } else {
1591 if (VDBG) log("onCreate: newBuildId is empty");
1592 }
1593
Wink Saville6de10272014-06-22 07:38:43 -07001594 if (VDBG) log("onCreate:- ret true");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001595 return true;
1596 }
1597
Wink Saville830a40f2014-10-23 10:16:47 -07001598 private void setPreferredApnId(Long id, int subId) {
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001599 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
John Huangb1bc16d2009-03-24 18:26:28 -07001600 SharedPreferences.Editor editor = sp.edit();
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001601 editor.putLong(COLUMN_APN_ID + subId, id != null ? id.longValue() : INVALID_APN_ID);
Brad Fitzpatrick2227c4a2010-08-30 17:42:39 -07001602 editor.apply();
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001603 // remove saved apn if apnId is invalid
1604 if (id == null || id.longValue() == INVALID_APN_ID) {
1605 deletePreferredApn(subId);
1606 }
John Huangb1bc16d2009-03-24 18:26:28 -07001607 }
1608
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001609 private long getPreferredApnId(int subId, boolean checkApnSp) {
1610 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
1611 long apnId = sp.getLong(COLUMN_APN_ID + subId, INVALID_APN_ID);
1612 if (apnId == INVALID_APN_ID && checkApnSp) {
1613 apnId = getPreferredApnIdFromApn(subId);
1614 if (apnId != INVALID_APN_ID) {
1615 setPreferredApnId(apnId, subId);
1616 deletePreferredApn(subId);
1617 }
1618 }
1619 return apnId;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001620 }
1621
1622 private void deletePreferredApnId() {
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001623 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
1624 // before deleting, save actual preferred apns (not the ids) in a separate SP
1625 Map<String, ?> allPrefApnId = sp.getAll();
1626 for (String key : allPrefApnId.keySet()) {
1627 // extract subId from key by removing COLUMN_APN_ID
Amit Mahajanf596d652015-11-09 13:20:21 -08001628 try {
1629 int subId = Integer.parseInt(key.replace(COLUMN_APN_ID, ""));
1630 long apnId = getPreferredApnId(subId, false);
1631 if (apnId != INVALID_APN_ID) {
1632 setPreferredApn(apnId, subId);
1633 }
1634 } catch (Exception e) {
1635 loge("Skipping over key " + key + " due to exception " + e);
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001636 }
1637 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001638 SharedPreferences.Editor editor = sp.edit();
1639 editor.clear();
1640 editor.apply();
John Huangb1bc16d2009-03-24 18:26:28 -07001641 }
1642
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001643 private void setPreferredApn(Long id, int subId) {
1644 log("setPreferredApn: _id " + id + " subId " + subId);
1645 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1646 // query all unique fields from id
1647 String[] proj = CARRIERS_UNIQUE_FIELDS.toArray(new String[CARRIERS_UNIQUE_FIELDS.size()]);
1648 Cursor c = db.query(CARRIERS_TABLE, proj, "_id=" + id, null, null, null, null);
1649 if (c != null) {
1650 if (c.getCount() == 1) {
1651 c.moveToFirst();
1652 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
1653 Context.MODE_PRIVATE);
1654 SharedPreferences.Editor editor = sp.edit();
1655 // store values of all unique fields to SP
1656 for (String key : CARRIERS_UNIQUE_FIELDS) {
1657 editor.putString(key + subId, c.getString(c.getColumnIndex(key)));
1658 }
1659 // also store the version number
1660 editor.putString(DB_VERSION_KEY + subId, "" + DATABASE_VERSION);
1661 editor.apply();
1662 } else {
1663 log("setPreferredApn: # matching APNs found " + c.getCount());
1664 }
1665 c.close();
1666 } else {
1667 log("setPreferredApn: No matching APN found");
1668 }
1669 }
1670
1671 private long getPreferredApnIdFromApn(int subId) {
1672 log("getPreferredApnIdFromApn: for subId " + subId);
1673 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1674 String where = TextUtils.join("=? and ", CARRIERS_UNIQUE_FIELDS) + "=?";
1675 String[] whereArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
1676 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
1677 Context.MODE_PRIVATE);
1678 long apnId = INVALID_APN_ID;
1679 int i = 0;
1680 for (String key : CARRIERS_UNIQUE_FIELDS) {
1681 whereArgs[i] = sp.getString(key + subId, null);
1682 if (whereArgs[i] == null) {
1683 return INVALID_APN_ID;
1684 }
1685 i++;
1686 }
1687 Cursor c = db.query(CARRIERS_TABLE, new String[]{"_id"}, where, whereArgs, null, null, null);
1688 if (c != null) {
1689 if (c.getCount() == 1) {
1690 c.moveToFirst();
1691 apnId = c.getInt(c.getColumnIndex("_id"));
1692 } else {
1693 log("getPreferredApnIdFromApn: returning INVALID. # matching APNs found " +
1694 c.getCount());
1695 }
1696 c.close();
1697 } else {
1698 log("getPreferredApnIdFromApn: returning INVALID. No matching APN found");
1699 }
1700 return apnId;
1701 }
1702
1703 private void deletePreferredApn(int subId) {
1704 log("deletePreferredApn: for subId " + subId);
1705 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
1706 Context.MODE_PRIVATE);
1707 if (sp.contains(DB_VERSION_KEY + subId)) {
1708 log("deletePreferredApn: apn is stored. Deleting it now for subId " + subId);
1709 SharedPreferences.Editor editor = sp.edit();
1710 editor.remove(DB_VERSION_KEY + subId);
1711 for (String key : CARRIERS_UNIQUE_FIELDS) {
1712 editor.remove(key + subId);
1713 }
1714 editor.remove(DB_VERSION_KEY + subId);
1715 editor.apply();
1716 }
1717 }
1718
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001719 @Override
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001720 public synchronized Cursor query(Uri url, String[] projectionIn, String selection,
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001721 String[] selectionArgs, String sort) {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001722 if (VDBG) log("query: url=" + url + ", projectionIn=" + projectionIn + ", selection="
1723 + selection + "selectionArgs=" + selectionArgs + ", sort=" + sort);
Wink Savillee84c0a82014-06-09 21:04:39 -07001724 TelephonyManager mTelephonyManager =
1725 (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
Wink Saville830a40f2014-10-23 10:16:47 -07001726 int subId = SubscriptionManager.getDefaultSubId();
Wink Savillee84c0a82014-06-09 21:04:39 -07001727 String subIdString;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001728 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
Robert Greenwalt429cf072013-05-21 17:04:09 -07001729 qb.setStrict(true); // a little protection from injection attacks
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001730 qb.setTables(CARRIERS_TABLE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001731
1732 int match = s_urlMatcher.match(url);
1733 switch (match) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001734 case URL_TELEPHONY_USING_SUBID: {
1735 subIdString = url.getLastPathSegment();
1736 try {
Wink Saville830a40f2014-10-23 10:16:47 -07001737 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001738 } catch (NumberFormatException e) {
1739 loge("NumberFormatException" + e);
1740 return null;
1741 }
1742 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
Susheel nyamala606de662015-10-28 13:37:18 +05301743 qb.appendWhere("numeric = '" +
1744 mTelephonyManager.getIccOperatorNumericForData(subId)+"'");
Wink Savillee84c0a82014-06-09 21:04:39 -07001745 // FIXME alter the selection to pass subId
1746 // selection = selection + "and subId = "
1747 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001748 // intentional fall through from above case
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001749 // do nothing
1750 case URL_TELEPHONY: {
1751 break;
1752 }
1753
Wink Savillee84c0a82014-06-09 21:04:39 -07001754 case URL_CURRENT_USING_SUBID: {
1755 subIdString = url.getLastPathSegment();
1756 try {
Wink Saville830a40f2014-10-23 10:16:47 -07001757 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001758 } catch (NumberFormatException e) {
1759 loge("NumberFormatException" + e);
1760 return null;
1761 }
1762 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1763 // FIXME alter the selection to pass subId
1764 // selection = selection + "and subId = "
1765 }
1766 //intentional fall through from above case
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001767 case URL_CURRENT: {
1768 qb.appendWhere("current IS NOT NULL");
Sangcheol Lee4e180882011-04-01 19:24:52 -07001769 // do not ignore the selection since MMS may use it.
1770 //selection = null;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001771 break;
1772 }
1773
1774 case URL_ID: {
1775 qb.appendWhere("_id = " + url.getPathSegments().get(1));
1776 break;
1777 }
1778
Wink Savillee84c0a82014-06-09 21:04:39 -07001779 case URL_PREFERAPN_USING_SUBID:
1780 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: {
1781 subIdString = url.getLastPathSegment();
1782 try {
Wink Saville830a40f2014-10-23 10:16:47 -07001783 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001784 } catch (NumberFormatException e) {
1785 loge("NumberFormatException" + e);
1786 return null;
1787 }
1788 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1789 }
1790 //intentional fall through from above case
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06001791 case URL_PREFERAPN:
1792 case URL_PREFERAPN_NO_UPDATE: {
Amit Mahajan91c5dff2015-10-20 11:13:19 -07001793 qb.appendWhere("_id = " + getPreferredApnId(subId, true));
Wink Savillee84c0a82014-06-09 21:04:39 -07001794 break;
1795 }
1796
1797 case URL_SIMINFO: {
1798 qb.setTables(SIMINFO_TABLE);
John Huangb1bc16d2009-03-24 18:26:28 -07001799 break;
1800 }
1801
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001802 default: {
1803 return null;
1804 }
1805 }
1806
Wink Savillee84c0a82014-06-09 21:04:39 -07001807 if (match != URL_SIMINFO) {
1808 if (projectionIn != null) {
1809 for (String column : projectionIn) {
1810 if (Telephony.Carriers.TYPE.equals(column) ||
1811 Telephony.Carriers.MMSC.equals(column) ||
1812 Telephony.Carriers.MMSPROXY.equals(column) ||
1813 Telephony.Carriers.MMSPORT.equals(column) ||
1814 Telephony.Carriers.APN.equals(column)) {
1815 // noop
1816 } else {
1817 checkPermission();
1818 break;
1819 }
Robert Greenwalt429cf072013-05-21 17:04:09 -07001820 }
Wink Savillee84c0a82014-06-09 21:04:39 -07001821 } else {
1822 // null returns all columns, so need permission check
1823 checkPermission();
Robert Greenwalt429cf072013-05-21 17:04:09 -07001824 }
Robert Greenwalt429cf072013-05-21 17:04:09 -07001825 }
1826
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001827 SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Hyejin Kimcfdb7432013-02-16 00:58:37 +09001828 Cursor ret = null;
1829 try {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001830 // Exclude entries marked deleted
1831 if (CARRIERS_TABLE.equals(qb.getTables())) {
1832 if (TextUtils.isEmpty(selection)) {
1833 selection = "";
1834 } else {
1835 selection += " and ";
1836 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07001837 selection += "edited!=" + Telephony.Carriers.USER_DELETED + " and edited!="
1838 + Telephony.Carriers.USER_DELETED_BUT_PRESENT_IN_XML + " and edited!="
1839 + Telephony.Carriers.CARRIER_DELETED + " and edited!="
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001840 + Telephony.Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001841 if (VDBG) log("query: selection modified to " + selection);
1842 }
Hyejin Kimcfdb7432013-02-16 00:58:37 +09001843 ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort);
1844 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001845 loge("got exception when querying: " + e);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09001846 }
1847 if (ret != null)
1848 ret.setNotificationUri(getContext().getContentResolver(), url);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001849 return ret;
1850 }
1851
1852 @Override
1853 public String getType(Uri url)
1854 {
1855 switch (s_urlMatcher.match(url)) {
1856 case URL_TELEPHONY:
Wink Savillee84c0a82014-06-09 21:04:39 -07001857 case URL_TELEPHONY_USING_SUBID:
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001858 return "vnd.android.cursor.dir/telephony-carrier";
1859
1860 case URL_ID:
1861 return "vnd.android.cursor.item/telephony-carrier";
1862
Wink Savillee84c0a82014-06-09 21:04:39 -07001863 case URL_PREFERAPN_USING_SUBID:
1864 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
John Huangb1bc16d2009-03-24 18:26:28 -07001865 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06001866 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07001867 return "vnd.android.cursor.item/telephony-carrier";
1868
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001869 default:
1870 throw new IllegalArgumentException("Unknown URL " + url);
1871 }
1872 }
1873
1874 @Override
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001875 public synchronized Uri insert(Uri url, ContentValues initialValues)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001876 {
1877 Uri result = null;
Wink Saville830a40f2014-10-23 10:16:47 -07001878 int subId = SubscriptionManager.getDefaultSubId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001879
1880 checkPermission();
1881
1882 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1883 int match = s_urlMatcher.match(url);
1884 boolean notify = false;
1885 switch (match)
1886 {
Wink Savillee84c0a82014-06-09 21:04:39 -07001887 case URL_TELEPHONY_USING_SUBID:
1888 {
1889 String subIdString = url.getLastPathSegment();
1890 try {
Wink Saville830a40f2014-10-23 10:16:47 -07001891 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001892 } catch (NumberFormatException e) {
1893 loge("NumberFormatException" + e);
1894 return result;
1895 }
1896 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1897 }
1898 //intentional fall through from above case
1899
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001900 case URL_TELEPHONY:
1901 {
1902 ContentValues values;
1903 if (initialValues != null) {
1904 values = new ContentValues(initialValues);
1905 } else {
1906 values = new ContentValues();
1907 }
1908
Amit Mahajanb0688862014-08-13 16:53:51 +00001909 values = DatabaseHelper.setDefaultValue(values);
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001910 if (!values.containsKey(Telephony.Carriers.EDITED)) {
1911 values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
1912 }
Wink Savillee84c0a82014-06-09 21:04:39 -07001913
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001914 try {
Amit Mahajanb80f7332015-04-16 10:02:52 -07001915 // Replace on conflict so that if same APN is present in db with edited
Amit Mahajanbc1edc22015-04-09 13:53:33 -07001916 // as Telephony.Carriers.UNEDITED or USER/CARRIER_DELETED, it is replaced with
Amit Mahajanb80f7332015-04-16 10:02:52 -07001917 // edited USER/CARRIER_EDITED
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001918 long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
1919 SQLiteDatabase.CONFLICT_REPLACE);
1920 if (rowID >= 0) {
1921 result = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, rowID);
1922 notify = true;
1923 }
1924 if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
1925 } catch (SQLException e) {
1926 log("insert: exception " + e);
1927 // Insertion failed which could be due to a conflict. Check if that is the case
1928 // and merge the entries
1929 Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
1930 if (oldRow != null) {
1931 ContentValues mergedValues = new ContentValues();
1932 DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
Amit Mahajanb80f7332015-04-16 10:02:52 -07001933 mergedValues, false, getContext());
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001934 oldRow.close();
Amit Mahajanbec84922015-04-13 10:16:43 -07001935 notify = true;
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001936 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001937 }
1938
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001939 break;
1940 }
1941
Wink Savillee84c0a82014-06-09 21:04:39 -07001942 case URL_CURRENT_USING_SUBID:
1943 {
1944 String subIdString = url.getLastPathSegment();
1945 try {
Wink Saville830a40f2014-10-23 10:16:47 -07001946 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001947 } catch (NumberFormatException e) {
1948 loge("NumberFormatException" + e);
1949 return result;
1950 }
1951 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1952 // FIXME use subId in the query
1953 }
1954 //intentional fall through from above case
1955
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001956 case URL_CURRENT:
1957 {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001958 // zero out the previous operator
1959 db.update(CARRIERS_TABLE, s_currentNullMap, "current!=0", null);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001960
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08001961 String numeric = initialValues.getAsString(Telephony.Carriers.NUMERIC);
1962 int updated = db.update(CARRIERS_TABLE, s_currentSetMap,
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001963 "numeric = '" + numeric + "'", null);
1964
1965 if (updated > 0)
1966 {
Wink Savillee84c0a82014-06-09 21:04:39 -07001967 if (VDBG) log("Setting numeric '" + numeric + "' to be the current operator");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001968 }
1969 else
1970 {
Wink Savillee84c0a82014-06-09 21:04:39 -07001971 loge("Failed setting numeric '" + numeric + "' to the current operator");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001972 }
1973 break;
1974 }
John Huangb1bc16d2009-03-24 18:26:28 -07001975
Wink Savillee84c0a82014-06-09 21:04:39 -07001976 case URL_PREFERAPN_USING_SUBID:
1977 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
1978 {
1979 String subIdString = url.getLastPathSegment();
1980 try {
Wink Saville830a40f2014-10-23 10:16:47 -07001981 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001982 } catch (NumberFormatException e) {
1983 loge("NumberFormatException" + e);
1984 return result;
1985 }
1986 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1987 }
1988 //intentional fall through from above case
1989
John Huangb1bc16d2009-03-24 18:26:28 -07001990 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06001991 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07001992 {
1993 if (initialValues != null) {
1994 if(initialValues.containsKey(COLUMN_APN_ID)) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001995 setPreferredApnId(initialValues.getAsLong(COLUMN_APN_ID), subId);
John Huangb1bc16d2009-03-24 18:26:28 -07001996 }
1997 }
1998 break;
1999 }
Wink Savillee84c0a82014-06-09 21:04:39 -07002000
2001 case URL_SIMINFO: {
2002 long id = db.insert(SIMINFO_TABLE, null, initialValues);
2003 result = ContentUris.withAppendedId(SubscriptionManager.CONTENT_URI, id);
2004 break;
2005 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002006 }
2007
2008 if (notify) {
Amith Yamasani887288c2014-11-06 09:01:20 -08002009 getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null,
2010 true, UserHandle.USER_ALL);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002011 }
2012
2013 return result;
2014 }
2015
2016 @Override
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002017 public synchronized int delete(Uri url, String where, String[] whereArgs)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002018 {
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06002019 int count = 0;
Wink Saville830a40f2014-10-23 10:16:47 -07002020 int subId = SubscriptionManager.getDefaultSubId();
Amit Mahajan7b8040a2015-06-15 18:11:01 -07002021 String userOrCarrierEdited = ") and (" +
2022 Telephony.Carriers.EDITED + "=" + Telephony.Carriers.USER_EDITED + " or " +
2023 Telephony.Carriers.EDITED + "=" + Telephony.Carriers.CARRIER_EDITED + ")";
2024 String notUserOrCarrierEdited = ") and (" +
2025 Telephony.Carriers.EDITED + "!=" + Telephony.Carriers.USER_EDITED + " and " +
2026 Telephony.Carriers.EDITED + "!=" + Telephony.Carriers.CARRIER_EDITED + ")";
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002027 ContentValues cv = new ContentValues();
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002028 cv.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_DELETED);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002029
2030 checkPermission();
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07002031
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002032 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
2033 int match = s_urlMatcher.match(url);
2034 switch (match)
2035 {
Wink Savillee84c0a82014-06-09 21:04:39 -07002036 case URL_TELEPHONY_USING_SUBID:
2037 {
2038 String subIdString = url.getLastPathSegment();
2039 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002040 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002041 } catch (NumberFormatException e) {
2042 loge("NumberFormatException" + e);
2043 throw new IllegalArgumentException("Invalid subId " + url);
2044 }
2045 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2046 // FIXME use subId in query
2047 }
2048 //intentional fall through from above case
2049
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002050 case URL_TELEPHONY:
2051 {
Amit Mahajan7b8040a2015-06-15 18:11:01 -07002052 // Delete user/carrier edited entries
2053 count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited, whereArgs);
2054 // Otherwise mark as user deleted instead of deleting
2055 count += db.update(CARRIERS_TABLE, cv, "(" + where + notUserOrCarrierEdited,
2056 whereArgs);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002057 break;
2058 }
2059
Wink Savillee84c0a82014-06-09 21:04:39 -07002060 case URL_CURRENT_USING_SUBID: {
2061 String subIdString = url.getLastPathSegment();
2062 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002063 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002064 } catch (NumberFormatException e) {
2065 loge("NumberFormatException" + e);
2066 throw new IllegalArgumentException("Invalid subId " + url);
2067 }
2068 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2069 // FIXME use subId in query
2070 }
2071 //intentional fall through from above case
2072
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002073 case URL_CURRENT:
2074 {
Amit Mahajan7b8040a2015-06-15 18:11:01 -07002075 // Delete user/carrier edited entries
2076 count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited, whereArgs);
2077 // Otherwise mark as user deleted instead of deleting
2078 count += db.update(CARRIERS_TABLE, cv, "(" + where + notUserOrCarrierEdited,
2079 whereArgs);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002080 break;
2081 }
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -07002082
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002083 case URL_ID:
2084 {
Amit Mahajan7b8040a2015-06-15 18:11:01 -07002085 // Delete user/carrier edited entries
2086 count = db.delete(CARRIERS_TABLE,
2087 "(" + Telephony.Carriers._ID + "=?" + userOrCarrierEdited,
2088 new String[] { url.getLastPathSegment() });
2089 // Otherwise mark as user deleted instead of deleting
2090 count += db.update(CARRIERS_TABLE, cv,
2091 "(" + Telephony.Carriers._ID + "=?" + notUserOrCarrierEdited,
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002092 new String[] { url.getLastPathSegment() });
2093 break;
2094 }
2095
Wink Savillee84c0a82014-06-09 21:04:39 -07002096 case URL_RESTOREAPN_USING_SUBID: {
2097 String subIdString = url.getLastPathSegment();
2098 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002099 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002100 } catch (NumberFormatException e) {
2101 loge("NumberFormatException" + e);
2102 throw new IllegalArgumentException("Invalid subId " + url);
2103 }
2104 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2105 // FIXME use subId in query
2106 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002107 case URL_RESTOREAPN: {
2108 count = 1;
Wink Savillee84c0a82014-06-09 21:04:39 -07002109 restoreDefaultAPN(subId);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002110 break;
2111 }
2112
Wink Savillee84c0a82014-06-09 21:04:39 -07002113 case URL_PREFERAPN_USING_SUBID:
2114 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: {
2115 String subIdString = url.getLastPathSegment();
2116 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002117 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002118 } catch (NumberFormatException e) {
2119 loge("NumberFormatException" + e);
2120 throw new IllegalArgumentException("Invalid subId " + url);
2121 }
2122 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2123 }
2124 //intentional fall through from above case
2125
John Huangb1bc16d2009-03-24 18:26:28 -07002126 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06002127 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07002128 {
Wink Savillee84c0a82014-06-09 21:04:39 -07002129 setPreferredApnId((long)-1, subId);
2130 if ((match == URL_PREFERAPN) || (match == URL_PREFERAPN_USING_SUBID)) count = 1;
2131 break;
2132 }
2133
2134 case URL_SIMINFO: {
2135 count = db.delete(SIMINFO_TABLE, where, whereArgs);
John Huangb1bc16d2009-03-24 18:26:28 -07002136 break;
2137 }
2138
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002139 case URL_UPDATE_DB: {
2140 updateApnDb();
2141 count = 1;
2142 break;
2143 }
2144
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002145 default: {
2146 throw new UnsupportedOperationException("Cannot delete that URL: " + url);
2147 }
2148 }
2149
2150 if (count > 0) {
Amith Yamasani887288c2014-11-06 09:01:20 -08002151 getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null,
2152 true, UserHandle.USER_ALL);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002153 }
2154
2155 return count;
2156 }
2157
2158 @Override
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002159 public synchronized int update(Uri url, ContentValues values, String where, String[] whereArgs)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002160 {
John Huangb1bc16d2009-03-24 18:26:28 -07002161 int count = 0;
Wink Savillee84c0a82014-06-09 21:04:39 -07002162 int uriType = URL_UNKNOWN;
Wink Saville830a40f2014-10-23 10:16:47 -07002163 int subId = SubscriptionManager.getDefaultSubId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002164
2165 checkPermission();
2166
2167 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
2168 int match = s_urlMatcher.match(url);
2169 switch (match)
2170 {
Wink Savillee84c0a82014-06-09 21:04:39 -07002171 case URL_TELEPHONY_USING_SUBID:
2172 {
2173 String subIdString = url.getLastPathSegment();
2174 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002175 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002176 } catch (NumberFormatException e) {
2177 loge("NumberFormatException" + e);
2178 throw new IllegalArgumentException("Invalid subId " + url);
2179 }
2180 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2181 //FIXME use subId in the query
2182 }
2183 //intentional fall through from above case
2184
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002185 case URL_TELEPHONY:
2186 {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002187 if (!values.containsKey(Telephony.Carriers.EDITED)) {
2188 values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
2189 }
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002190
Amit Mahajanb80f7332015-04-16 10:02:52 -07002191 // Replace on conflict so that if same APN is present in db with edited
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002192 // as Telephony.Carriers.UNEDITED or USER/CARRIER_DELETED, it is replaced with
Amit Mahajanb80f7332015-04-16 10:02:52 -07002193 // edited USER/CARRIER_EDITED
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002194 count = db.updateWithOnConflict(CARRIERS_TABLE, values, where, whereArgs,
2195 SQLiteDatabase.CONFLICT_REPLACE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002196 break;
2197 }
2198
Wink Savillee84c0a82014-06-09 21:04:39 -07002199 case URL_CURRENT_USING_SUBID:
2200 {
2201 String subIdString = url.getLastPathSegment();
2202 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002203 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002204 } catch (NumberFormatException e) {
2205 loge("NumberFormatException" + e);
2206 throw new IllegalArgumentException("Invalid subId " + url);
2207 }
2208 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2209 //FIXME use subId in the query
2210 }
2211 //intentional fall through from above case
2212
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002213 case URL_CURRENT:
2214 {
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002215 if (!values.containsKey(Telephony.Carriers.EDITED)) {
2216 values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
2217 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07002218 // Replace on conflict so that if same APN is present in db with edited
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002219 // as Telephony.Carriers.UNEDITED or USER/CARRIER_DELETED, it is replaced with
Amit Mahajanb80f7332015-04-16 10:02:52 -07002220 // edited USER/CARRIER_EDITED
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002221 count = db.updateWithOnConflict(CARRIERS_TABLE, values, where, whereArgs,
2222 SQLiteDatabase.CONFLICT_REPLACE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002223 break;
2224 }
2225
2226 case URL_ID:
2227 {
2228 if (where != null || whereArgs != null) {
2229 throw new UnsupportedOperationException(
2230 "Cannot update URL " + url + " with a where clause");
2231 }
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002232 if (!values.containsKey(Telephony.Carriers.EDITED)) {
2233 values.put(Telephony.Carriers.EDITED, Telephony.Carriers.USER_EDITED);
2234 }
Amit Mahajanb80f7332015-04-16 10:02:52 -07002235 // Replace on conflict so that if same APN is present in db with edited
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002236 // as Telephony.Carriers.UNEDITED or USER/CARRIER_DELETED, it is replaced with
Amit Mahajanb80f7332015-04-16 10:02:52 -07002237 // edited USER/CARRIER_EDITED
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002238 count = db.updateWithOnConflict(CARRIERS_TABLE, values,
2239 Telephony.Carriers._ID + "=?", new String[] { url.getLastPathSegment() },
2240 SQLiteDatabase.CONFLICT_REPLACE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002241 break;
2242 }
2243
Wink Savillee84c0a82014-06-09 21:04:39 -07002244 case URL_PREFERAPN_USING_SUBID:
2245 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
2246 {
2247 String subIdString = url.getLastPathSegment();
2248 try {
Wink Saville830a40f2014-10-23 10:16:47 -07002249 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07002250 } catch (NumberFormatException e) {
2251 loge("NumberFormatException" + e);
2252 throw new IllegalArgumentException("Invalid subId " + url);
2253 }
2254 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
2255 }
2256
John Huangb1bc16d2009-03-24 18:26:28 -07002257 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06002258 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07002259 {
2260 if (values != null) {
2261 if (values.containsKey(COLUMN_APN_ID)) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002262 setPreferredApnId(values.getAsLong(COLUMN_APN_ID), subId);
2263 if ((match == URL_PREFERAPN) ||
2264 (match == URL_PREFERAPN_USING_SUBID)) {
2265 count = 1;
2266 }
John Huangb1bc16d2009-03-24 18:26:28 -07002267 }
2268 }
2269 break;
2270 }
2271
Wink Savillee84c0a82014-06-09 21:04:39 -07002272 case URL_SIMINFO: {
2273 count = db.update(SIMINFO_TABLE, values, where, whereArgs);
2274 uriType = URL_SIMINFO;
2275 break;
2276 }
2277
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002278 default: {
2279 throw new UnsupportedOperationException("Cannot update that URL: " + url);
2280 }
2281 }
2282
2283 if (count > 0) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002284 switch (uriType) {
2285 case URL_SIMINFO:
2286 getContext().getContentResolver().notifyChange(
Amith Yamasani887288c2014-11-06 09:01:20 -08002287 SubscriptionManager.CONTENT_URI, null, true, UserHandle.USER_ALL);
Wink Savillee84c0a82014-06-09 21:04:39 -07002288 break;
2289 default:
2290 getContext().getContentResolver().notifyChange(
Amith Yamasani887288c2014-11-06 09:01:20 -08002291 Telephony.Carriers.CONTENT_URI, null, true, UserHandle.USER_ALL);
Wink Savillee84c0a82014-06-09 21:04:39 -07002292 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002293 }
2294
2295 return count;
2296 }
2297
2298 private void checkPermission() {
Shishir Agrawalacf787b2014-07-14 17:13:51 -07002299 int status = getContext().checkCallingOrSelfPermission(
2300 "android.permission.WRITE_APN_SETTINGS");
2301 if (status == PackageManager.PERMISSION_GRANTED) {
2302 return;
2303 }
2304
2305 PackageManager packageManager = getContext().getPackageManager();
2306 String[] packages = packageManager.getPackagesForUid(Binder.getCallingUid());
2307
2308 TelephonyManager telephonyManager =
2309 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
2310 for (String pkg : packages) {
2311 if (telephonyManager.checkCarrierPrivilegesForPackage(pkg) ==
2312 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2313 return;
2314 }
2315 }
2316 throw new SecurityException("No permission to write APN settings");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002317 }
2318
Wink Savilled7c93502011-06-04 07:17:01 -07002319 private DatabaseHelper mOpenHelper;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002320
Wink Saville830a40f2014-10-23 10:16:47 -07002321 private void restoreDefaultAPN(int subId) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002322 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
2323
Hyejin Kimcfdb7432013-02-16 00:58:37 +09002324 try {
2325 db.delete(CARRIERS_TABLE, null, null);
2326 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07002327 loge("got exception when deleting to restore: " + e);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09002328 }
Wink Savillee84c0a82014-06-09 21:04:39 -07002329 setPreferredApnId((long)-1, subId);
Wink Savilled7c93502011-06-04 07:17:01 -07002330 mOpenHelper.initDatabase(db);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002331 }
Wink Savillee84c0a82014-06-09 21:04:39 -07002332
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002333 private synchronized void updateApnDb() {
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002334 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
2335
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002336 // Delete preferred APN for all subIds
2337 deletePreferredApnId();
2338
2339 // Delete entries in db
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002340 try {
Amit Mahajanb80f7332015-04-16 10:02:52 -07002341 if (VDBG) log("updateApnDb: deleting edited=Telephony.Carriers.UNEDITED entries");
2342 db.delete(CARRIERS_TABLE, "edited=" + Telephony.Carriers.UNEDITED, null);
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002343 } catch (SQLException e) {
2344 loge("got exception when deleting to update: " + e);
2345 }
2346
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002347 mOpenHelper.initDatabase(db);
2348
Amit Mahajanbc1edc22015-04-09 13:53:33 -07002349 // Notify listereners of DB change since DB has been updated
2350 getContext().getContentResolver().notifyChange(
2351 Telephony.Carriers.CONTENT_URI, null, true, UserHandle.USER_ALL);
2352
Amit Mahajan3f2e68a2015-02-27 15:40:41 -08002353 }
2354
Wink Savillee84c0a82014-06-09 21:04:39 -07002355 /**
2356 * Log with debug
2357 *
2358 * @param s is string log
2359 */
2360 private static void log(String s) {
2361 Log.d(TAG, s);
2362 }
2363
2364 private static void loge(String s) {
2365 Log.e(TAG, s);
2366 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08002367}