Messaging: Get rid of everything around the local apn database
Change-Id: Ie1916e93b274009494e76d6d99f36a025139127d
This commit is contained in:
3284
res/xml/apns.xml
3284
res/xml/apns.xml
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
* Copyright (C) 2024 The LineageOS Project
|
* Copyright (C) 2024-2025 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,8 +18,6 @@
|
|||||||
package android.support.v7.mms;
|
package android.support.v7.mms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XmlResourceParser;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteException;
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -28,8 +26,6 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.android.messaging.R;
|
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -112,95 +108,6 @@ class DefaultApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
public void setSuccess() {
|
public void setSuccess() {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(final BaseApn other) {
|
|
||||||
return TextUtils.equals(mMmsc, other.getMmsc()) &&
|
|
||||||
TextUtils.equals(mMmsProxy, other.getMmsProxy()) &&
|
|
||||||
mMmsProxyPort == other.getMmsProxyPort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An in-memory implementation of an APN. These APNs are organized into an in-memory list.
|
|
||||||
* The order of the list can be changed by the setSuccess method.
|
|
||||||
*/
|
|
||||||
private static class MemoryApn implements Apn {
|
|
||||||
/**
|
|
||||||
* Create an in-memory APN loaded from resources
|
|
||||||
*
|
|
||||||
* @param apns the in-memory APN list
|
|
||||||
* @param typesIn the APN type field
|
|
||||||
* @param mmscIn the APN mmsc field
|
|
||||||
* @param proxyIn the APN mmsproxy field
|
|
||||||
* @param portIn the APN mmsport field
|
|
||||||
* @return an in-memory APN instance, null if there is invalid parameter
|
|
||||||
*/
|
|
||||||
public static MemoryApn from(final List<Apn> apns, final String typesIn,
|
|
||||||
final String mmscIn, final String proxyIn, final String portIn) {
|
|
||||||
if (apns == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final BaseApn base = BaseApn.from(typesIn, mmscIn, proxyIn, portIn);
|
|
||||||
if (base == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (final Apn apn : apns) {
|
|
||||||
if (apn instanceof MemoryApn && ((MemoryApn) apn).equals(base)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new MemoryApn(apns, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<Apn> mApns;
|
|
||||||
private final BaseApn mBase;
|
|
||||||
|
|
||||||
public MemoryApn(final List<Apn> apns, final BaseApn base) {
|
|
||||||
mApns = apns;
|
|
||||||
mBase = base;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMmsc() {
|
|
||||||
return mBase.getMmsc();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMmsProxy() {
|
|
||||||
return mBase.getMmsProxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMmsProxyPort() {
|
|
||||||
return mBase.getMmsProxyPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSuccess() {
|
|
||||||
// If this is being marked as a successful APN, move it to the top of the list so
|
|
||||||
// next time it will be tried first
|
|
||||||
boolean moved = false;
|
|
||||||
synchronized (mApns) {
|
|
||||||
if (mApns.get(0) != this) {
|
|
||||||
mApns.remove(this);
|
|
||||||
mApns.add(0, this);
|
|
||||||
moved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (moved) {
|
|
||||||
Log.d(MmsService.TAG, "Set APN ["
|
|
||||||
+ "MMSC=" + getMmsc() + ", "
|
|
||||||
+ "PROXY=" + getMmsProxy() + ", "
|
|
||||||
+ "PORT=" + getMmsProxyPort() + "] to be first");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(final BaseApn other) {
|
|
||||||
if (other == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return mBase.equals(other);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,14 +129,6 @@ class DefaultApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
private static final int COLUMN_MMSPROXY = 2;
|
private static final int COLUMN_MMSPROXY = 2;
|
||||||
private static final int COLUMN_MMSPORT = 3;
|
private static final int COLUMN_MMSPORT = 3;
|
||||||
|
|
||||||
private static final String APN_MCC = "mcc";
|
|
||||||
private static final String APN_MNC = "mnc";
|
|
||||||
private static final String APN_APN = "apn";
|
|
||||||
private static final String APN_TYPE = "type";
|
|
||||||
private static final String APN_MMSC = "mmsc";
|
|
||||||
private static final String APN_MMSPROXY = "mmsproxy";
|
|
||||||
private static final String APN_MMSPORT = "mmsport";
|
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
// Cached APNs for subIds
|
// Cached APNs for subIds
|
||||||
@@ -263,16 +162,6 @@ class DefaultApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
|
private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
|
||||||
// Try system APN table first
|
// Try system APN table first
|
||||||
loadFromSystem(subId, apnName, apns);
|
loadFromSystem(subId, apnName, apns);
|
||||||
if (apns.size() > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Try loading from apns.xml in resources
|
|
||||||
loadFromResources(subId, apnName, apns);
|
|
||||||
if (apns.size() > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Try resources but without APN name
|
|
||||||
loadFromResources(subId, null/*apnName*/, apns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -384,48 +273,6 @@ class DefaultApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Find matching APNs using builtin APN list resource
|
|
||||||
*
|
|
||||||
* @param subId the SIM subId
|
|
||||||
* @param apnName the APN name to match
|
|
||||||
* @param apns the list for returning results
|
|
||||||
*/
|
|
||||||
private void loadFromResources(final int subId, final String apnName, final List<Apn> apns) {
|
|
||||||
Log.i(MmsService.TAG, "Loading APNs from resources, apnName=" + apnName);
|
|
||||||
final int[] mccMnc = Utils.getMccMnc(mContext, subId);
|
|
||||||
if (mccMnc[0] == 0) {
|
|
||||||
Log.w(MmsService.TAG, "Can not get valid mcc/mnc from system");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// MCC/MNC is good, loading/querying APNs from XML
|
|
||||||
try (XmlResourceParser xml = mContext.getResources().getXml(R.xml.apns)) {
|
|
||||||
new ApnsXmlParser(xml, apnValues -> {
|
|
||||||
final String mcc = trimWithNullCheck(apnValues.getAsString(APN_MCC));
|
|
||||||
final String mnc = trimWithNullCheck(apnValues.getAsString(APN_MNC));
|
|
||||||
final String apn = trimWithNullCheck(apnValues.getAsString(APN_APN));
|
|
||||||
try {
|
|
||||||
if (mccMnc[0] == Integer.parseInt(mcc) &&
|
|
||||||
mccMnc[1] == Integer.parseInt(mnc) &&
|
|
||||||
(TextUtils.isEmpty(apnName) || apnName.equalsIgnoreCase(apn))) {
|
|
||||||
final String type = apnValues.getAsString(APN_TYPE);
|
|
||||||
final String mmsc = apnValues.getAsString(APN_MMSC);
|
|
||||||
final String mmsproxy = apnValues.getAsString(APN_MMSPROXY);
|
|
||||||
final String mmsport = apnValues.getAsString(APN_MMSPORT);
|
|
||||||
final Apn newApn = MemoryApn.from(apns, type, mmsc, mmsproxy, mmsport);
|
|
||||||
if (newApn != null) {
|
|
||||||
apns.add(newApn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (final NumberFormatException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}).parse();
|
|
||||||
} catch (final Resources.NotFoundException e) {
|
|
||||||
Log.w(MmsService.TAG, "Can not get apns.xml " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String trimWithNullCheck(final String value) {
|
private static String trimWithNullCheck(final String value) {
|
||||||
return value != null ? value.trim() : null;
|
return value != null ? value.trim() : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import androidx.annotation.NonNull;
|
|||||||
|
|
||||||
import com.android.messaging.datamodel.DataModel;
|
import com.android.messaging.datamodel.DataModel;
|
||||||
import com.android.messaging.receiver.SmsReceiver;
|
import com.android.messaging.receiver.SmsReceiver;
|
||||||
import com.android.messaging.sms.ApnDatabase;
|
|
||||||
import com.android.messaging.sms.BugleApnSettingsLoader;
|
import com.android.messaging.sms.BugleApnSettingsLoader;
|
||||||
import com.android.messaging.sms.BugleUserAgentInfoLoader;
|
import com.android.messaging.sms.BugleUserAgentInfoLoader;
|
||||||
import com.android.messaging.sms.MmsConfig;
|
import com.android.messaging.sms.MmsConfig;
|
||||||
@@ -85,8 +84,6 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
|
|||||||
|
|
||||||
// Initialize MMS lib
|
// Initialize MMS lib
|
||||||
initMmsLib(context, carrierConfigValuesLoader);
|
initMmsLib(context, carrierConfigValuesLoader);
|
||||||
// Initialize APN database
|
|
||||||
ApnDatabase.initializeAppContext(context);
|
|
||||||
// Fixup messages in flight if we crashed and send any pending
|
// Fixup messages in flight if we crashed and send any pending
|
||||||
dataModel.onApplicationCreated();
|
dataModel.onApplicationCreated();
|
||||||
// Register carrier config change receiver
|
// Register carrier config change receiver
|
||||||
|
|||||||
@@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
|
||||||
* Copyright (C) 2024-2025 The LineageOS 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.messaging.sms;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.XmlResourceParser;
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
|
||||||
import android.provider.Telephony;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.android.messaging.R;
|
|
||||||
import com.android.messaging.datamodel.data.ParticipantData;
|
|
||||||
import com.android.messaging.util.LogUtil;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Database helper class for looking up APNs. This database has a single table
|
|
||||||
* which stores the APNs that are initially created from an xml file.
|
|
||||||
*/
|
|
||||||
public class ApnDatabase extends SQLiteOpenHelper {
|
|
||||||
private static final int DB_VERSION = 3; // added sub_id columns
|
|
||||||
|
|
||||||
private static final String TAG = LogUtil.BUGLE_TAG;
|
|
||||||
|
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
|
|
||||||
private static Context sContext;
|
|
||||||
private static ApnDatabase sApnDatabase;
|
|
||||||
|
|
||||||
private static final String APN_DATABASE_NAME = "apn.db";
|
|
||||||
|
|
||||||
/** table for carrier APN's */
|
|
||||||
public static final String APN_TABLE = "apn";
|
|
||||||
|
|
||||||
// APN table
|
|
||||||
private static final String APN_TABLE_SQL =
|
|
||||||
"CREATE TABLE " + APN_TABLE +
|
|
||||||
"(_id INTEGER PRIMARY KEY," +
|
|
||||||
Telephony.Carriers.NAME + " TEXT," +
|
|
||||||
Telephony.Carriers.NUMERIC + " TEXT," +
|
|
||||||
Telephony.Carriers.MCC + " TEXT," +
|
|
||||||
Telephony.Carriers.MNC + " TEXT," +
|
|
||||||
Telephony.Carriers.APN + " TEXT," +
|
|
||||||
Telephony.Carriers.USER + " TEXT," +
|
|
||||||
Telephony.Carriers.SERVER + " TEXT," +
|
|
||||||
Telephony.Carriers.PASSWORD + " TEXT," +
|
|
||||||
Telephony.Carriers.PROXY + " TEXT," +
|
|
||||||
Telephony.Carriers.PORT + " TEXT," +
|
|
||||||
Telephony.Carriers.MMSPROXY + " TEXT," +
|
|
||||||
Telephony.Carriers.MMSPORT + " TEXT," +
|
|
||||||
Telephony.Carriers.MMSC + " TEXT," +
|
|
||||||
Telephony.Carriers.AUTH_TYPE + " INTEGER," +
|
|
||||||
Telephony.Carriers.TYPE + " TEXT," +
|
|
||||||
Telephony.Carriers.CURRENT + " INTEGER," +
|
|
||||||
Telephony.Carriers.PROTOCOL + " TEXT," +
|
|
||||||
Telephony.Carriers.ROAMING_PROTOCOL + " TEXT," +
|
|
||||||
Telephony.Carriers.CARRIER_ENABLED + " BOOLEAN," +
|
|
||||||
Telephony.Carriers.BEARER + " INTEGER," +
|
|
||||||
Telephony.Carriers.MVNO_TYPE + " TEXT," +
|
|
||||||
Telephony.Carriers.MVNO_MATCH_DATA + " TEXT," +
|
|
||||||
Telephony.Carriers.SUBSCRIPTION_ID + " INTEGER DEFAULT " +
|
|
||||||
ParticipantData.DEFAULT_SELF_SUB_ID + ");";
|
|
||||||
public static final int COLUMN_ID = 4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ApnDatabase is initialized asynchronously from the application.onCreate
|
|
||||||
* To ensure that it works in a testing environment it needs to never access the factory context
|
|
||||||
*/
|
|
||||||
public static void initializeAppContext(final Context context) {
|
|
||||||
sContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApnDatabase() {
|
|
||||||
super(sContext, APN_DATABASE_NAME, null, DB_VERSION);
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase constructor");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApnDatabase getApnDatabase() {
|
|
||||||
if (sApnDatabase == null) {
|
|
||||||
sApnDatabase = new ApnDatabase();
|
|
||||||
}
|
|
||||||
return sApnDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean doesDatabaseExist() {
|
|
||||||
final File dbFile = sContext.getDatabasePath(APN_DATABASE_NAME);
|
|
||||||
return dbFile.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(final SQLiteDatabase db) {
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase onCreate");
|
|
||||||
}
|
|
||||||
// Build the table using defaults (apn info bundled with the app)
|
|
||||||
rebuildTables(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOpen(final SQLiteDatabase db) {
|
|
||||||
super.onOpen(db);
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase onOpen");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
super.close();
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase close");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rebuildTables(final SQLiteDatabase db) {
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase rebuildTables");
|
|
||||||
}
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + APN_TABLE + ";");
|
|
||||||
db.execSQL(APN_TABLE_SQL);
|
|
||||||
loadApnTable(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase onUpgrade");
|
|
||||||
}
|
|
||||||
rebuildTables(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
|
||||||
if (DEBUG) {
|
|
||||||
LogUtil.d(TAG, "ApnDatabase onDowngrade");
|
|
||||||
}
|
|
||||||
rebuildTables(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load APN table from app resources
|
|
||||||
*/
|
|
||||||
private static void loadApnTable(final SQLiteDatabase db) {
|
|
||||||
LogUtil.v(TAG, "ApnDatabase loadApnTable");
|
|
||||||
final Resources r = sContext.getResources();
|
|
||||||
final XmlResourceParser parser = r.getXml(R.xml.apns);
|
|
||||||
final ApnsXmlProcessor processor = ApnsXmlProcessor.get(parser);
|
|
||||||
processor.setApnHandler(apnValues -> db.insert(APN_TABLE, null/*nullColumnHack*/,
|
|
||||||
apnValues));
|
|
||||||
try {
|
|
||||||
processor.process();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
Log.e(TAG, "Got exception while loading APN database.", e);
|
|
||||||
} finally {
|
|
||||||
parser.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void forceBuildAndLoadApnTables() {
|
|
||||||
final SQLiteDatabase db = getApnDatabase().getWritableDatabase();
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + APN_TABLE);
|
|
||||||
// Table(s) always need for JB MR1 for APN support for MMS because JB MR1 throws
|
|
||||||
// a SecurityException when trying to access the carriers table (which holds the
|
|
||||||
// APNs). Some JB MR2 devices also throw the security exception, so we're building
|
|
||||||
// the table for JB MR2, too.
|
|
||||||
db.execSQL(APN_TABLE_SQL);
|
|
||||||
|
|
||||||
loadApnTable(db);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
* Copyright (C) 2024 The LineageOS Project
|
* Copyright (C) 2024-2025 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,18 +18,15 @@
|
|||||||
package com.android.messaging.sms;
|
package com.android.messaging.sms;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.provider.Telephony;
|
|
||||||
|
|
||||||
import com.android.messaging.util.Assert;
|
import com.android.messaging.util.Assert;
|
||||||
import com.android.messaging.util.LogUtil;
|
import com.android.messaging.util.LogUtil;
|
||||||
import com.android.messaging.util.PhoneUtils;
|
import com.android.messaging.util.PhoneUtils;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XML processor for the following files:
|
* XML processor for the following files:
|
||||||
@@ -37,46 +34,14 @@ import java.util.Map;
|
|||||||
* 2. res/xml/mms_config.xml (or related overlay files)
|
* 2. res/xml/mms_config.xml (or related overlay files)
|
||||||
*/
|
*/
|
||||||
class ApnsXmlProcessor {
|
class ApnsXmlProcessor {
|
||||||
public interface ApnHandler {
|
|
||||||
void process(ContentValues apnValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface MmsConfigHandler {
|
public interface MmsConfigHandler {
|
||||||
void process(String mccMnc, String key, String value, String type);
|
void process(String mccMnc, String key, String value, String type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String TAG = LogUtil.BUGLE_TAG;
|
private static final String TAG = LogUtil.BUGLE_TAG;
|
||||||
|
|
||||||
private static final Map<String, String> APN_ATTRIBUTE_MAP = Maps.newHashMap();
|
|
||||||
static {
|
|
||||||
APN_ATTRIBUTE_MAP.put("mcc", Telephony.Carriers.MCC);
|
|
||||||
APN_ATTRIBUTE_MAP.put("mnc", Telephony.Carriers.MNC);
|
|
||||||
APN_ATTRIBUTE_MAP.put("carrier", Telephony.Carriers.NAME);
|
|
||||||
APN_ATTRIBUTE_MAP.put("apn", Telephony.Carriers.APN);
|
|
||||||
APN_ATTRIBUTE_MAP.put("mmsc", Telephony.Carriers.MMSC);
|
|
||||||
APN_ATTRIBUTE_MAP.put("mmsproxy", Telephony.Carriers.MMSPROXY);
|
|
||||||
APN_ATTRIBUTE_MAP.put("mmsport", Telephony.Carriers.MMSPORT);
|
|
||||||
APN_ATTRIBUTE_MAP.put("type", Telephony.Carriers.TYPE);
|
|
||||||
APN_ATTRIBUTE_MAP.put("user", Telephony.Carriers.USER);
|
|
||||||
APN_ATTRIBUTE_MAP.put("password", Telephony.Carriers.PASSWORD);
|
|
||||||
APN_ATTRIBUTE_MAP.put("authtype", Telephony.Carriers.AUTH_TYPE);
|
|
||||||
APN_ATTRIBUTE_MAP.put("mvno_match_data", Telephony.Carriers.MVNO_MATCH_DATA);
|
|
||||||
APN_ATTRIBUTE_MAP.put("mvno_type", Telephony.Carriers.MVNO_TYPE);
|
|
||||||
APN_ATTRIBUTE_MAP.put("protocol", Telephony.Carriers.PROTOCOL);
|
|
||||||
APN_ATTRIBUTE_MAP.put("bearer", Telephony.Carriers.BEARER);
|
|
||||||
APN_ATTRIBUTE_MAP.put("server", Telephony.Carriers.SERVER);
|
|
||||||
APN_ATTRIBUTE_MAP.put("roaming_protocol", Telephony.Carriers.ROAMING_PROTOCOL);
|
|
||||||
APN_ATTRIBUTE_MAP.put("proxy", Telephony.Carriers.PROXY);
|
|
||||||
APN_ATTRIBUTE_MAP.put("port", Telephony.Carriers.PORT);
|
|
||||||
APN_ATTRIBUTE_MAP.put("carrier_enabled", Telephony.Carriers.CARRIER_ENABLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String TAG_APNS = "apns";
|
|
||||||
private static final String TAG_APN = "apn";
|
|
||||||
private static final String TAG_MMS_CONFIG = "mms_config";
|
private static final String TAG_MMS_CONFIG = "mms_config";
|
||||||
|
|
||||||
// Handler to process one apn
|
|
||||||
private ApnHandler mApnHandler;
|
|
||||||
// Handler to process one mms_config key/value pair
|
// Handler to process one mms_config key/value pair
|
||||||
private MmsConfigHandler mMmsConfigHandler;
|
private MmsConfigHandler mMmsConfigHandler;
|
||||||
|
|
||||||
@@ -86,7 +51,6 @@ class ApnsXmlProcessor {
|
|||||||
|
|
||||||
private ApnsXmlProcessor(XmlPullParser parser) {
|
private ApnsXmlProcessor(XmlPullParser parser) {
|
||||||
mInputParser = parser;
|
mInputParser = parser;
|
||||||
mApnHandler = null;
|
|
||||||
mMmsConfigHandler = null;
|
mMmsConfigHandler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,11 +59,6 @@ class ApnsXmlProcessor {
|
|||||||
return new ApnsXmlProcessor(parser);
|
return new ApnsXmlProcessor(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApnsXmlProcessor setApnHandler(ApnHandler handler) {
|
|
||||||
mApnHandler = handler;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ApnsXmlProcessor setMmsConfigHandler(MmsConfigHandler handler) {
|
public ApnsXmlProcessor setMmsConfigHandler(MmsConfigHandler handler) {
|
||||||
mMmsConfigHandler = handler;
|
mMmsConfigHandler = handler;
|
||||||
return this;
|
return this;
|
||||||
@@ -131,22 +90,8 @@ class ApnsXmlProcessor {
|
|||||||
// an apn element
|
// an apn element
|
||||||
final ContentValues values = new ContentValues();
|
final ContentValues values = new ContentValues();
|
||||||
String tagName = mInputParser.getName();
|
String tagName = mInputParser.getName();
|
||||||
// Top level tag can be "apns" (apns.xml)
|
// Top level tag can be "mms_config" (mms_config.xml)
|
||||||
// or "mms_config" (mms_config.xml)
|
if (TAG_MMS_CONFIG.equals(tagName)) {
|
||||||
if (TAG_APNS.equals(tagName)) {
|
|
||||||
// For "apns", there could be "apn" or both "apn" and "mms_config"
|
|
||||||
for (;;) {
|
|
||||||
if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tagName = mInputParser.getName();
|
|
||||||
if (TAG_APN.equals(tagName)) {
|
|
||||||
processApn(values);
|
|
||||||
} else if (TAG_MMS_CONFIG.equals(tagName)) {
|
|
||||||
processMmsConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (TAG_MMS_CONFIG.equals(tagName)) {
|
|
||||||
// mms_config.xml resource
|
// mms_config.xml resource
|
||||||
processMmsConfig();
|
processMmsConfig();
|
||||||
}
|
}
|
||||||
@@ -157,28 +102,6 @@ class ApnsXmlProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer parseInt(String text, Integer defaultValue, String logHint) {
|
|
||||||
Integer value = defaultValue;
|
|
||||||
try {
|
|
||||||
value = Integer.parseInt(text);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.e(TAG,
|
|
||||||
"Invalid value " + text + "for" + logHint + " @" + xmlParserDebugContext());
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean parseBoolean(String text, Boolean defaultValue, String logHint) {
|
|
||||||
Boolean value = defaultValue;
|
|
||||||
try {
|
|
||||||
value = Boolean.parseBoolean(text);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.e(TAG,
|
|
||||||
"Invalid value " + text + "for" + logHint + " @" + xmlParserDebugContext());
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String xmlParserEventString(int event) {
|
private static String xmlParserEventString(int event) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT";
|
case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT";
|
||||||
@@ -219,51 +142,6 @@ class ApnsXmlProcessor {
|
|||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Process one apn
|
|
||||||
*
|
|
||||||
* @param apnValues Where we store the parsed apn
|
|
||||||
*/
|
|
||||||
private void processApn(ContentValues apnValues) throws IOException, XmlPullParserException {
|
|
||||||
Assert.notNull(apnValues);
|
|
||||||
apnValues.clear();
|
|
||||||
// Collect all the attributes
|
|
||||||
for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
|
|
||||||
final String key = APN_ATTRIBUTE_MAP.get(mInputParser.getAttributeName(i));
|
|
||||||
if (key != null) {
|
|
||||||
apnValues.put(key, mInputParser.getAttributeValue(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Set numeric to be canonicalized mcc/mnc like "310120", always 6 digits
|
|
||||||
final String canonicalMccMnc = PhoneUtils.canonicalizeMccMnc(
|
|
||||||
apnValues.getAsString(Telephony.Carriers.MCC),
|
|
||||||
apnValues.getAsString(Telephony.Carriers.MNC));
|
|
||||||
apnValues.put(Telephony.Carriers.NUMERIC, canonicalMccMnc);
|
|
||||||
// Some of the values should not be string type, converting them to desired types
|
|
||||||
final String authType = apnValues.getAsString(Telephony.Carriers.AUTH_TYPE);
|
|
||||||
if (authType != null) {
|
|
||||||
apnValues.put(Telephony.Carriers.AUTH_TYPE, parseInt(authType, -1, "apn authtype"));
|
|
||||||
}
|
|
||||||
final String carrierEnabled = apnValues.getAsString(Telephony.Carriers.CARRIER_ENABLED);
|
|
||||||
if (carrierEnabled != null) {
|
|
||||||
apnValues.put(Telephony.Carriers.CARRIER_ENABLED,
|
|
||||||
parseBoolean(carrierEnabled, null, "apn carrierEnabled"));
|
|
||||||
}
|
|
||||||
final String bearer = apnValues.getAsString(Telephony.Carriers.BEARER);
|
|
||||||
if (bearer != null) {
|
|
||||||
apnValues.put(Telephony.Carriers.BEARER, parseInt(bearer, 0, "apn bearer"));
|
|
||||||
}
|
|
||||||
// We are at the end tag
|
|
||||||
if (mInputParser.next() != XmlPullParser.END_TAG) {
|
|
||||||
throw new XmlPullParserException("Apn: expecting end tag @"
|
|
||||||
+ xmlParserDebugContext());
|
|
||||||
}
|
|
||||||
// We are done parsing one APN, call the handler
|
|
||||||
if (mApnHandler != null) {
|
|
||||||
mApnHandler.process(apnValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process one mms_config.
|
* Process one mms_config.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,10 +17,8 @@
|
|||||||
|
|
||||||
package com.android.messaging.sms;
|
package com.android.messaging.sms;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
|
||||||
import android.database.sqlite.SQLiteException;
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.Telephony;
|
import android.provider.Telephony;
|
||||||
@@ -119,151 +117,6 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
public void setSuccess() {
|
public void setSuccess() {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(final BaseApn other) {
|
|
||||||
return TextUtils.equals(mMmsc, other.getMmsc()) &&
|
|
||||||
TextUtils.equals(mMmsProxy, other.getMmsProxy()) &&
|
|
||||||
mMmsProxyPort == other.getMmsProxyPort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The APN represented by the local APN table row
|
|
||||||
*/
|
|
||||||
private static class DatabaseApn implements Apn {
|
|
||||||
private static final ContentValues CURRENT_NULL_VALUE;
|
|
||||||
private static final ContentValues CURRENT_SET_VALUE;
|
|
||||||
static {
|
|
||||||
CURRENT_NULL_VALUE = new ContentValues(1);
|
|
||||||
CURRENT_NULL_VALUE.putNull(Telephony.Carriers.CURRENT);
|
|
||||||
CURRENT_SET_VALUE = new ContentValues(1);
|
|
||||||
CURRENT_SET_VALUE.put(Telephony.Carriers.CURRENT, "1"); // 1 for auto selected APN
|
|
||||||
}
|
|
||||||
private static final String CLEAR_UPDATE_SELECTION = Telephony.Carriers.CURRENT + " =?";
|
|
||||||
private static final String[] CLEAR_UPDATE_SELECTION_ARGS = new String[] { "1" };
|
|
||||||
private static final String SET_UPDATE_SELECTION = Telephony.Carriers._ID + " =?";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an APN loaded from local database
|
|
||||||
*
|
|
||||||
* @param apns the in-memory APN list
|
|
||||||
* @param typesIn the APN type field
|
|
||||||
* @param mmscIn the APN mmsc field
|
|
||||||
* @param proxyIn the APN mmsproxy field
|
|
||||||
* @param portIn the APN mmsport field
|
|
||||||
* @param rowId the APN's row ID in database
|
|
||||||
* @param current the value of CURRENT column in database
|
|
||||||
* @return an in-memory APN instance for database APN row, null if parameter invalid
|
|
||||||
*/
|
|
||||||
public static DatabaseApn from(final List<Apn> apns, final String typesIn,
|
|
||||||
final String mmscIn, final String proxyIn, final String portIn,
|
|
||||||
final long rowId, final int current) {
|
|
||||||
if (apns == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final BaseApn base = BaseApn.from(typesIn, mmscIn, proxyIn, portIn);
|
|
||||||
if (base == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (final ApnSettingsLoader.Apn apn : apns) {
|
|
||||||
if (apn instanceof DatabaseApn && ((DatabaseApn) apn).equals(base)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new DatabaseApn(apns, base, rowId, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<Apn> mApns;
|
|
||||||
private final BaseApn mBase;
|
|
||||||
private final long mRowId;
|
|
||||||
private int mCurrent;
|
|
||||||
|
|
||||||
public DatabaseApn(final List<Apn> apns, final BaseApn base, final long rowId,
|
|
||||||
final int current) {
|
|
||||||
mApns = apns;
|
|
||||||
mBase = base;
|
|
||||||
mRowId = rowId;
|
|
||||||
mCurrent = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMmsc() {
|
|
||||||
return mBase.getMmsc();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMmsProxy() {
|
|
||||||
return mBase.getMmsProxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMmsProxyPort() {
|
|
||||||
return mBase.getMmsProxyPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSuccess() {
|
|
||||||
moveToListHead();
|
|
||||||
setCurrentInDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to move this APN to the head of in-memory list
|
|
||||||
*/
|
|
||||||
private void moveToListHead() {
|
|
||||||
// If this is being marked as a successful APN, move it to the top of the list so
|
|
||||||
// next time it will be tried first
|
|
||||||
boolean moved = false;
|
|
||||||
synchronized (mApns) {
|
|
||||||
if (mApns.get(0) != this) {
|
|
||||||
mApns.remove(this);
|
|
||||||
mApns.add(0, this);
|
|
||||||
moved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (moved) {
|
|
||||||
LogUtil.d(LogUtil.BUGLE_TAG, "Set APN ["
|
|
||||||
+ "MMSC=" + getMmsc() + ", "
|
|
||||||
+ "PROXY=" + getMmsProxy() + ", "
|
|
||||||
+ "PORT=" + getMmsProxyPort() + "] to be first");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to set the APN to be CURRENT in its database table
|
|
||||||
*/
|
|
||||||
private void setCurrentInDatabase() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (mCurrent > 0) {
|
|
||||||
// Already current
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCurrent = 1;
|
|
||||||
}
|
|
||||||
LogUtil.d(LogUtil.BUGLE_TAG, "Set APN @" + mRowId + " to be CURRENT in local db");
|
|
||||||
final SQLiteDatabase database = ApnDatabase.getApnDatabase().getWritableDatabase();
|
|
||||||
database.beginTransaction();
|
|
||||||
try {
|
|
||||||
// clear the previous current=1 apn
|
|
||||||
// we don't clear current=2 apn since it is manually selected by user
|
|
||||||
// and we should not override it.
|
|
||||||
database.update(ApnDatabase.APN_TABLE, CURRENT_NULL_VALUE,
|
|
||||||
CLEAR_UPDATE_SELECTION, CLEAR_UPDATE_SELECTION_ARGS);
|
|
||||||
// set this one to be current (1)
|
|
||||||
database.update(ApnDatabase.APN_TABLE, CURRENT_SET_VALUE, SET_UPDATE_SELECTION,
|
|
||||||
new String[] { Long.toString(mRowId) });
|
|
||||||
database.setTransactionSuccessful();
|
|
||||||
} finally {
|
|
||||||
database.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(final BaseApn other) {
|
|
||||||
if (other == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return mBase.equals(other);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,14 +133,7 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
Telephony.Carriers.MMSPROXY,
|
Telephony.Carriers.MMSPROXY,
|
||||||
Telephony.Carriers.MMSPORT,
|
Telephony.Carriers.MMSPORT,
|
||||||
};
|
};
|
||||||
private static final String[] APN_PROJECTION_LOCAL = {
|
|
||||||
Telephony.Carriers.TYPE,
|
|
||||||
Telephony.Carriers.MMSC,
|
|
||||||
Telephony.Carriers.MMSPROXY,
|
|
||||||
Telephony.Carriers.MMSPORT,
|
|
||||||
Telephony.Carriers.CURRENT,
|
|
||||||
Telephony.Carriers._ID,
|
|
||||||
};
|
|
||||||
private static final int COLUMN_TYPE = 0;
|
private static final int COLUMN_TYPE = 0;
|
||||||
private static final int COLUMN_MMSC = 1;
|
private static final int COLUMN_MMSC = 1;
|
||||||
private static final int COLUMN_MMSPROXY = 2;
|
private static final int COLUMN_MMSPROXY = 2;
|
||||||
@@ -297,8 +143,6 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
|
|
||||||
private static final String SELECTION_APN = Telephony.Carriers.APN + "=?";
|
private static final String SELECTION_APN = Telephony.Carriers.APN + "=?";
|
||||||
private static final String SELECTION_CURRENT = Telephony.Carriers.CURRENT + " IS NOT NULL";
|
private static final String SELECTION_CURRENT = Telephony.Carriers.CURRENT + " IS NOT NULL";
|
||||||
private static final String SELECTION_NUMERIC = Telephony.Carriers.NUMERIC + "=?";
|
|
||||||
private static final String ORDER_BY = Telephony.Carriers.CURRENT + " DESC";
|
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
@@ -334,14 +178,6 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
|
private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
|
||||||
// Try system APN table
|
// Try system APN table
|
||||||
loadFromSystem(subId, apnName, apns);
|
loadFromSystem(subId, apnName, apns);
|
||||||
if (apns.size() > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Try local APN table
|
|
||||||
loadFromLocalDatabase(apnName, apns);
|
|
||||||
if (apns.size() <= 0) {
|
|
||||||
LogUtil.w(LogUtil.BUGLE_TAG, "Failed to load any APN");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -455,85 +291,6 @@ public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load matching APNs from local APN table.
|
|
||||||
* We try both using the APN name and not using the APN name.
|
|
||||||
*
|
|
||||||
* @param apnName the APN name
|
|
||||||
* @param apns the list of results to return
|
|
||||||
*/
|
|
||||||
private void loadFromLocalDatabase(final String apnName, final List<Apn> apns) {
|
|
||||||
LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from local APN table");
|
|
||||||
final SQLiteDatabase database = ApnDatabase.getApnDatabase().getWritableDatabase();
|
|
||||||
final String mccMnc = PhoneUtils.getMccMncString(PhoneUtils.getDefault().getMccMnc());
|
|
||||||
Cursor cursor;
|
|
||||||
cursor = queryLocalDatabase(database, mccMnc, apnName);
|
|
||||||
if (cursor == null) {
|
|
||||||
cursor = queryLocalDatabase(database, mccMnc, null/*apnName*/);
|
|
||||||
}
|
|
||||||
if (cursor == null) {
|
|
||||||
LogUtil.w(LogUtil.BUGLE_TAG, "Could not find any APN in local table");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
final Apn apn = DatabaseApn.from(apns,
|
|
||||||
cursor.getString(COLUMN_TYPE),
|
|
||||||
cursor.getString(COLUMN_MMSC),
|
|
||||||
cursor.getString(COLUMN_MMSPROXY),
|
|
||||||
cursor.getString(COLUMN_MMSPORT),
|
|
||||||
cursor.getLong(COLUMN_ID),
|
|
||||||
cursor.getInt(COLUMN_CURRENT));
|
|
||||||
if (apn != null) {
|
|
||||||
apns.add(apn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a query of local APN table based on MCC/MNC and APN name, sorted by CURRENT
|
|
||||||
* column in descending order
|
|
||||||
*
|
|
||||||
* @param db the local database
|
|
||||||
* @param numeric the MCC/MNC string
|
|
||||||
* @param apnName the optional APN name to match
|
|
||||||
* @return the cursor of the query, null if no result
|
|
||||||
*/
|
|
||||||
private static Cursor queryLocalDatabase(final SQLiteDatabase db, final String numeric,
|
|
||||||
final String apnName) {
|
|
||||||
final String selection;
|
|
||||||
final String[] selectionArgs;
|
|
||||||
if (TextUtils.isEmpty(apnName)) {
|
|
||||||
selection = SELECTION_NUMERIC;
|
|
||||||
selectionArgs = new String[] { numeric };
|
|
||||||
} else {
|
|
||||||
selection = SELECTION_NUMERIC + " AND " + SELECTION_APN;
|
|
||||||
selectionArgs = new String[] { numeric, apnName };
|
|
||||||
}
|
|
||||||
Cursor cursor;
|
|
||||||
try {
|
|
||||||
cursor = db.query(ApnDatabase.APN_TABLE, APN_PROJECTION_LOCAL, selection, selectionArgs,
|
|
||||||
null/*groupBy*/, null/*having*/, ORDER_BY, null/*limit*/);
|
|
||||||
} catch (final SQLiteException e) {
|
|
||||||
LogUtil.w(LogUtil.BUGLE_TAG, "Local APN table does not exist. Try rebuilding.", e);
|
|
||||||
ApnDatabase.forceBuildAndLoadApnTables();
|
|
||||||
cursor = db.query(ApnDatabase.APN_TABLE, APN_PROJECTION_LOCAL, selection, selectionArgs,
|
|
||||||
null/*groupBy*/, null/*having*/, ORDER_BY, null/*limit*/);
|
|
||||||
}
|
|
||||||
if (cursor == null || cursor.getCount() < 1) {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
LogUtil.w(LogUtil.BUGLE_TAG, "Query local APNs with apn " + apnName
|
|
||||||
+ " returned empty");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String trimWithNullCheck(final String value) {
|
private static String trimWithNullCheck(final String value) {
|
||||||
return value != null ? value.trim() : null;
|
return value != null ? value.trim() : null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user