Initial checkin of AOSP Messaging app.
b/23110861 Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
This commit is contained in:
646
src/com/android/messaging/sms/BugleApnSettingsLoader.java
Normal file
646
src/com/android/messaging/sms/BugleApnSettingsLoader.java
Normal file
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
package com.android.messaging.sms;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.net.Uri;
|
||||
import android.provider.Telephony;
|
||||
import android.support.v7.mms.ApnSettingsLoader;
|
||||
import android.support.v7.mms.MmsManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.messaging.datamodel.data.ParticipantData;
|
||||
import com.android.messaging.mmslib.SqliteWrapper;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.BugleGservicesKeys;
|
||||
import com.android.messaging.util.LogUtil;
|
||||
import com.android.messaging.util.OsUtil;
|
||||
import com.android.messaging.util.PhoneUtils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* APN loader for default SMS SIM
|
||||
*
|
||||
* This loader tries to load APNs from 3 sources in order:
|
||||
* 1. Gservices setting
|
||||
* 2. System APN table
|
||||
* 3. Local APN table
|
||||
*/
|
||||
public class BugleApnSettingsLoader implements ApnSettingsLoader {
|
||||
/**
|
||||
* The base implementation of an APN
|
||||
*/
|
||||
private static class BaseApn implements Apn {
|
||||
/**
|
||||
* Create a base APN from parameters
|
||||
*
|
||||
* @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 instance of base APN, or null if any of the parameter is invalid
|
||||
*/
|
||||
public static BaseApn from(final String typesIn, final String mmscIn, final String proxyIn,
|
||||
final String portIn) {
|
||||
if (!isValidApnType(trimWithNullCheck(typesIn), APN_TYPE_MMS)) {
|
||||
return null;
|
||||
}
|
||||
String mmsc = trimWithNullCheck(mmscIn);
|
||||
if (TextUtils.isEmpty(mmsc)) {
|
||||
return null;
|
||||
}
|
||||
mmsc = trimV4AddrZeros(mmsc);
|
||||
try {
|
||||
new URI(mmsc);
|
||||
} catch (final URISyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
String mmsProxy = trimWithNullCheck(proxyIn);
|
||||
int mmsProxyPort = 80;
|
||||
if (!TextUtils.isEmpty(mmsProxy)) {
|
||||
mmsProxy = trimV4AddrZeros(mmsProxy);
|
||||
final String portString = trimWithNullCheck(portIn);
|
||||
if (portString != null) {
|
||||
try {
|
||||
mmsProxyPort = Integer.parseInt(portString);
|
||||
} catch (final NumberFormatException e) {
|
||||
// Ignore, just use 80 to try
|
||||
}
|
||||
}
|
||||
}
|
||||
return new BaseApn(mmsc, mmsProxy, mmsProxyPort);
|
||||
}
|
||||
|
||||
private final String mMmsc;
|
||||
private final String mMmsProxy;
|
||||
private final int mMmsProxyPort;
|
||||
|
||||
public BaseApn(final String mmsc, final String proxy, final int port) {
|
||||
mMmsc = mmsc;
|
||||
mMmsProxy = proxy;
|
||||
mMmsProxyPort = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMmsc() {
|
||||
return mMmsc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMmsProxy() {
|
||||
return mMmsProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMmsProxyPort() {
|
||||
return mMmsProxyPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSuccess() {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* APN_TYPE_ALL is a special type to indicate that this APN entry can
|
||||
* service all data connections.
|
||||
*/
|
||||
public static final String APN_TYPE_ALL = "*";
|
||||
/** APN type for MMS traffic */
|
||||
public static final String APN_TYPE_MMS = "mms";
|
||||
|
||||
private static final String[] APN_PROJECTION_SYSTEM = {
|
||||
Telephony.Carriers.TYPE,
|
||||
Telephony.Carriers.MMSC,
|
||||
Telephony.Carriers.MMSPROXY,
|
||||
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_MMSC = 1;
|
||||
private static final int COLUMN_MMSPROXY = 2;
|
||||
private static final int COLUMN_MMSPORT = 3;
|
||||
private static final int COLUMN_CURRENT = 4;
|
||||
private static final int COLUMN_ID = 5;
|
||||
|
||||
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_NUMERIC = Telephony.Carriers.NUMERIC + "=?";
|
||||
private static final String ORDER_BY = Telephony.Carriers.CURRENT + " DESC";
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
// Cached APNs for subIds
|
||||
private final SparseArray<List<ApnSettingsLoader.Apn>> mApnsCache;
|
||||
|
||||
public BugleApnSettingsLoader(final Context context) {
|
||||
mContext = context;
|
||||
mApnsCache = new SparseArray<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApnSettingsLoader.Apn> get(final String apnName) {
|
||||
final int subId = PhoneUtils.getDefault().getEffectiveSubId(
|
||||
ParticipantData.DEFAULT_SELF_SUB_ID);
|
||||
List<ApnSettingsLoader.Apn> apns;
|
||||
boolean didLoad = false;
|
||||
synchronized (this) {
|
||||
apns = mApnsCache.get(subId);
|
||||
if (apns == null) {
|
||||
apns = new ArrayList<>();
|
||||
mApnsCache.put(subId, apns);
|
||||
loadLocked(subId, apnName, apns);
|
||||
didLoad = true;
|
||||
}
|
||||
}
|
||||
if (didLoad) {
|
||||
LogUtil.i(LogUtil.BUGLE_TAG, "Loaded " + apns.size() + " APNs");
|
||||
}
|
||||
return apns;
|
||||
}
|
||||
|
||||
private void loadLocked(final int subId, final String apnName, final List<Apn> apns) {
|
||||
// Try Gservices first
|
||||
loadFromGservices(apns);
|
||||
if (apns.size() > 0) {
|
||||
return;
|
||||
}
|
||||
// Try system APN table
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load from Gservices if APN setting is set in Gservices
|
||||
*
|
||||
* @param apns the list used to return results
|
||||
*/
|
||||
private void loadFromGservices(final List<Apn> apns) {
|
||||
final BugleGservices gservices = BugleGservices.get();
|
||||
final String mmsc = gservices.getString(BugleGservicesKeys.MMS_MMSC, null);
|
||||
if (TextUtils.isEmpty(mmsc)) {
|
||||
return;
|
||||
}
|
||||
LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from gservices");
|
||||
final String proxy = gservices.getString(BugleGservicesKeys.MMS_PROXY_ADDRESS, null);
|
||||
final int port = gservices.getInt(BugleGservicesKeys.MMS_PROXY_PORT, -1);
|
||||
final Apn apn = BaseApn.from("mms", mmsc, proxy, Integer.toString(port));
|
||||
if (apn != null) {
|
||||
apns.add(apn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load matching APNs from telephony provider.
|
||||
* We try different combinations of the query to work around some platform quirks.
|
||||
*
|
||||
* @param subId the SIM subId
|
||||
* @param apnName the APN name to match
|
||||
* @param apns the list used to return results
|
||||
*/
|
||||
private void loadFromSystem(final int subId, final String apnName, final List<Apn> apns) {
|
||||
Uri uri;
|
||||
if (OsUtil.isAtLeastL_MR1() && subId != MmsManager.DEFAULT_SUB_ID) {
|
||||
uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId);
|
||||
} else {
|
||||
uri = Telephony.Carriers.CONTENT_URI;
|
||||
}
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
for (; ; ) {
|
||||
// Try different combinations of queries. Some would work on some platforms.
|
||||
// So we query each combination until we find one returns non-empty result.
|
||||
cursor = querySystem(uri, true/*checkCurrent*/, apnName);
|
||||
if (cursor != null) {
|
||||
break;
|
||||
}
|
||||
cursor = querySystem(uri, false/*checkCurrent*/, apnName);
|
||||
if (cursor != null) {
|
||||
break;
|
||||
}
|
||||
cursor = querySystem(uri, true/*checkCurrent*/, null/*apnName*/);
|
||||
if (cursor != null) {
|
||||
break;
|
||||
}
|
||||
cursor = querySystem(uri, false/*checkCurrent*/, null/*apnName*/);
|
||||
break;
|
||||
}
|
||||
} catch (final SecurityException e) {
|
||||
// Can't access platform APN table, return directly
|
||||
return;
|
||||
}
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (cursor.moveToFirst()) {
|
||||
final ApnSettingsLoader.Apn apn = BaseApn.from(
|
||||
cursor.getString(COLUMN_TYPE),
|
||||
cursor.getString(COLUMN_MMSC),
|
||||
cursor.getString(COLUMN_MMSPROXY),
|
||||
cursor.getString(COLUMN_MMSPORT));
|
||||
if (apn != null) {
|
||||
apns.add(apn);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query system APN table
|
||||
*
|
||||
* @param uri The APN query URL to use
|
||||
* @param checkCurrent If add "CURRENT IS NOT NULL" condition
|
||||
* @param apnName The optional APN name for query condition
|
||||
* @return A cursor of the query result. If a cursor is returned as not null, it is
|
||||
* guaranteed to contain at least one row.
|
||||
*/
|
||||
private Cursor querySystem(final Uri uri, final boolean checkCurrent, String apnName) {
|
||||
LogUtil.i(LogUtil.BUGLE_TAG, "Loading APNs from system, "
|
||||
+ "checkCurrent=" + checkCurrent + " apnName=" + apnName);
|
||||
final StringBuilder selectionBuilder = new StringBuilder();
|
||||
String[] selectionArgs = null;
|
||||
if (checkCurrent) {
|
||||
selectionBuilder.append(SELECTION_CURRENT);
|
||||
}
|
||||
apnName = trimWithNullCheck(apnName);
|
||||
if (!TextUtils.isEmpty(apnName)) {
|
||||
if (selectionBuilder.length() > 0) {
|
||||
selectionBuilder.append(" AND ");
|
||||
}
|
||||
selectionBuilder.append(SELECTION_APN);
|
||||
selectionArgs = new String[] { apnName };
|
||||
}
|
||||
try {
|
||||
final Cursor cursor = SqliteWrapper.query(
|
||||
mContext,
|
||||
mContext.getContentResolver(),
|
||||
uri,
|
||||
APN_PROJECTION_SYSTEM,
|
||||
selectionBuilder.toString(),
|
||||
selectionArgs,
|
||||
null/*sortOrder*/);
|
||||
if (cursor == null || cursor.getCount() < 1) {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
LogUtil.w(LogUtil.BUGLE_TAG, "Query " + uri + " with apn " + apnName + " and "
|
||||
+ (checkCurrent ? "checking CURRENT" : "not checking CURRENT")
|
||||
+ " returned empty");
|
||||
return null;
|
||||
}
|
||||
return cursor;
|
||||
} catch (final SQLiteException e) {
|
||||
LogUtil.w(LogUtil.BUGLE_TAG, "APN table query exception: " + e);
|
||||
} catch (final SecurityException e) {
|
||||
LogUtil.w(LogUtil.BUGLE_TAG, "Platform restricts APN table access: " + e);
|
||||
throw e;
|
||||
}
|
||||
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 = null;
|
||||
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 = null;
|
||||
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) {
|
||||
return value != null ? value.trim() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim leading zeros from IPv4 address strings
|
||||
* Our base libraries will interpret that as octel..
|
||||
* Must leave non v4 addresses and host names alone.
|
||||
* For example, 192.168.000.010 -> 192.168.0.10
|
||||
*
|
||||
* @param addr a string representing an ip addr
|
||||
* @return a string propertly trimmed
|
||||
*/
|
||||
private static String trimV4AddrZeros(final String addr) {
|
||||
if (addr == null) {
|
||||
return null;
|
||||
}
|
||||
final String[] octets = addr.split("\\.");
|
||||
if (octets.length != 4) {
|
||||
return addr;
|
||||
}
|
||||
final StringBuilder builder = new StringBuilder(16);
|
||||
String result = null;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
try {
|
||||
if (octets[i].length() > 3) {
|
||||
return addr;
|
||||
}
|
||||
builder.append(Integer.parseInt(octets[i]));
|
||||
} catch (final NumberFormatException e) {
|
||||
return addr;
|
||||
}
|
||||
if (i < 3) {
|
||||
builder.append('.');
|
||||
}
|
||||
}
|
||||
result = builder.toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the APN contains the APN type we want
|
||||
*
|
||||
* @param types The string encodes a list of supported types
|
||||
* @param requestType The type we want
|
||||
* @return true if the input types string contains the requestType
|
||||
*/
|
||||
public static boolean isValidApnType(final String types, final String requestType) {
|
||||
// If APN type is unspecified, assume APN_TYPE_ALL.
|
||||
if (TextUtils.isEmpty(types)) {
|
||||
return true;
|
||||
}
|
||||
for (final String t : types.split(",")) {
|
||||
if (t.equals(requestType) || t.equals(APN_TYPE_ALL)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of first APN to try
|
||||
*/
|
||||
public static String getFirstTryApn(final SQLiteDatabase database, final String mccMnc) {
|
||||
String key = null;
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = queryLocalDatabase(database, mccMnc, null/*apnName*/);
|
||||
if (cursor.moveToFirst()) {
|
||||
key = cursor.getString(ApnDatabase.COLUMN_ID);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
// Nothing to do
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user