/* ** ** Copyright (C) 2014, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ /* * This class is used to create, load tables for HBPCD * HBPCD means 'Handset Based Plus Code Dialing', for CDMA network, most of network * couldn't handle international dialing number with '+', it need to be converted * to a IDD (International Direct Dialing) number, and some CDMA network won't * broadcast operator numeric, we need CDMA system ID and timezone etc. information * to get right MCC part of numeric, MNC part of numeric has no way to get in this * case, but for HBPCD, the MCC is enough. * * Table TABLE_MCC_LOOKUP_TABLE * This table has country name, country code, time zones for each MCC * * Table TABLE_MCC_IDD * This table has the IDDs for each MCC, some countries have multiple IDDs. * * Table TABLE_MCC_SID_RANGE * This table are SIDs assigned to each MCC * * Table TABLE_MCC_SID_CONFLICT * This table shows those SIDs are assigned to more than 1 MCC entry, * if the SID is here, it means the SID couldn't be matched to a single MCC, * it need to check the time zone and SID in TABLE_MCC_LOOKUP_TABLE to get * right MCC. * * Table TABLE_ARBITRARY_MCC_SID_MATCH * The SID listed in this table technically have operators in multiple MCC, * but conveniently only have *active* operators in a single MCC allowing a * unique SID->MCC lookup. Lookup by Timezone however would be complicatedi * as there will be multiple matches, and those matched entries have same * time zone, which can not tell which MCC is right. Conventionaly it is known * that SID is used only by the *active* operators in that MCC. * * Table TABLE_NANP_AREA_CODE * This table has NANP(North America Number Planning) area code, this is used * to check if a dialing number is a NANP number. */ package com.android.providers.telephony; import android.content.ContentValues; import android.content.Context; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.util.Log; import android.util.Xml; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import com.android.internal.telephony.HbpcdLookup; import com.android.internal.telephony.HbpcdLookup.MccIdd; import com.android.internal.telephony.HbpcdLookup.MccLookup; import com.android.internal.telephony.HbpcdLookup.MccSidConflicts; import com.android.internal.telephony.HbpcdLookup.MccSidRange; import com.android.internal.telephony.HbpcdLookup.ArbitraryMccSidMatch; import com.android.internal.telephony.HbpcdLookup.NanpAreaCode; public class HbpcdLookupDatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "HbpcdLockupDatabaseHelper"; private static final boolean DBG = true; private static final String DATABASE_NAME = "HbpcdLookup.db"; private static final int DATABASE_VERSION = 1; // Context to access resources with private Context mContext; /** * DatabaseHelper helper class for loading apns into a database. * * @param context of the user. */ public HbpcdLookupDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { //set up the database schema // 1 MCC may has more IDDs db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_IDD + "(_id INTEGER PRIMARY KEY," + "MCC INTEGER," + "IDD TEXT);"); db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_LOOKUP_TABLE + "(_id INTEGER PRIMARY KEY," + "MCC INTEGER," + "Country_Code TEXT," + "Country_Name TEXT," + "NDD TEXT," + "NANPS BOOLEAN," + "GMT_Offset_Low REAL," + "GMT_Offset_High REAL," + "GMT_DST_Low REAL," + "GMT_DST_High REAL);"); db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_SID_CONFLICT + "(_id INTEGER PRIMARY KEY," + "MCC INTEGER," + "SID_Conflict INTEGER);"); db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_MCC_SID_RANGE + "(_id INTEGER PRIMARY KEY," + "MCC INTEGER," + "SID_Range_Low INTEGER," + "SID_Range_High INTEGER);"); db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_NANP_AREA_CODE + "(_id INTEGER PRIMARY KEY," + "AREA_CODE INTEGER UNIQUE);"); db.execSQL("CREATE TABLE " + HbpcdLookupProvider.TABLE_ARBITRARY_MCC_SID_MATCH + "(_id INTEGER PRIMARY KEY," + "MCC INTEGER," + "SID INTEGER UNIQUE);"); initDatabase(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // do nothing } private void initDatabase (SQLiteDatabase db) { // Read internal data from xml Resources r = mContext.getResources(); XmlResourceParser parser = r.getXml(R.xml.hbpcd_lookup_tables); if (parser == null) { Log.e (TAG, "error to load the HBPCD resource"); } else { try { db.beginTransaction(); XmlUtils.beginDocument(parser, "hbpcd_info"); int eventType = parser.getEventType(); String tagName = parser.getName(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG && tagName.equalsIgnoreCase("table")) { String tableName = parser.getAttributeValue(null, "name"); loadTable(db, parser, tableName); } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } db.setTransactionSuccessful(); } catch (XmlPullParserException e) { Log.e (TAG, "Got XmlPullParserException when load hbpcd info"); } catch (IOException e) { Log.e (TAG, "Got IOException when load hbpcd info"); } catch (SQLException e) { Log.e (TAG, "Got SQLException when load hbpcd info"); } finally { db.endTransaction(); parser.close(); } } } private void loadTable(SQLiteDatabase db, XmlPullParser parser, String tableName) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("table"))) { ContentValues row = null; if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_IDD)) { row = getTableMccIddRow(parser); } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_LOOKUP_TABLE)) { row = getTableMccLookupTableRow(parser); } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_SID_CONFLICT)) { row = getTableMccSidConflictRow(parser); } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_MCC_SID_RANGE)) { row = getTableMccSidRangeRow(parser); } else if (tableName.equalsIgnoreCase(HbpcdLookupProvider.TABLE_NANP_AREA_CODE)) { row = getTableNanpAreaCodeRow(parser); } else if (tableName.equalsIgnoreCase( HbpcdLookupProvider.TABLE_ARBITRARY_MCC_SID_MATCH)) { row = getTableArbitraryMccSidMatch(parser); } else { Log.e(TAG, "unrecognized table name" + tableName); break; } if (row != null) { db.insert(tableName, null, row); } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } } private ContentValues getTableMccIddRow(XmlPullParser parser) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); ContentValues row = new ContentValues(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) { if (eventType == XmlPullParser.START_TAG) { if (tagName.equalsIgnoreCase(MccIdd.MCC)) { row.put(MccIdd.MCC, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccIdd.IDD)) { row.put(MccIdd.IDD, parser.nextText()); } } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } return row; } private ContentValues getTableMccLookupTableRow(XmlPullParser parser) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); ContentValues row = new ContentValues(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) { if (eventType == XmlPullParser.START_TAG) { if (tagName.equalsIgnoreCase(MccLookup.MCC)) { row.put(MccLookup.MCC, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccLookup.COUNTRY_CODE)) { row.put(MccLookup.COUNTRY_CODE, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccLookup.COUNTRY_NAME)) { row.put(MccLookup.COUNTRY_NAME, parser.nextText()); } else if (tagName.equalsIgnoreCase(MccLookup.NDD)) { row.put(MccLookup.NDD, parser.nextText()); } else if (tagName.equalsIgnoreCase(MccLookup.NANPS)) { row.put(MccLookup.NANPS, Boolean.parseBoolean(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccLookup.GMT_OFFSET_LOW)) { row.put(MccLookup.GMT_OFFSET_LOW, Float.parseFloat(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccLookup.GMT_OFFSET_HIGH)) { row.put(MccLookup.GMT_OFFSET_HIGH, Float.parseFloat(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccLookup.GMT_DST_LOW)) { row.put(MccLookup.GMT_DST_LOW, Float.parseFloat(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccLookup.GMT_DST_HIGH)) { row.put(MccLookup.GMT_DST_HIGH, Float.parseFloat(parser.nextText())); } } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } return row; } private ContentValues getTableMccSidConflictRow(XmlPullParser parser) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); ContentValues row = new ContentValues(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) { if (eventType == XmlPullParser.START_TAG) { if (tagName.equalsIgnoreCase(MccSidConflicts.MCC)) { row.put(MccSidConflicts.MCC, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccSidConflicts.SID_CONFLICT)) { row.put(MccSidConflicts.SID_CONFLICT, Integer.parseInt(parser.nextText())); } } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } return row; } private ContentValues getTableMccSidRangeRow(XmlPullParser parser) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); ContentValues row = new ContentValues(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) { if (eventType == XmlPullParser.START_TAG) { if (tagName.equalsIgnoreCase(MccSidRange.MCC)) { row.put(MccSidRange.MCC, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccSidRange.RANGE_LOW)) { row.put(MccSidRange.RANGE_LOW, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(MccSidRange.RANGE_HIGH)) { row.put(MccSidRange.RANGE_HIGH, Integer.parseInt(parser.nextText())); } } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } return row; } private ContentValues getTableNanpAreaCodeRow(XmlPullParser parser) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); ContentValues row = new ContentValues(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) { if (eventType == XmlPullParser.START_TAG) { if (tagName.equalsIgnoreCase(NanpAreaCode.AREA_CODE)) { row.put(NanpAreaCode.AREA_CODE, Integer.parseInt(parser.nextText())); } } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } return row; } private ContentValues getTableArbitraryMccSidMatch(XmlPullParser parser) throws XmlPullParserException, IOException { int eventType = parser.getEventType(); String tagName = parser.getName(); ContentValues row = new ContentValues(); while (!(eventType == XmlPullParser.END_TAG && tagName.equalsIgnoreCase("row"))) { if (eventType == XmlPullParser.START_TAG) { if (tagName.equalsIgnoreCase(ArbitraryMccSidMatch.MCC)) { row.put(ArbitraryMccSidMatch.MCC, Integer.parseInt(parser.nextText())); } else if (tagName.equalsIgnoreCase(ArbitraryMccSidMatch.SID)) { row.put(ArbitraryMccSidMatch.SID, Integer.parseInt(parser.nextText())); } } parser.next(); eventType = parser.getEventType(); tagName = parser.getName(); } return row; } }