blob: ceaed4c814890c04a03ba93f5d5ad9eb57f8818c [file] [log] [blame]
/*
**
** 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;
}
}