blob: 66deed43ece31ad412678b83405779c0dcfea7b7 [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;
Amith Yamasani27085172014-11-06 09:01:20 -080038import android.os.UserHandle;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080039import android.provider.Telephony;
Wink Savillee84c0a82014-06-09 21:04:39 -070040import android.telephony.SubscriptionManager;
41import android.telephony.TelephonyManager;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080042import android.util.Log;
43import android.util.Xml;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070044
Wink Savilled7c93502011-06-04 07:17:01 -070045import com.android.internal.telephony.BaseCommands;
46import com.android.internal.telephony.Phone;
Wink Savillebf7c6172012-06-14 12:43:28 -070047import com.android.internal.telephony.PhoneConstants;
Dianne Hackborn49f22d32010-02-24 19:58:29 -080048import com.android.internal.util.XmlUtils;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080049
50import org.xmlpull.v1.XmlPullParser;
51import org.xmlpull.v1.XmlPullParserException;
52
53import java.io.File;
54import java.io.FileNotFoundException;
55import java.io.FileReader;
56import java.io.IOException;
w19976e9a6c452014-07-18 16:43:00 -070057import java.lang.NumberFormatException;
Wink Savilled7c93502011-06-04 07:17:01 -070058
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080059public class TelephonyProvider extends ContentProvider
60{
61 private static final String DATABASE_NAME = "telephony.db";
Wink Savilled7c93502011-06-04 07:17:01 -070062 private static final boolean DBG = true;
Wink Savillee84c0a82014-06-09 21:04:39 -070063 private static final boolean VDBG = false;
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -070064
Sindhu Kanathura6259882015-01-29 18:50:51 +053065 private static final int DATABASE_VERSION = 13 << 16;
Wink Savillee84c0a82014-06-09 21:04:39 -070066 private static final int URL_UNKNOWN = 0;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080067 private static final int URL_TELEPHONY = 1;
68 private static final int URL_CURRENT = 2;
69 private static final int URL_ID = 3;
70 private static final int URL_RESTOREAPN = 4;
John Huangb1bc16d2009-03-24 18:26:28 -070071 private static final int URL_PREFERAPN = 5;
Kazuhiro Ondod616ee62012-01-10 17:12:59 -060072 private static final int URL_PREFERAPN_NO_UPDATE = 6;
Wink Savillee84c0a82014-06-09 21:04:39 -070073 private static final int URL_SIMINFO = 7;
74 private static final int URL_TELEPHONY_USING_SUBID = 8;
75 private static final int URL_CURRENT_USING_SUBID = 9;
76 private static final int URL_RESTOREAPN_USING_SUBID = 10;
77 private static final int URL_PREFERAPN_USING_SUBID = 11;
78 private static final int URL_PREFERAPN_NO_UPDATE_USING_SUBID = 12;
79 private static final int URL_SIMINFO_USING_SUBID = 13;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080080
81 private static final String TAG = "TelephonyProvider";
82 private static final String CARRIERS_TABLE = "carriers";
Wink Savillee84c0a82014-06-09 21:04:39 -070083 private static final String SIMINFO_TABLE = "siminfo";
John Huangb1bc16d2009-03-24 18:26:28 -070084
85 private static final String PREF_FILE = "preferred-apn";
86 private static final String COLUMN_APN_ID = "apn_id";
87
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080088 private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";
Legler Wu36788802014-12-29 13:20:29 +080089 private static final String OEM_APNS_PATH = "telephony/apns-conf.xml";
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080090
kaiyiz663a6702014-07-31 15:50:20 +080091 private static final String READ_ONLY = "read_only";
92
The Android Open Source Project7236c3a2009-03-03 19:32:44 -080093 private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
94
95 private static final ContentValues s_currentNullMap;
96 private static final ContentValues s_currentSetMap;
97
98 static {
99 s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY);
100 s_urlMatcher.addURI("telephony", "carriers/current", URL_CURRENT);
101 s_urlMatcher.addURI("telephony", "carriers/#", URL_ID);
102 s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN);
John Huangb1bc16d2009-03-24 18:26:28 -0700103 s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN);
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600104 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800105
Wink Savillee84c0a82014-06-09 21:04:39 -0700106 s_urlMatcher.addURI("telephony", "siminfo", URL_SIMINFO);
107
108 s_urlMatcher.addURI("telephony", "carriers/subId/*", URL_TELEPHONY_USING_SUBID);
109 s_urlMatcher.addURI("telephony", "carriers/current/subId/*", URL_CURRENT_USING_SUBID);
110 s_urlMatcher.addURI("telephony", "carriers/restore/subId/*", URL_RESTOREAPN_USING_SUBID);
111 s_urlMatcher.addURI("telephony", "carriers/preferapn/subId/*", URL_PREFERAPN_USING_SUBID);
112 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update/subId/*",
113 URL_PREFERAPN_NO_UPDATE_USING_SUBID);
114
115
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800116 s_currentNullMap = new ContentValues(1);
117 s_currentNullMap.put("current", (Long) null);
118
119 s_currentSetMap = new ContentValues(1);
120 s_currentSetMap.put("current", "1");
121 }
122
123 private static class DatabaseHelper extends SQLiteOpenHelper {
124 // Context to access resources with
125 private Context mContext;
126
127 /**
128 * DatabaseHelper helper class for loading apns into a database.
129 *
Wink Savilled7c93502011-06-04 07:17:01 -0700130 * @param context of the user.
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800131 */
132 public DatabaseHelper(Context context) {
133 super(context, DATABASE_NAME, null, getVersion(context));
134 mContext = context;
135 }
136
137 private static int getVersion(Context context) {
Wink Saville6de10272014-06-22 07:38:43 -0700138 if (VDBG) log("getVersion:+");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800139 // Get the database version, combining a static schema version and the XML version
140 Resources r = context.getResources();
141 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
142 try {
143 XmlUtils.beginDocument(parser, "apns");
144 int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
Wink Saville6de10272014-06-22 07:38:43 -0700145 int version = DATABASE_VERSION | publicversion;
146 if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version));
147 return version;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800148 } catch (Exception e) {
Wink Saville6de10272014-06-22 07:38:43 -0700149 loge("Can't get version of APN database" + e + " return version=" +
150 Integer.toHexString(DATABASE_VERSION));
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800151 return DATABASE_VERSION;
152 } finally {
153 parser.close();
154 }
155 }
156
157 @Override
158 public void onCreate(SQLiteDatabase db) {
Wink Saville6de10272014-06-22 07:38:43 -0700159 if (DBG) log("dbh.onCreate:+ db=" + db);
160 createSimInfoTable(db);
161 createCarriersTable(db);
162 initDatabase(db);
163 if (DBG) log("dbh.onCreate:- db=" + db);
164 }
165
166 @Override
167 public void onOpen(SQLiteDatabase db) {
168 if (VDBG) log("dbh.onOpen:+ db=" + db);
169 try {
170 // Try to access the table and create it if "no such table"
171 db.query(SIMINFO_TABLE, null, null, null, null, null, null);
172 if (DBG) log("dbh.onOpen: ok, queried table=" + SIMINFO_TABLE);
173 } catch (SQLiteException e) {
174 loge("Exception " + SIMINFO_TABLE + "e=" + e);
175 if (e.getMessage().startsWith("no such table")) {
176 createSimInfoTable(db);
177 }
178 }
179 try {
180 db.query(CARRIERS_TABLE, null, null, null, null, null, null);
181 if (DBG) log("dbh.onOpen: ok, queried table=" + CARRIERS_TABLE);
182 } catch (SQLiteException e) {
183 loge("Exception " + CARRIERS_TABLE + " e=" + e);
184 if (e.getMessage().startsWith("no such table")) {
185 createCarriersTable(db);
186 }
187 }
188 if (VDBG) log("dbh.onOpen:- db=" + db);
189 }
190
191 private void createSimInfoTable(SQLiteDatabase db) {
192 if (DBG) log("dbh.createSimInfoTable:+");
Wink Savillee84c0a82014-06-09 21:04:39 -0700193 db.execSQL("CREATE TABLE " + SIMINFO_TABLE + "("
Wink Saville8ca608c2014-11-15 12:49:01 -0800194 + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
Wink Savillee84c0a82014-06-09 21:04:39 -0700195 + SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
Wink Saville8ca608c2014-11-15 12:49:01 -0800196 + SubscriptionManager.SIM_SLOT_INDEX + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
Wink Savillee84c0a82014-06-09 21:04:39 -0700197 + SubscriptionManager.DISPLAY_NAME + " TEXT,"
Sanket Padawe0f8d6692014-11-06 11:50:40 -0800198 + SubscriptionManager.CARRIER_NAME + " TEXT,"
Wink Savilled3b87ec2014-09-02 22:45:38 -0700199 + SubscriptionManager.NAME_SOURCE + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
Wink Savillee84c0a82014-06-09 21:04:39 -0700200 + SubscriptionManager.COLOR + " INTEGER DEFAULT " + SubscriptionManager.COLOR_DEFAULT + ","
201 + SubscriptionManager.NUMBER + " TEXT,"
Yashdev Singh9c601802015-02-24 23:03:06 -0800202 + SubscriptionManager.DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700203 + SubscriptionManager.DATA_ROAMING + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
204 + SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
Rakesh Pallerlac69605f2014-07-18 17:17:29 +0530205 + SubscriptionManager.MNC + " INTEGER DEFAULT 0" + ","
Rakesh Pallerlafdaecc72014-09-26 16:15:33 +0530206 + SubscriptionManager.SUB_STATE + " INTEGER DEFAULT " + SubscriptionManager.ACTIVE + ","
207 + SubscriptionManager.NETWORK_MODE+ " INTEGER DEFAULT " + SubscriptionManager.DEFAULT_NW_MODE
Wink Savillee84c0a82014-06-09 21:04:39 -0700208 + ");");
Wink Saville6de10272014-06-22 07:38:43 -0700209 if (DBG) log("dbh.createSimInfoTable:-");
210 }
211
212 private void createCarriersTable(SQLiteDatabase db) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800213 // Set up the database schema
Wink Saville6de10272014-06-22 07:38:43 -0700214 if (DBG) log("dbh.createCarriersTable:+");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800215 db.execSQL("CREATE TABLE " + CARRIERS_TABLE +
216 "(_id INTEGER PRIMARY KEY," +
217 "name TEXT," +
218 "numeric TEXT," +
219 "mcc TEXT," +
220 "mnc TEXT," +
221 "apn TEXT," +
222 "user TEXT," +
223 "server TEXT," +
224 "password TEXT," +
225 "proxy TEXT," +
226 "port TEXT," +
227 "mmsproxy TEXT," +
228 "mmsport TEXT," +
229 "mmsc TEXT," +
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700230 "authtype INTEGER," +
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800231 "type TEXT," +
Lorenzo Colitti9dd054f2010-12-29 15:54:00 -0800232 "current INTEGER," +
233 "protocol TEXT," +
sinikangbae4b072011-09-02 09:49:37 +0900234 "roaming_protocol TEXT," +
235 "carrier_enabled BOOLEAN," +
Sungmin Choi27045ef2013-01-25 17:48:06 +0900236 "bearer INTEGER," +
237 "mvno_type TEXT," +
Wink Savillee84c0a82014-06-09 21:04:39 -0700238 "mvno_match_data TEXT," +
Wink Saville8ca608c2014-11-15 12:49:01 -0800239 "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + "," +
Amit Mahajanb0688862014-08-13 16:53:51 +0000240 "profile_id INTEGER default 0," +
241 "modem_cognitive BOOLEAN default 0," +
242 "max_conns INTEGER default 0," +
243 "wait_time INTEGER default 0," +
w19976e9a6c452014-07-18 16:43:00 -0700244 "max_conns_time INTEGER default 0," +
kaiyiz663a6702014-07-31 15:50:20 +0800245 "read_only BOOLEAN DEFAULT 0," +
w19976e9a6c452014-07-18 16:43:00 -0700246 "mtu INTEGER);");
Wink Saville6de10272014-06-22 07:38:43 -0700247 if (DBG) log("dbh.createCarriersTable:-");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800248 }
Shri Borde4b471cc2014-09-15 13:46:01 -0700249
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800250 private void initDatabase(SQLiteDatabase db) {
Wink Saville6de10272014-06-22 07:38:43 -0700251 if (VDBG) log("dbh.initDatabase:+ db=" + db);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800252 // Read internal APNS data
253 Resources r = mContext.getResources();
254 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);
255 int publicversion = -1;
256 try {
257 XmlUtils.beginDocument(parser, "apns");
258 publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));
259 loadApns(db, parser);
260 } catch (Exception e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700261 loge("Got exception while loading APN database." + e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800262 } finally {
263 parser.close();
264 }
265
Sungmin Choi22b63062013-01-25 15:53:15 +0900266 // Read external APNS data (partner-provided)
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800267 XmlPullParser confparser = null;
268 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
269 File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);
Legler Wu36788802014-12-29 13:20:29 +0800270 File oemConfFile = new File(Environment.getOemDirectory(), OEM_APNS_PATH);
271 if (oemConfFile.exists()) {
272 // OEM image exist APN xml, get the timestamp from OEM & System image for comparison
273 long oemApnTime = oemConfFile.lastModified();
274 long sysApnTime = confFile.lastModified();
275 if (DBG) log("APNs Timestamp: oemTime = " + oemApnTime + " sysTime = "
276 + sysApnTime);
277
278 // To get the latest version from OEM or System image
279 if (oemApnTime > sysApnTime) {
280 if (DBG) log("APNs Timestamp: OEM image is greater than System image");
281 confFile = oemConfFile;
282 }
283 } else {
284 // No Apn in OEM image, so load it from system image.
285 if (DBG) log("No APNs in OEM image = " + oemConfFile.getPath() +
286 " Load APNs from system image");
287 }
288
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800289 FileReader confreader = null;
Legler Wu36788802014-12-29 13:20:29 +0800290 if (DBG) log("confFile = " + confFile);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800291 try {
292 confreader = new FileReader(confFile);
293 confparser = Xml.newPullParser();
294 confparser.setInput(confreader);
295 XmlUtils.beginDocument(confparser, "apns");
296
297 // Sanity check. Force internal version and confidential versions to agree
298 int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version"));
299 if (publicversion != confversion) {
300 throw new IllegalStateException("Internal APNS file version doesn't match "
301 + confFile.getAbsolutePath());
302 }
303
304 loadApns(db, confparser);
305 } catch (FileNotFoundException e) {
306 // It's ok if the file isn't found. It means there isn't a confidential file
307 // Log.e(TAG, "File not found: '" + confFile.getAbsolutePath() + "'");
308 } catch (Exception e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700309 loge("Exception while parsing '" + confFile.getAbsolutePath() + "'" + e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800310 } finally {
311 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
312 }
Wink Saville6de10272014-06-22 07:38:43 -0700313 if (VDBG) log("dbh.initDatabase:- db=" + db);
Amit Mahajanb0688862014-08-13 16:53:51 +0000314
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800315 }
316
317 @Override
318 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Wink Saville6de10272014-06-22 07:38:43 -0700319 if (DBG) {
320 log("dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
321 }
322
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700323 if (oldVersion < (5 << 16 | 6)) {
324 // 5 << 16 is the Database version and 6 in the xml version.
325
326 // This change adds a new authtype column to the database.
327 // The auth type column can have 4 values: 0 (None), 1 (PAP), 2 (CHAP)
328 // 3 (PAP or CHAP). To avoid breaking compatibility, with already working
329 // APNs, the unset value (-1) will be used. If the value is -1.
330 // the authentication will default to 0 (if no user / password) is specified
331 // or to 3. Currently, there have been no reported problems with
332 // pre-configured APNs and hence it is set to -1 for them. Similarly,
333 // if the user, has added a new APN, we set the authentication type
334 // to -1.
335
336 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
337 " ADD COLUMN authtype INTEGER DEFAULT -1;");
338
339 oldVersion = 5 << 16 | 6;
340 }
Lorenzo Colitti9dd054f2010-12-29 15:54:00 -0800341 if (oldVersion < (6 << 16 | 6)) {
342 // Add protcol fields to the APN. The XML file does not change.
343 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
344 " ADD COLUMN protocol TEXT DEFAULT IP;");
345 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
346 " ADD COLUMN roaming_protocol TEXT DEFAULT IP;");
347 oldVersion = 6 << 16 | 6;
348 }
sinikangbae4b072011-09-02 09:49:37 +0900349 if (oldVersion < (7 << 16 | 6)) {
Sungmin Choi22b63062013-01-25 15:53:15 +0900350 // Add carrier_enabled, bearer fields to the APN. The XML file does not change.
sinikangbae4b072011-09-02 09:49:37 +0900351 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
352 " ADD COLUMN carrier_enabled BOOLEAN DEFAULT 1;");
353 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
354 " ADD COLUMN bearer INTEGER DEFAULT 0;");
355 oldVersion = 7 << 16 | 6;
356 }
Sungmin Choi27045ef2013-01-25 17:48:06 +0900357 if (oldVersion < (8 << 16 | 6)) {
358 // Add mvno_type, mvno_match_data fields to the APN.
359 // The XML file does not change.
360 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
361 " ADD COLUMN mvno_type TEXT DEFAULT '';");
362 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
363 " ADD COLUMN mvno_match_data TEXT DEFAULT '';");
364 oldVersion = 8 << 16 | 6;
365 }
Wink Savillee84c0a82014-06-09 21:04:39 -0700366 if (oldVersion < (9 << 16 | 6)) {
367 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
Tom Taylorbb50ace2014-10-28 13:35:34 -0700368 " ADD COLUMN sub_id INTEGER DEFAULT " +
Wink Saville8ca608c2014-11-15 12:49:01 -0800369 SubscriptionManager.INVALID_SUBSCRIPTION_ID + ";");
Wink Savillee84c0a82014-06-09 21:04:39 -0700370 oldVersion = 9 << 16 | 6;
371 }
Amit Mahajanb0688862014-08-13 16:53:51 +0000372 if (oldVersion < (10 << 16 | 6)) {
373 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
374 " ADD COLUMN profile_id INTEGER DEFAULT 0;");
375 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
376 " ADD COLUMN modem_cognitive BOOLEAN DEFAULT 0;");
377 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
378 " ADD COLUMN max_conns INTEGER DEFAULT 0;");
379 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
380 " ADD COLUMN wait_time INTEGER DEFAULT 0;");
381 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
382 " ADD COLUMN max_conns_time INTEGER DEFAULT 0;");
383 oldVersion = 10 << 16 | 6;
384 }
w19976e9a6c452014-07-18 16:43:00 -0700385 if (oldVersion < (11 << 16 | 6)) {
386 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
387 " ADD COLUMN mtu INTEGER DEFAULT 0;");
388 oldVersion = 11 << 16 | 6;
389 }
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700390 if (oldVersion < (12 << 16 | 6)) {
Tom Taylorc55054d2014-09-10 11:01:44 -0700391 try {
392 // Try to update the siminfo table. It might not be there.
393 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
394 " ADD COLUMN " + SubscriptionManager.MCC + " INTEGER DEFAULT 0;");
395 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
396 " ADD COLUMN " + SubscriptionManager.MNC + " INTEGER DEFAULT 0;");
397 } catch (SQLiteException e) {
398 if (DBG) {
399 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
400 " The table will get created in onOpen.");
401 }
402 }
Tom Taylor7c6edbe2014-09-04 12:02:34 -0700403 oldVersion = 12 << 16 | 6;
404 }
Sindhu Kanathura6259882015-01-29 18:50:51 +0530405 if (oldVersion < (13 << 16 | 6)) {
406 db.execSQL("ALTER TABLE " + CARRIERS_TABLE +
407 " ADD COLUMN "+READ_ONLY+" BOOLEAN DEFAULT 0;");
Sanket Padawe0f8d6692014-11-06 11:50:40 -0800408 try {
409 // Try to update the siminfo table. It might not be there.
410 db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
411 " ADD COLUMN " + SubscriptionManager.CARRIER_NAME + " TEXT DEFAULT '';");
412 } catch (SQLiteException e) {
413 if (DBG) {
414 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
415 " The table will get created in onOpen.");
416 }
417 }
418 oldVersion = 13 << 16 | 6;
Sindhu Kanathura6259882015-01-29 18:50:51 +0530419 }
Wink Saville6de10272014-06-22 07:38:43 -0700420 if (DBG) {
421 log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
422 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800423 }
424
425 /**
426 * Gets the next row of apn values.
427 *
428 * @param parser the parser
429 * @return the row or null if it's not an apn
430 */
431 private ContentValues getRow(XmlPullParser parser) {
432 if (!"apn".equals(parser.getName())) {
433 return null;
434 }
435
436 ContentValues map = new ContentValues();
437
438 String mcc = parser.getAttributeValue(null, "mcc");
439 String mnc = parser.getAttributeValue(null, "mnc");
440 String numeric = mcc + mnc;
441
442 map.put(Telephony.Carriers.NUMERIC,numeric);
443 map.put(Telephony.Carriers.MCC, mcc);
444 map.put(Telephony.Carriers.MNC, mnc);
445 map.put(Telephony.Carriers.NAME, parser.getAttributeValue(null, "carrier"));
446 map.put(Telephony.Carriers.APN, parser.getAttributeValue(null, "apn"));
447 map.put(Telephony.Carriers.USER, parser.getAttributeValue(null, "user"));
448 map.put(Telephony.Carriers.SERVER, parser.getAttributeValue(null, "server"));
449 map.put(Telephony.Carriers.PASSWORD, parser.getAttributeValue(null, "password"));
450
451 // do not add NULL to the map so that insert() will set the default value
452 String proxy = parser.getAttributeValue(null, "proxy");
453 if (proxy != null) {
454 map.put(Telephony.Carriers.PROXY, proxy);
455 }
456 String port = parser.getAttributeValue(null, "port");
457 if (port != null) {
458 map.put(Telephony.Carriers.PORT, port);
459 }
460 String mmsproxy = parser.getAttributeValue(null, "mmsproxy");
461 if (mmsproxy != null) {
462 map.put(Telephony.Carriers.MMSPROXY, mmsproxy);
463 }
464 String mmsport = parser.getAttributeValue(null, "mmsport");
465 if (mmsport != null) {
466 map.put(Telephony.Carriers.MMSPORT, mmsport);
467 }
468 map.put(Telephony.Carriers.MMSC, parser.getAttributeValue(null, "mmsc"));
469 String type = parser.getAttributeValue(null, "type");
470 if (type != null) {
471 map.put(Telephony.Carriers.TYPE, type);
472 }
473
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700474 String auth = parser.getAttributeValue(null, "authtype");
475 if (auth != null) {
476 map.put(Telephony.Carriers.AUTH_TYPE, Integer.parseInt(auth));
477 }
478
Lorenzo Colitti9dd054f2010-12-29 15:54:00 -0800479 String protocol = parser.getAttributeValue(null, "protocol");
480 if (protocol != null) {
481 map.put(Telephony.Carriers.PROTOCOL, protocol);
482 }
483
484 String roamingProtocol = parser.getAttributeValue(null, "roaming_protocol");
485 if (roamingProtocol != null) {
486 map.put(Telephony.Carriers.ROAMING_PROTOCOL, roamingProtocol);
487 }
488
sinikangbae4b072011-09-02 09:49:37 +0900489 String carrierEnabled = parser.getAttributeValue(null, "carrier_enabled");
490 if (carrierEnabled != null) {
491 map.put(Telephony.Carriers.CARRIER_ENABLED, Boolean.parseBoolean(carrierEnabled));
492 }
493
494 String bearer = parser.getAttributeValue(null, "bearer");
495 if (bearer != null) {
496 map.put(Telephony.Carriers.BEARER, Integer.parseInt(bearer));
497 }
Sungmin Choi27045ef2013-01-25 17:48:06 +0900498
499 String mvno_type = parser.getAttributeValue(null, "mvno_type");
500 if (mvno_type != null) {
501 String mvno_match_data = parser.getAttributeValue(null, "mvno_match_data");
502 if (mvno_match_data != null) {
503 map.put(Telephony.Carriers.MVNO_TYPE, mvno_type);
504 map.put(Telephony.Carriers.MVNO_MATCH_DATA, mvno_match_data);
505 }
506 }
Amit Mahajanb0688862014-08-13 16:53:51 +0000507
508 String profileId = parser.getAttributeValue(null, "profile_id");
509 if (profileId != null) {
510 map.put(Telephony.Carriers.PROFILE_ID, Integer.parseInt(profileId));
511 }
512
513 String modemCognitive = parser.getAttributeValue(null, "modem_cognitive");
Hui Wanga1045b02014-10-01 16:18:50 -0500514 if (modemCognitive != null) {
Amit Mahajanb0688862014-08-13 16:53:51 +0000515 map.put(Telephony.Carriers.MODEM_COGNITIVE, Boolean.parseBoolean(modemCognitive));
516 }
517
518 String maxConns = parser.getAttributeValue(null, "max_conns");
519 if (maxConns != null) {
520 map.put(Telephony.Carriers.MAX_CONNS, Integer.parseInt(maxConns));
521 }
522
523 String waitTime = parser.getAttributeValue(null, "wait_time");
524 if (waitTime != null) {
525 map.put(Telephony.Carriers.WAIT_TIME, Integer.parseInt(waitTime));
526 }
527
528 String maxConnsTime = parser.getAttributeValue(null, "max_conns_time");
529 if (maxConnsTime != null) {
530 map.put(Telephony.Carriers.MAX_CONNS_TIME, Integer.parseInt(maxConnsTime));
531 }
532
w19976e9a6c452014-07-18 16:43:00 -0700533 String mtu = parser.getAttributeValue(null, "mtu");
534 if (mtu != null) {
535 map.put(Telephony.Carriers.MTU, Integer.parseInt(mtu));
536 }
537
kaiyiz663a6702014-07-31 15:50:20 +0800538 String readOnly = parser.getAttributeValue(null, "read_only");
539 if (readOnly != null) {
540 map.put(mContext.getString(R.string.read_only), Boolean.
541 parseBoolean(readOnly));
542 }
543
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800544 return map;
545 }
546
547 /*
548 * Loads apns from xml file into the database
549 *
550 * @param db the sqlite database to write to
551 * @param parser the xml parser
552 *
553 */
554 private void loadApns(SQLiteDatabase db, XmlPullParser parser) {
555 if (parser != null) {
556 try {
jewon.lee4167fcc2013-01-17 13:10:37 +0900557 db.beginTransaction();
Hyejin Kim7e7c2742013-02-11 20:02:18 +0900558 XmlUtils.nextElement(parser);
559 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800560 ContentValues row = getRow(parser);
Hyejin Kim7e7c2742013-02-11 20:02:18 +0900561 if (row == null) {
562 throw new XmlPullParserException("Expected 'apn' tag", parser, null);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800563 }
Hyejin Kim7e7c2742013-02-11 20:02:18 +0900564 insertAddingDefaults(db, CARRIERS_TABLE, row);
565 XmlUtils.nextElement(parser);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800566 }
jewon.lee4167fcc2013-01-17 13:10:37 +0900567 db.setTransactionSuccessful();
Hyejin Kim7e7c2742013-02-11 20:02:18 +0900568 } catch (XmlPullParserException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700569 loge("Got XmlPullParserException while loading apns." + e);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800570 } catch (IOException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700571 loge("Got IOException while loading apns." + e);
Hyejin Kim7e7c2742013-02-11 20:02:18 +0900572 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700573 loge("Got SQLException while loading apns." + e);
jewon.lee4167fcc2013-01-17 13:10:37 +0900574 } finally {
575 db.endTransaction();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800576 }
577 }
578 }
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700579
Amit Mahajanb0688862014-08-13 16:53:51 +0000580 static public ContentValues setDefaultValue(ContentValues values) {
581 if (!values.containsKey(Telephony.Carriers.NAME)) {
582 values.put(Telephony.Carriers.NAME, "");
583 }
584 if (!values.containsKey(Telephony.Carriers.APN)) {
585 values.put(Telephony.Carriers.APN, "");
586 }
587 if (!values.containsKey(Telephony.Carriers.PORT)) {
588 values.put(Telephony.Carriers.PORT, "");
589 }
590 if (!values.containsKey(Telephony.Carriers.PROXY)) {
591 values.put(Telephony.Carriers.PROXY, "");
592 }
593 if (!values.containsKey(Telephony.Carriers.USER)) {
594 values.put(Telephony.Carriers.USER, "");
595 }
596 if (!values.containsKey(Telephony.Carriers.SERVER)) {
597 values.put(Telephony.Carriers.SERVER, "");
598 }
599 if (!values.containsKey(Telephony.Carriers.PASSWORD)) {
600 values.put(Telephony.Carriers.PASSWORD, "");
601 }
602 if (!values.containsKey(Telephony.Carriers.MMSPORT)) {
603 values.put(Telephony.Carriers.MMSPORT, "");
604 }
605 if (!values.containsKey(Telephony.Carriers.MMSPROXY)) {
606 values.put(Telephony.Carriers.MMSPROXY, "");
607 }
608 if (!values.containsKey(Telephony.Carriers.AUTH_TYPE)) {
609 values.put(Telephony.Carriers.AUTH_TYPE, -1);
610 }
611 if (!values.containsKey(Telephony.Carriers.PROTOCOL)) {
612 values.put(Telephony.Carriers.PROTOCOL, "IP");
613 }
614 if (!values.containsKey(Telephony.Carriers.ROAMING_PROTOCOL)) {
615 values.put(Telephony.Carriers.ROAMING_PROTOCOL, "IP");
616 }
617 if (!values.containsKey(Telephony.Carriers.CARRIER_ENABLED)) {
618 values.put(Telephony.Carriers.CARRIER_ENABLED, true);
619 }
620 if (!values.containsKey(Telephony.Carriers.BEARER)) {
621 values.put(Telephony.Carriers.BEARER, 0);
622 }
623 if (!values.containsKey(Telephony.Carriers.MVNO_TYPE)) {
624 values.put(Telephony.Carriers.MVNO_TYPE, "");
625 }
626 if (!values.containsKey(Telephony.Carriers.MVNO_MATCH_DATA)) {
627 values.put(Telephony.Carriers.MVNO_MATCH_DATA, "");
628 }
629
Wink Saville85477f62014-10-23 10:16:47 -0700630 int subId = SubscriptionManager.getDefaultDataSubId();
Wink Saville8ca608c2014-11-15 12:49:01 -0800631 if (!values.containsKey(Telephony.Carriers.SUBSCRIPTION_ID)) {
632 values.put(Telephony.Carriers.SUBSCRIPTION_ID, subId);
Amit Mahajanb0688862014-08-13 16:53:51 +0000633 }
634
635 if (!values.containsKey(Telephony.Carriers.PROFILE_ID)) {
636 values.put(Telephony.Carriers.PROFILE_ID, 0);
637 }
638 if (!values.containsKey(Telephony.Carriers.MODEM_COGNITIVE)) {
639 values.put(Telephony.Carriers.MODEM_COGNITIVE, false);
640 }
641 if (!values.containsKey(Telephony.Carriers.MAX_CONNS)) {
642 values.put(Telephony.Carriers.MAX_CONNS, 0);
643 }
644 if (!values.containsKey(Telephony.Carriers.WAIT_TIME)) {
645 values.put(Telephony.Carriers.WAIT_TIME, 0);
646 }
647 if (!values.containsKey(Telephony.Carriers.MAX_CONNS_TIME)) {
648 values.put(Telephony.Carriers.MAX_CONNS_TIME, 0);
649 }
650
kaiyiz663a6702014-07-31 15:50:20 +0800651 if (!values.containsKey(READ_ONLY)) {
652 values.put(READ_ONLY, false);
653 }
Amit Mahajanb0688862014-08-13 16:53:51 +0000654 return values;
655 }
656
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700657 private void insertAddingDefaults(SQLiteDatabase db, String table, ContentValues row) {
Amit Mahajanb0688862014-08-13 16:53:51 +0000658 row = setDefaultValue(row);
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700659 db.insert(CARRIERS_TABLE, null, row);
660 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800661 }
662
663 @Override
664 public boolean onCreate() {
Wink Saville6de10272014-06-22 07:38:43 -0700665 if (VDBG) log("onCreate:+");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800666 mOpenHelper = new DatabaseHelper(getContext());
Wink Saville6de10272014-06-22 07:38:43 -0700667 if (VDBG) log("onCreate:- ret true");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800668 return true;
669 }
670
Wink Saville85477f62014-10-23 10:16:47 -0700671 private void setPreferredApnId(Long id, int subId) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700672 SharedPreferences sp = getContext().getSharedPreferences(
673 PREF_FILE + subId, Context.MODE_PRIVATE);
John Huangb1bc16d2009-03-24 18:26:28 -0700674 SharedPreferences.Editor editor = sp.edit();
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700675 editor.putLong(COLUMN_APN_ID, id != null ? id.longValue() : -1);
Brad Fitzpatrick2227c4a2010-08-30 17:42:39 -0700676 editor.apply();
John Huangb1bc16d2009-03-24 18:26:28 -0700677 }
678
Wink Saville85477f62014-10-23 10:16:47 -0700679 private long getPreferredApnId(int subId) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700680 SharedPreferences sp = getContext().getSharedPreferences(
681 PREF_FILE + subId, Context.MODE_PRIVATE);
John Huangb1bc16d2009-03-24 18:26:28 -0700682 return sp.getLong(COLUMN_APN_ID, -1);
683 }
684
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800685 @Override
686 public Cursor query(Uri url, String[] projectionIn, String selection,
687 String[] selectionArgs, String sort) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700688 TelephonyManager mTelephonyManager =
689 (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
Wink Saville85477f62014-10-23 10:16:47 -0700690 int subId = SubscriptionManager.getDefaultDataSubId();
Wink Savillee84c0a82014-06-09 21:04:39 -0700691 String subIdString;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800692 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
Robert Greenwalt429cf072013-05-21 17:04:09 -0700693 qb.setStrict(true); // a little protection from injection attacks
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800694 qb.setTables("carriers");
695
696 int match = s_urlMatcher.match(url);
697 switch (match) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700698 case URL_TELEPHONY_USING_SUBID: {
699 subIdString = url.getLastPathSegment();
700 try {
Wink Saville85477f62014-10-23 10:16:47 -0700701 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700702 } catch (NumberFormatException e) {
703 loge("NumberFormatException" + e);
704 return null;
705 }
706 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
Susheel nyamala3372c2e2014-09-24 20:55:57 +0530707 qb.appendWhere("numeric = '" +
708 mTelephonyManager.getIccOperatorNumeric(subId)+"'");
Wink Savillee84c0a82014-06-09 21:04:39 -0700709 // FIXME alter the selection to pass subId
710 // selection = selection + "and subId = "
711 }
712 //intentional fall through from above case
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800713 // do nothing
714 case URL_TELEPHONY: {
715 break;
716 }
717
Wink Savillee84c0a82014-06-09 21:04:39 -0700718 case URL_CURRENT_USING_SUBID: {
719 subIdString = url.getLastPathSegment();
720 try {
Wink Saville85477f62014-10-23 10:16:47 -0700721 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700722 } catch (NumberFormatException e) {
723 loge("NumberFormatException" + e);
724 return null;
725 }
726 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
727 // FIXME alter the selection to pass subId
728 // selection = selection + "and subId = "
729 }
730 //intentional fall through from above case
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800731 case URL_CURRENT: {
732 qb.appendWhere("current IS NOT NULL");
Sangcheol Lee4e180882011-04-01 19:24:52 -0700733 // do not ignore the selection since MMS may use it.
734 //selection = null;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800735 break;
736 }
737
738 case URL_ID: {
739 qb.appendWhere("_id = " + url.getPathSegments().get(1));
740 break;
741 }
742
Wink Savillee84c0a82014-06-09 21:04:39 -0700743 case URL_PREFERAPN_USING_SUBID:
744 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: {
745 subIdString = url.getLastPathSegment();
746 try {
Wink Saville85477f62014-10-23 10:16:47 -0700747 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700748 } catch (NumberFormatException e) {
749 loge("NumberFormatException" + e);
750 return null;
751 }
752 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
753 }
754 //intentional fall through from above case
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600755 case URL_PREFERAPN:
756 case URL_PREFERAPN_NO_UPDATE: {
Wink Savillee84c0a82014-06-09 21:04:39 -0700757 qb.appendWhere("_id = " + getPreferredApnId(subId));
758 break;
759 }
760
761 case URL_SIMINFO: {
762 qb.setTables(SIMINFO_TABLE);
John Huangb1bc16d2009-03-24 18:26:28 -0700763 break;
764 }
765
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800766 default: {
767 return null;
768 }
769 }
770
Wink Savillee84c0a82014-06-09 21:04:39 -0700771 if (match != URL_SIMINFO) {
772 if (projectionIn != null) {
773 for (String column : projectionIn) {
774 if (Telephony.Carriers.TYPE.equals(column) ||
775 Telephony.Carriers.MMSC.equals(column) ||
776 Telephony.Carriers.MMSPROXY.equals(column) ||
777 Telephony.Carriers.MMSPORT.equals(column) ||
778 Telephony.Carriers.APN.equals(column)) {
779 // noop
780 } else {
781 checkPermission();
782 break;
783 }
Robert Greenwalt429cf072013-05-21 17:04:09 -0700784 }
Wink Savillee84c0a82014-06-09 21:04:39 -0700785 } else {
786 // null returns all columns, so need permission check
787 checkPermission();
Robert Greenwalt429cf072013-05-21 17:04:09 -0700788 }
Robert Greenwalt429cf072013-05-21 17:04:09 -0700789 }
790
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800791 SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Hyejin Kimcfdb7432013-02-16 00:58:37 +0900792 Cursor ret = null;
793 try {
794 ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort);
795 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700796 loge("got exception when querying: " + e);
Hyejin Kimcfdb7432013-02-16 00:58:37 +0900797 }
798 if (ret != null)
799 ret.setNotificationUri(getContext().getContentResolver(), url);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800800 return ret;
801 }
802
803 @Override
804 public String getType(Uri url)
805 {
806 switch (s_urlMatcher.match(url)) {
807 case URL_TELEPHONY:
Wink Savillee84c0a82014-06-09 21:04:39 -0700808 case URL_TELEPHONY_USING_SUBID:
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800809 return "vnd.android.cursor.dir/telephony-carrier";
810
811 case URL_ID:
812 return "vnd.android.cursor.item/telephony-carrier";
813
Wink Savillee84c0a82014-06-09 21:04:39 -0700814 case URL_PREFERAPN_USING_SUBID:
815 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
John Huangb1bc16d2009-03-24 18:26:28 -0700816 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600817 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -0700818 return "vnd.android.cursor.item/telephony-carrier";
819
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800820 default:
821 throw new IllegalArgumentException("Unknown URL " + url);
822 }
823 }
824
825 @Override
826 public Uri insert(Uri url, ContentValues initialValues)
827 {
828 Uri result = null;
Wink Saville85477f62014-10-23 10:16:47 -0700829 int subId = SubscriptionManager.getDefaultDataSubId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800830
831 checkPermission();
832
833 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
834 int match = s_urlMatcher.match(url);
835 boolean notify = false;
836 switch (match)
837 {
Wink Savillee84c0a82014-06-09 21:04:39 -0700838 case URL_TELEPHONY_USING_SUBID:
839 {
840 String subIdString = url.getLastPathSegment();
841 try {
Wink Saville85477f62014-10-23 10:16:47 -0700842 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700843 } catch (NumberFormatException e) {
844 loge("NumberFormatException" + e);
845 return result;
846 }
847 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
848 }
849 //intentional fall through from above case
850
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800851 case URL_TELEPHONY:
852 {
853 ContentValues values;
854 if (initialValues != null) {
855 values = new ContentValues(initialValues);
856 } else {
857 values = new ContentValues();
858 }
859
Amit Mahajanb0688862014-08-13 16:53:51 +0000860 values = DatabaseHelper.setDefaultValue(values);
Wink Savillee84c0a82014-06-09 21:04:39 -0700861
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800862 long rowID = db.insert(CARRIERS_TABLE, null, values);
863 if (rowID > 0)
864 {
865 result = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, rowID);
866 notify = true;
867 }
868
Wink Savillee84c0a82014-06-09 21:04:39 -0700869 if (VDBG) log("inserted " + values.toString() + " rowID = " + rowID);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800870 break;
871 }
872
Wink Savillee84c0a82014-06-09 21:04:39 -0700873 case URL_CURRENT_USING_SUBID:
874 {
875 String subIdString = url.getLastPathSegment();
876 try {
Wink Saville85477f62014-10-23 10:16:47 -0700877 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700878 } catch (NumberFormatException e) {
879 loge("NumberFormatException" + e);
880 return result;
881 }
882 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
883 // FIXME use subId in the query
884 }
885 //intentional fall through from above case
886
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800887 case URL_CURRENT:
888 {
889 // null out the previous operator
890 db.update("carriers", s_currentNullMap, "current IS NOT NULL", null);
891
892 String numeric = initialValues.getAsString("numeric");
893 int updated = db.update("carriers", s_currentSetMap,
894 "numeric = '" + numeric + "'", null);
895
896 if (updated > 0)
897 {
Wink Savillee84c0a82014-06-09 21:04:39 -0700898 if (VDBG) log("Setting numeric '" + numeric + "' to be the current operator");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800899 }
900 else
901 {
Wink Savillee84c0a82014-06-09 21:04:39 -0700902 loge("Failed setting numeric '" + numeric + "' to the current operator");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800903 }
904 break;
905 }
John Huangb1bc16d2009-03-24 18:26:28 -0700906
Wink Savillee84c0a82014-06-09 21:04:39 -0700907 case URL_PREFERAPN_USING_SUBID:
908 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
909 {
910 String subIdString = url.getLastPathSegment();
911 try {
Wink Saville85477f62014-10-23 10:16:47 -0700912 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700913 } catch (NumberFormatException e) {
914 loge("NumberFormatException" + e);
915 return result;
916 }
917 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
918 }
919 //intentional fall through from above case
920
John Huangb1bc16d2009-03-24 18:26:28 -0700921 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600922 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -0700923 {
924 if (initialValues != null) {
925 if(initialValues.containsKey(COLUMN_APN_ID)) {
Wink Savillee84c0a82014-06-09 21:04:39 -0700926 setPreferredApnId(initialValues.getAsLong(COLUMN_APN_ID), subId);
John Huangb1bc16d2009-03-24 18:26:28 -0700927 }
928 }
929 break;
930 }
Wink Savillee84c0a82014-06-09 21:04:39 -0700931
932 case URL_SIMINFO: {
933 long id = db.insert(SIMINFO_TABLE, null, initialValues);
934 result = ContentUris.withAppendedId(SubscriptionManager.CONTENT_URI, id);
935 break;
936 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800937 }
938
939 if (notify) {
Amith Yamasani27085172014-11-06 09:01:20 -0800940 getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null,
941 true, UserHandle.USER_ALL);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800942 }
943
944 return result;
945 }
946
947 @Override
948 public int delete(Uri url, String where, String[] whereArgs)
949 {
Kazuhiro Ondod616ee62012-01-10 17:12:59 -0600950 int count = 0;
Wink Saville85477f62014-10-23 10:16:47 -0700951 int subId = SubscriptionManager.getDefaultDataSubId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800952
953 checkPermission();
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700954
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800955 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
956 int match = s_urlMatcher.match(url);
957 switch (match)
958 {
Wink Savillee84c0a82014-06-09 21:04:39 -0700959 case URL_TELEPHONY_USING_SUBID:
960 {
961 String subIdString = url.getLastPathSegment();
962 try {
Wink Saville85477f62014-10-23 10:16:47 -0700963 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700964 } catch (NumberFormatException e) {
965 loge("NumberFormatException" + e);
966 throw new IllegalArgumentException("Invalid subId " + url);
967 }
968 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
969 // FIXME use subId in query
970 }
971 //intentional fall through from above case
972
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800973 case URL_TELEPHONY:
974 {
975 count = db.delete(CARRIERS_TABLE, where, whereArgs);
976 break;
977 }
978
Wink Savillee84c0a82014-06-09 21:04:39 -0700979 case URL_CURRENT_USING_SUBID: {
980 String subIdString = url.getLastPathSegment();
981 try {
Wink Saville85477f62014-10-23 10:16:47 -0700982 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -0700983 } catch (NumberFormatException e) {
984 loge("NumberFormatException" + e);
985 throw new IllegalArgumentException("Invalid subId " + url);
986 }
987 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
988 // FIXME use subId in query
989 }
990 //intentional fall through from above case
991
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800992 case URL_CURRENT:
993 {
994 count = db.delete(CARRIERS_TABLE, where, whereArgs);
995 break;
996 }
Jaikumar Ganesh8e1a4f92009-10-26 13:07:37 -0700997
The Android Open Source Project7236c3a2009-03-03 19:32:44 -0800998 case URL_ID:
999 {
1000 count = db.delete(CARRIERS_TABLE, Telephony.Carriers._ID + "=?",
1001 new String[] { url.getLastPathSegment() });
1002 break;
1003 }
1004
Wink Savillee84c0a82014-06-09 21:04:39 -07001005 case URL_RESTOREAPN_USING_SUBID: {
1006 String subIdString = url.getLastPathSegment();
1007 try {
Wink Saville85477f62014-10-23 10:16:47 -07001008 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001009 } catch (NumberFormatException e) {
1010 loge("NumberFormatException" + e);
1011 throw new IllegalArgumentException("Invalid subId " + url);
1012 }
1013 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1014 // FIXME use subId in query
1015 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001016 case URL_RESTOREAPN: {
1017 count = 1;
Wink Savillee84c0a82014-06-09 21:04:39 -07001018 restoreDefaultAPN(subId);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001019 break;
1020 }
1021
Wink Savillee84c0a82014-06-09 21:04:39 -07001022 case URL_PREFERAPN_USING_SUBID:
1023 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: {
1024 String subIdString = url.getLastPathSegment();
1025 try {
Wink Saville85477f62014-10-23 10:16:47 -07001026 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001027 } catch (NumberFormatException e) {
1028 loge("NumberFormatException" + e);
1029 throw new IllegalArgumentException("Invalid subId " + url);
1030 }
1031 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1032 }
1033 //intentional fall through from above case
1034
John Huangb1bc16d2009-03-24 18:26:28 -07001035 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06001036 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07001037 {
Wink Savillee84c0a82014-06-09 21:04:39 -07001038 setPreferredApnId((long)-1, subId);
1039 if ((match == URL_PREFERAPN) || (match == URL_PREFERAPN_USING_SUBID)) count = 1;
1040 break;
1041 }
1042
1043 case URL_SIMINFO: {
1044 count = db.delete(SIMINFO_TABLE, where, whereArgs);
John Huangb1bc16d2009-03-24 18:26:28 -07001045 break;
1046 }
1047
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001048 default: {
1049 throw new UnsupportedOperationException("Cannot delete that URL: " + url);
1050 }
1051 }
1052
1053 if (count > 0) {
Amith Yamasani27085172014-11-06 09:01:20 -08001054 getContext().getContentResolver().notifyChange(Telephony.Carriers.CONTENT_URI, null,
1055 true, UserHandle.USER_ALL);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001056 }
1057
1058 return count;
1059 }
1060
1061 @Override
1062 public int update(Uri url, ContentValues values, String where, String[] whereArgs)
1063 {
John Huangb1bc16d2009-03-24 18:26:28 -07001064 int count = 0;
Wink Savillee84c0a82014-06-09 21:04:39 -07001065 int uriType = URL_UNKNOWN;
Wink Saville85477f62014-10-23 10:16:47 -07001066 int subId = SubscriptionManager.getDefaultDataSubId();
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001067
1068 checkPermission();
1069
1070 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1071 int match = s_urlMatcher.match(url);
1072 switch (match)
1073 {
Wink Savillee84c0a82014-06-09 21:04:39 -07001074 case URL_TELEPHONY_USING_SUBID:
1075 {
1076 String subIdString = url.getLastPathSegment();
1077 try {
Wink Saville85477f62014-10-23 10:16:47 -07001078 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001079 } catch (NumberFormatException e) {
1080 loge("NumberFormatException" + e);
1081 throw new IllegalArgumentException("Invalid subId " + url);
1082 }
1083 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1084 //FIXME use subId in the query
1085 }
1086 //intentional fall through from above case
1087
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001088 case URL_TELEPHONY:
1089 {
1090 count = db.update(CARRIERS_TABLE, values, where, whereArgs);
1091 break;
1092 }
1093
Wink Savillee84c0a82014-06-09 21:04:39 -07001094 case URL_CURRENT_USING_SUBID:
1095 {
1096 String subIdString = url.getLastPathSegment();
1097 try {
Wink Saville85477f62014-10-23 10:16:47 -07001098 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001099 } catch (NumberFormatException e) {
1100 loge("NumberFormatException" + e);
1101 throw new IllegalArgumentException("Invalid subId " + url);
1102 }
1103 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1104 //FIXME use subId in the query
1105 }
1106 //intentional fall through from above case
1107
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001108 case URL_CURRENT:
1109 {
1110 count = db.update(CARRIERS_TABLE, values, where, whereArgs);
1111 break;
1112 }
1113
1114 case URL_ID:
1115 {
1116 if (where != null || whereArgs != null) {
1117 throw new UnsupportedOperationException(
1118 "Cannot update URL " + url + " with a where clause");
1119 }
1120 count = db.update(CARRIERS_TABLE, values, Telephony.Carriers._ID + "=?",
1121 new String[] { url.getLastPathSegment() });
1122 break;
1123 }
1124
Wink Savillee84c0a82014-06-09 21:04:39 -07001125 case URL_PREFERAPN_USING_SUBID:
1126 case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
1127 {
1128 String subIdString = url.getLastPathSegment();
1129 try {
Wink Saville85477f62014-10-23 10:16:47 -07001130 subId = Integer.parseInt(subIdString);
Wink Savillee84c0a82014-06-09 21:04:39 -07001131 } catch (NumberFormatException e) {
1132 loge("NumberFormatException" + e);
1133 throw new IllegalArgumentException("Invalid subId " + url);
1134 }
1135 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
1136 }
1137
John Huangb1bc16d2009-03-24 18:26:28 -07001138 case URL_PREFERAPN:
Kazuhiro Ondod616ee62012-01-10 17:12:59 -06001139 case URL_PREFERAPN_NO_UPDATE:
John Huangb1bc16d2009-03-24 18:26:28 -07001140 {
1141 if (values != null) {
1142 if (values.containsKey(COLUMN_APN_ID)) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001143 setPreferredApnId(values.getAsLong(COLUMN_APN_ID), subId);
1144 if ((match == URL_PREFERAPN) ||
1145 (match == URL_PREFERAPN_USING_SUBID)) {
1146 count = 1;
1147 }
John Huangb1bc16d2009-03-24 18:26:28 -07001148 }
1149 }
1150 break;
1151 }
1152
Wink Savillee84c0a82014-06-09 21:04:39 -07001153 case URL_SIMINFO: {
1154 count = db.update(SIMINFO_TABLE, values, where, whereArgs);
1155 uriType = URL_SIMINFO;
1156 break;
1157 }
1158
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001159 default: {
1160 throw new UnsupportedOperationException("Cannot update that URL: " + url);
1161 }
1162 }
1163
1164 if (count > 0) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001165 switch (uriType) {
1166 case URL_SIMINFO:
1167 getContext().getContentResolver().notifyChange(
Amith Yamasani27085172014-11-06 09:01:20 -08001168 SubscriptionManager.CONTENT_URI, null, true, UserHandle.USER_ALL);
Wink Savillee84c0a82014-06-09 21:04:39 -07001169 break;
1170 default:
1171 getContext().getContentResolver().notifyChange(
Amith Yamasani27085172014-11-06 09:01:20 -08001172 Telephony.Carriers.CONTENT_URI, null, true, UserHandle.USER_ALL);
Wink Savillee84c0a82014-06-09 21:04:39 -07001173 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001174 }
1175
1176 return count;
1177 }
1178
1179 private void checkPermission() {
Shishir Agrawalacf787b2014-07-14 17:13:51 -07001180 int status = getContext().checkCallingOrSelfPermission(
1181 "android.permission.WRITE_APN_SETTINGS");
1182 if (status == PackageManager.PERMISSION_GRANTED) {
1183 return;
1184 }
1185
1186 PackageManager packageManager = getContext().getPackageManager();
1187 String[] packages = packageManager.getPackagesForUid(Binder.getCallingUid());
1188
1189 TelephonyManager telephonyManager =
1190 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
1191 for (String pkg : packages) {
1192 if (telephonyManager.checkCarrierPrivilegesForPackage(pkg) ==
1193 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1194 return;
1195 }
1196 }
1197 throw new SecurityException("No permission to write APN settings");
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001198 }
1199
Wink Savilled7c93502011-06-04 07:17:01 -07001200 private DatabaseHelper mOpenHelper;
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001201
Wink Saville85477f62014-10-23 10:16:47 -07001202 private void restoreDefaultAPN(int subId) {
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001203 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
1204
Hyejin Kimcfdb7432013-02-16 00:58:37 +09001205 try {
1206 db.delete(CARRIERS_TABLE, null, null);
1207 } catch (SQLException e) {
Wink Savillee84c0a82014-06-09 21:04:39 -07001208 loge("got exception when deleting to restore: " + e);
Hyejin Kimcfdb7432013-02-16 00:58:37 +09001209 }
Wink Savillee84c0a82014-06-09 21:04:39 -07001210 setPreferredApnId((long)-1, subId);
Wink Savilled7c93502011-06-04 07:17:01 -07001211 mOpenHelper.initDatabase(db);
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001212 }
Wink Savillee84c0a82014-06-09 21:04:39 -07001213
1214 /**
1215 * Log with debug
1216 *
1217 * @param s is string log
1218 */
1219 private static void log(String s) {
1220 Log.d(TAG, s);
1221 }
1222
1223 private static void loge(String s) {
1224 Log.e(TAG, s);
1225 }
The Android Open Source Project7236c3a2009-03-03 19:32:44 -08001226}