• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright (C) 2014, 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 
18 /*
19  * This class is used to create, load tables for HBPCD
20  * HBPCD means 'Handset Based Plus Code Dialing', for CDMA network, most of network
21  * couldn't handle international dialing number with '+', it need to be converted
22  * to a IDD (International Direct Dialing) number, and some CDMA network won't
23  * broadcast operator numeric, we need CDMA system ID and timezone etc. information
24  * to get right MCC part of numeric, MNC part of numeric has no way to get in this
25  * case, but for HBPCD, the MCC is enough.
26  *
27  * Table TABLE_MCC_LOOKUP_TABLE
28  * This table has country name, country code, time zones for each MCC
29  *
30  * Table TABLE_MCC_IDD
31  * This table has the IDDs for each MCC, some countries have multiple IDDs.
32  *
33  * Table TABLE_MCC_SID_RANGE
34  * This table are SIDs assigned to each MCC
35  *
36  * Table TABLE_MCC_SID_CONFLICT
37  * This table shows those SIDs are assigned to more than 1 MCC entry,
38  * if the SID is here, it means the SID couldn't be matched to a single MCC,
39  * it need to check the time zone and SID in TABLE_MCC_LOOKUP_TABLE to get
40  * right MCC.
41  *
42  * Table TABLE_ARBITRARY_MCC_SID_MATCH
43  * The SID listed in this table technically have operators in multiple MCC,
44  * but conveniently only have *active* operators in a single MCC allowing a
45  * unique SID->MCC lookup.  Lookup by Timezone however would be complicatedi
46  * as there will be multiple matches, and those matched entries have same
47  * time zone, which can not tell which MCC is right. Conventionaly it is known
48  * that SID is used only by the *active* operators in that MCC.
49  *
50  * Table TABLE_NANP_AREA_CODE
51  * This table has NANP(North America Number Planning) area code, this is used
52  * to check if a dialing number is a NANP number.
53  */
54 
55 package com.android.providers.telephony;
56 
57 import android.content.ContentValues;
58 import android.content.Context;
59 import android.content.res.Resources;
60 import android.content.res.XmlResourceParser;
61 import android.database.Cursor;
62 import android.database.SQLException;
63 import android.database.sqlite.SQLiteDatabase;
64 import android.database.sqlite.SQLiteOpenHelper;
65 import android.database.sqlite.SQLiteQueryBuilder;
66 import android.util.Log;
67 import android.util.Xml;
68 import com.android.internal.util.XmlUtils;
69 
70 import org.xmlpull.v1.XmlPullParser;
71 import org.xmlpull.v1.XmlPullParserException;
72 
73 import java.io.IOException;
74 
75 import com.android.internal.telephony.HbpcdLookup;
76 import com.android.internal.telephony.HbpcdLookup.MccIdd;
77 import com.android.internal.telephony.HbpcdLookup.MccLookup;
78 import com.android.internal.telephony.HbpcdLookup.MccSidConflicts;
79 import com.android.internal.telephony.HbpcdLookup.MccSidRange;
80 import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch;
81 import com.android.internal.telephony.HbpcdLookup.NanpAreaCode;
82 
83 public class HbpcdLookupDatabaseHelper extends SQLiteOpenHelper {
84     private static final String TAG = "HbpcdLockupDatabaseHelper";
85     private static final boolean DBG = true;
86 
87     private static final String DATABASE_NAME = "HbpcdLookup.db";
88     private static final int DATABASE_VERSION = 1;
89     private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
90 
91     // Context to access resources with
92     private Context mContext;
93 
94     /**
95      * DatabaseHelper helper class for loading apns into a database.
96      *
97      * @param context of the user.
98      */
HbpcdLookupDatabaseHelper(Context context)99     public HbpcdLookupDatabaseHelper(Context context) {
100         super(context, DATABASE_NAME, null, DATABASE_VERSION);
101 
102         mContext = context;
103         // Memory optimization - close idle connections after 30s of inactivity
104         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
105     }
106 
107     @Override
onCreate(SQLiteDatabase db)108     public void onCreate(SQLiteDatabase db) {
109         //set up the database schema
110         // 1 MCC may has more IDDs
111         db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_IDD +
112             "(_id INTEGER PRIMARY KEY," +
113                 "MCC INTEGER," +
114                 "IDD TEXT);");
115 
116         db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_LOOKUP_TABLE +
117             "(_id INTEGER PRIMARY KEY," +
118                 "MCC INTEGER," +
119                 "Country_Code TEXT," +
120                 "Country_Name TEXT," +
121                 "NDD TEXT," +
122                 "NANPS BOOLEAN," +
123                 "GMT_Offset_Low REAL," +
124                 "GMT_Offset_High REAL," +
125                 "GMT_DST_Low REAL," +
126                 "GMT_DST_High REAL);");
127 
128         db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_SID_CONFLICT +
129             "(_id INTEGER PRIMARY KEY," +
130                 "MCC INTEGER," +
131                 "SID_Conflict INTEGER);");
132 
133         db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_SID_RANGE +
134             "(_id INTEGER PRIMARY KEY," +
135                 "MCC INTEGER," +
136                 "SID_Range_Low INTEGER," +
137                 "SID_Range_High INTEGER);");
138 
139         db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_NANP_AREA_CODE +
140             "(_id INTEGER PRIMARY KEY," +
141                 "AREA_CODE INTEGER UNIQUE);");
142 
143         db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_ARBITRARY_MCC_SID_MATCH +
144             "(_id INTEGER PRIMARY KEY," +
145                 "MCC INTEGER," +
146                 "SID INTEGER UNIQUE);");
147 
148         initDatabase(db);
149     }
150 
151     @Override
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)152     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
153         // do nothing
154     }
155 
initDatabase(SQLiteDatabase db)156     private void initDatabase (SQLiteDatabase db) {
157         // Read internal data from xml
158         Resources r = mContext.getResources();
159         XmlResourceParser parser = r.getXml(R.xml.hbpcd_lookup_tables);
160 
161         if (parser == null) {
162            Log.e (TAG, "error to load the HBPCD resource");
163         } else {
164             try {
165                 db.beginTransaction();
166                 XmlUtils.beginDocument(parser, "hbpcd_info");
167 
168                 int eventType = parser.getEventType();
169                 String tagName = parser.getName();
170 
171                 while (eventType != XmlPullParser.END_DOCUMENT) {
172                     if (eventType == XmlPullParser.START_TAG
173                             && tagName.equalsIgnoreCase("table")) {
174                         String tableName = parser.getAttributeValue(null, "name");
175                         loadTable(db, parser, tableName);
176                     }
177                     parser.next();
178                     eventType = parser.getEventType();
179                     tagName = parser.getName();
180                 }
181                 db.setTransactionSuccessful();
182             } catch (XmlPullParserException e) {
183                 Log.e (TAG, "Got XmlPullParserException when load hbpcd info");
184             } catch (IOException e) {
185                 Log.e (TAG, "Got IOException when load hbpcd info");
186             } catch (SQLException e) {
187                 Log.e (TAG, "Got SQLException when load hbpcd info");
188             } finally {
189                 db.endTransaction();
190                 parser.close();
191             }
192         }
193     }
194 
loadTable(SQLiteDatabase db, XmlPullParser parser, String tableName)195     private void loadTable(SQLiteDatabase db, XmlPullParser parser, String tableName)
196             throws XmlPullParserException, IOException {
197         int eventType = parser.getEventType();
198         String tagName = parser.getName();
199         while (!(eventType == XmlPullParser.END_TAG
200                 && tagName.equalsIgnoreCase("table"))) {
201             ContentValues row = null;
202             if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_IDD)) {
203                 row = getTableMccIddRow(parser);
204             } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_LOOKUP_TABLE)) {
205                 row = getTableMccLookupTableRow(parser);
206             } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_SID_CONFLICT)) {
207                 row = getTableMccSidConflictRow(parser);
208             } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_SID_RANGE)) {
209                 row = getTableMccSidRangeRow(parser);
210             } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_NANP_AREA_CODE)) {
211                 row = getTableNanpAreaCodeRow(parser);
212             } else if (tableName.equalsIgnoreCase(
213                     HbpcdLookupProvider.TABLE_ARBITRARY_MCC_SID_MATCH)) {
214                 row = getTableArbitraryMccSidMatch(parser);
215             } else {
216                 Log.e(TAG, "unrecognized table name"  + tableName);
217                 break;
218             }
219             if (row != null) {
220                 db.insert(tableName, null, row);
221             }
222             parser.next();
223             eventType = parser.getEventType();
224             tagName = parser.getName();
225         }
226     }
227 
getTableMccIddRow(XmlPullParser parser)228     private ContentValues getTableMccIddRow(XmlPullParser parser)
229             throws XmlPullParserException, IOException {
230         int eventType = parser.getEventType();
231         String tagName = parser.getName();
232         ContentValues row = new ContentValues();
233 
234         while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
235             if (eventType == XmlPullParser.START_TAG) {
236                 if (tagName.equalsIgnoreCase(MccIdd.MCC)) {
237                     row.put(MccIdd.MCC, Integer.parseInt(parser.nextText()));
238                 } else if (tagName.equalsIgnoreCase(MccIdd.IDD)) {
239                     row.put(MccIdd.IDD, parser.nextText());
240                 }
241             }
242             parser.next();
243             eventType = parser.getEventType();
244             tagName = parser.getName();
245         }
246         return row;
247     }
248 
getTableMccLookupTableRow(XmlPullParser parser)249     private ContentValues getTableMccLookupTableRow(XmlPullParser parser)
250             throws XmlPullParserException, IOException {
251         int eventType = parser.getEventType();
252         String tagName = parser.getName();
253         ContentValues row = new ContentValues();
254 
255         while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
256             if (eventType == XmlPullParser.START_TAG) {
257                 if (tagName.equalsIgnoreCase(MccLookup.MCC)) {
258                     row.put(MccLookup.MCC, Integer.parseInt(parser.nextText()));
259                 } else if (tagName.equalsIgnoreCase(MccLookup.COUNTRY_CODE)) {
260                     row.put(MccLookup.COUNTRY_CODE, Integer.parseInt(parser.nextText()));
261                 } else if (tagName.equalsIgnoreCase(MccLookup.COUNTRY_NAME)) {
262                     row.put(MccLookup.COUNTRY_NAME, parser.nextText());
263                 } else if (tagName.equalsIgnoreCase(MccLookup.NDD)) {
264                     row.put(MccLookup.NDD, parser.nextText());
265                 } else if (tagName.equalsIgnoreCase(MccLookup.NANPS)) {
266                     row.put(MccLookup.NANPS, Boolean.parseBoolean(parser.nextText()));
267                 } else if (tagName.equalsIgnoreCase(MccLookup.GMT_OFFSET_LOW)) {
268                     row.put(MccLookup.GMT_OFFSET_LOW, Float.parseFloat(parser.nextText()));
269                 } else if (tagName.equalsIgnoreCase(MccLookup.GMT_OFFSET_HIGH)) {
270                     row.put(MccLookup.GMT_OFFSET_HIGH, Float.parseFloat(parser.nextText()));
271                 } else if (tagName.equalsIgnoreCase(MccLookup.GMT_DST_LOW)) {
272                     row.put(MccLookup.GMT_DST_LOW, Float.parseFloat(parser.nextText()));
273                 } else if (tagName.equalsIgnoreCase(MccLookup.GMT_DST_HIGH)) {
274                     row.put(MccLookup.GMT_DST_HIGH, Float.parseFloat(parser.nextText()));
275                 }
276             }
277             parser.next();
278             eventType = parser.getEventType();
279             tagName = parser.getName();
280         }
281         return row;
282     }
283 
getTableMccSidConflictRow(XmlPullParser parser)284     private ContentValues getTableMccSidConflictRow(XmlPullParser parser)
285             throws XmlPullParserException, IOException {
286         int eventType = parser.getEventType();
287         String tagName = parser.getName();
288         ContentValues row = new ContentValues();
289 
290         while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
291             if (eventType == XmlPullParser.START_TAG) {
292                 if (tagName.equalsIgnoreCase(MccSidConflicts.MCC)) {
293                     row.put(MccSidConflicts.MCC, Integer.parseInt(parser.nextText()));
294                 } else if (tagName.equalsIgnoreCase(MccSidConflicts.SID_CONFLICT)) {
295                     row.put(MccSidConflicts.SID_CONFLICT, Integer.parseInt(parser.nextText()));
296                 }
297             }
298             parser.next();
299             eventType = parser.getEventType();
300             tagName = parser.getName();
301         }
302         return row;
303     }
304 
getTableMccSidRangeRow(XmlPullParser parser)305     private ContentValues getTableMccSidRangeRow(XmlPullParser parser)
306             throws XmlPullParserException, IOException {
307         int eventType = parser.getEventType();
308         String tagName = parser.getName();
309         ContentValues row = new ContentValues();
310 
311         while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
312             if (eventType == XmlPullParser.START_TAG) {
313                 if (tagName.equalsIgnoreCase(MccSidRange.MCC)) {
314                     row.put(MccSidRange.MCC, Integer.parseInt(parser.nextText()));
315                 } else if (tagName.equalsIgnoreCase(MccSidRange.RANGE_LOW)) {
316                     row.put(MccSidRange.RANGE_LOW, Integer.parseInt(parser.nextText()));
317                 } else if (tagName.equalsIgnoreCase(MccSidRange.RANGE_HIGH)) {
318                     row.put(MccSidRange.RANGE_HIGH, Integer.parseInt(parser.nextText()));
319                 }
320             }
321             parser.next();
322             eventType = parser.getEventType();
323             tagName = parser.getName();
324        }
325        return row;
326     }
327 
getTableNanpAreaCodeRow(XmlPullParser parser)328     private ContentValues getTableNanpAreaCodeRow(XmlPullParser parser)
329             throws XmlPullParserException, IOException {
330         int eventType = parser.getEventType();
331         String tagName = parser.getName();
332         ContentValues row = new ContentValues();
333 
334         while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
335             if (eventType == XmlPullParser.START_TAG) {
336                 if (tagName.equalsIgnoreCase(NanpAreaCode.AREA_CODE)) {
337                     row.put(NanpAreaCode.AREA_CODE, Integer.parseInt(parser.nextText()));
338                 }
339             }
340             parser.next();
341             eventType = parser.getEventType();
342             tagName = parser.getName();
343         }
344         return row;
345     }
346 
getTableArbitraryMccSidMatch(XmlPullParser parser)347     private ContentValues getTableArbitraryMccSidMatch(XmlPullParser parser)
348             throws XmlPullParserException, IOException {
349         int eventType = parser.getEventType();
350         String tagName = parser.getName();
351         ContentValues row = new ContentValues();
352 
353         while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) {
354             if (eventType == XmlPullParser.START_TAG) {
355                 if (tagName.equalsIgnoreCase(ArbitraryMccSidMatch.MCC)) {
356                     row.put(ArbitraryMccSidMatch.MCC, Integer.parseInt(parser.nextText()));
357                 } else if (tagName.equalsIgnoreCase(ArbitraryMccSidMatch.SID)) {
358                     row.put(ArbitraryMccSidMatch.SID, Integer.parseInt(parser.nextText()));
359                 }
360             }
361             parser.next();
362             eventType = parser.getEventType();
363             tagName = parser.getName();
364         }
365         return row;
366     }
367 }
368