Support carrier id in SIM_APN_URI
In order to support backward compatibility, SIM_APN_URI only queries
based on MNO or MVNO APN in Android Q. To support the carrier ID in
Android R, but the APN added by the user only has MCC/MNC(SIM_APN_URI
should return the APN added by user and OEM). Therefore, the SIM_APN_URI
will query based on the MNO or MVNO APN and then append the APN based
on the carrier ID.
Bug: 143931670
Test: atest TelephonyProviderTests
Change-Id: Ia8288568c2dca12bd4e8cef729d35c732a230f67
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 8e77e18..d669e05 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -70,6 +70,7 @@
import static android.provider.Telephony.Carriers.WAIT_TIME_RETRY;
import static android.provider.Telephony.Carriers._ID;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -3026,33 +3027,34 @@
}
/**
- * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} to support backward
- * compatibility but will move to carrier id in the future.
+ * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} and {Carrier_ID}.
*
* There has three steps:
- * 1. Query the APN based on { MCC, MNC, MVNO }.
- * 2. If can't find the current APN, then query the parent APN. Query based on { MCC, MNC }.
- * 3. else return empty cursor
- *
+ * 1. Query the APN based on { MCC, MNC, MVNO } and if has results jump to step 3, else jump to
+ * step 2.
+ * 2. Fallback to query the parent APN that query based on { MCC, MNC }.
+ * 3. Append the result with the APN that query based on { Carrier_ID }
*/
private Cursor getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn,
String selection, String[] selectionArgs, String sort, int subId) {
Cursor ret;
- final TelephonyManager tm = ((TelephonyManager)
- getContext().getSystemService(Context.TELEPHONY_SERVICE))
+ final TelephonyManager tm = ((TelephonyManager) getContext()
+ .getSystemService(Context.TELEPHONY_SERVICE))
.createForSubscriptionId(subId);
SQLiteDatabase db = getReadableDatabase();
String mccmnc = tm.getSimOperator();
+ int carrierId = tm.getSimCarrierId();
qb.appendWhereStandalone(IS_NOT_USER_DELETED + " and " +
IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " +
IS_NOT_CARRIER_DELETED + " and " +
IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML);
- // For query db one time, append step 1 and step 2 condition in one selection and
- // separate results after the query is completed. Because IMSI has special match rule,
- // so just query the MCC / MNC and filter the MVNO by ourselves
- qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' ");
+ // For query db one time, append all conditions in one selection and separate results after
+ // the query is completed. IMSI has special match rule, so just query the MCC / MNC and
+ // filter the MVNO by ourselves
+ qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' OR " +
+ CARRIER_ID + " = '" + carrierId + "'");
ret = qb.query(db, null, selection, selectionArgs, null, null, sort);
if (ret == null) {
@@ -3062,13 +3064,15 @@
if (DBG) log("match current APN size: " + ret.getCount());
- String[] coulmnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
- MatrixCursor currentCursor = new MatrixCursor(coulmnNames);
- MatrixCursor parentCursor = new MatrixCursor(coulmnNames);
+ String[] columnNames = projectionIn != null ? projectionIn : ret.getColumnNames();
+ MatrixCursor currentCursor = new MatrixCursor(columnNames);
+ MatrixCursor parentCursor = new MatrixCursor(columnNames);
+ MatrixCursor carrierIdCursor = new MatrixCursor(columnNames);
int numericIndex = ret.getColumnIndex(NUMERIC);
int mvnoIndex = ret.getColumnIndex(MVNO_TYPE);
int mvnoDataIndex = ret.getColumnIndex(MVNO_MATCH_DATA);
+ int carrierIdIndex = ret.getColumnIndex(CARRIER_ID);
IccRecords iccRecords = UiccController.getInstance().getIccRecords(
SubscriptionManager.getPhoneId(subId), UiccController.APP_FAM_3GPP);
@@ -3080,7 +3084,7 @@
//Separate the result into MatrixCursor
while (ret.moveToNext()) {
List<String> data = new ArrayList<>();
- for (String column : coulmnNames) {
+ for (String column : columnNames) {
data.add(ret.getString(ret.getColumnIndex(column)));
}
@@ -3088,25 +3092,60 @@
ApnSettingUtils.mvnoMatches(iccRecords,
getMvnoTypeIntFromString(ret.getString(mvnoIndex)),
ret.getString(mvnoDataIndex))) {
- // 1. APN query result based on legacy SIM MCC/MCC and MVNO
+ // 1. The APN that query based on legacy SIM MCC/MCC and MVNO
currentCursor.addRow(data);
- } else if (!TextUtils.isEmpty(ret.getString(numericIndex)) &&
- TextUtils.isEmpty(ret.getString(mvnoIndex))) {
- // 2. APN query result based on SIM MCC/MNC
+ } else if (!TextUtils.isEmpty(ret.getString(numericIndex))
+ && TextUtils.isEmpty(ret.getString(mvnoIndex))) {
+ // 2. The APN that query based on SIM MCC/MNC
parentCursor.addRow(data);
+ } else if (!TextUtils.isEmpty(ret.getString(carrierIdIndex))
+ && ret.getString(carrierIdIndex).equals(String.valueOf(carrierId))) {
+ // The APN that query based on carrier Id (not include the MVNO or MNO APN)
+ carrierIdCursor.addRow(data);
}
}
ret.close();
+ MatrixCursor result;
if (currentCursor.getCount() > 0) {
if (DBG) log("match MVNO APN: " + currentCursor.getCount());
- return currentCursor;
+ result = currentCursor;
} else if (parentCursor.getCount() > 0) {
if (DBG) log("match MNO APN: " + parentCursor.getCount());
- return parentCursor;
+ result = parentCursor;
} else {
- if (DBG) log("APN no match");
- return new MatrixCursor(coulmnNames);
+ if (DBG) log("can't find the MVNO and MNO APN");
+ result = new MatrixCursor(columnNames);
+ }
+
+ if (DBG) log("match carrier id APN: " + carrierIdCursor.getCount());
+ appendCursorData(result, carrierIdCursor);
+ return result;
+ }
+
+ private static void appendCursorData(@NonNull MatrixCursor from, @NonNull MatrixCursor to) {
+ while (to.moveToNext()) {
+ List<Object> data = new ArrayList<>();
+ for (String column : to.getColumnNames()) {
+ int index = to.getColumnIndex(column);
+ switch (to.getType(index)) {
+ case Cursor.FIELD_TYPE_NULL:
+ break;
+ case Cursor.FIELD_TYPE_INTEGER:
+ data.add(to.getInt(index));
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ data.add(to.getFloat(index));
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ data.add(to.getBlob(index));
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ data.add(to.getString(index));
+ break;
+ }
+ }
+ from.addRow(data);
}
}
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 47c1dc6..f062943 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -39,6 +39,7 @@
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -93,6 +94,7 @@
private static final String TEST_MCC = "123";
private static final String TEST_MNC = "456";
private static final String TEST_SPN = TelephonyProviderTestable.TEST_SPN;
+ private static final int TEST_CARRIERID = 1;
// Used to test the path for URL_TELEPHONY_USING_SUBID with subid 1
private static final Uri CONTENT_URI_WITH_SUBID = Uri.parse(
@@ -155,6 +157,7 @@
doReturn(mIcRecords).when(mUiccController).getIccRecords(anyInt(), anyInt());
doReturn(TEST_SPN).when(mIcRecords).getServiceProviderName();
doReturn(TEST_SPN).when(mIcRecords).getServiceProviderNameWithBrandOverride();
+ doReturn(TEST_CARRIERID).when(mTelephonyManager).getSimCarrierId();
// Add authority="telephony" to given telephonyProvider
ProviderInfo providerInfo = new ProviderInfo();
@@ -1479,15 +1482,15 @@
@Test
@SmallTest
- public void testSIMAPNLIST_APNMatchTheMCCMNCAndMVNO() {
- // Test on getCurrentAPNList() step 1
+ public void testSIMAPNLIST_MatchTheMVNOAPN() {
+ // Test on getSubscriptionMatchingAPNList() step 1
final String apnName = "apnName";
final String carrierName = "name";
final String numeric = TEST_OPERATOR;
final String mvnoType = "spn";
final String mvnoData = TEST_SPN;
- // Insert the APN and DB only have the MCC/MNC and MVNO APN
+ // Insert the MVNO APN
ContentValues contentValues = new ContentValues();
contentValues.put(Carriers.APN, apnName);
contentValues.put(Carriers.NAME, carrierName);
@@ -1496,6 +1499,13 @@
contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+ // Insert the MNO APN
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, numeric);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
// Query DB
final String[] testProjection =
{
@@ -1507,7 +1517,9 @@
Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
testProjection, null, null, null);
+ // When the DB has MVNO and MNO APN, the query based on SIM_APN_LIST will return MVNO APN
cursor.moveToFirst();
+ assertEquals(cursor.getCount(), 1);
assertEquals(apnName, cursor.getString(0));
assertEquals(carrierName, cursor.getString(1));
assertEquals(numeric, cursor.getString(2));
@@ -1516,13 +1528,13 @@
@Test
@SmallTest
- public void testSIMAPNLIST_APNMatchTheParentMCCMNC() {
- // Test on getCurrentAPNList() step 2
+ public void testSIMAPNLIST_MatchTheMNOAPN() {
+ // Test on getSubscriptionMatchingAPNList() step 2
final String apnName = "apnName";
final String carrierName = "name";
final String numeric = TEST_OPERATOR;
- // Insert the APN and DB only have the MNO APN
+ // Insert the MNO APN
ContentValues contentValues = new ContentValues();
contentValues.put(Carriers.APN, apnName);
contentValues.put(Carriers.NAME, carrierName);
@@ -1544,4 +1556,91 @@
assertEquals(carrierName, cursor.getString(1));
assertEquals(numeric, cursor.getString(2));
}
+
+ @Test
+ @SmallTest
+ public void testSIMAPNLIST_MatchTheCarrierIDANDMNOAPN() {
+ // Test on getSubscriptionMatchingAPNList() will return the {MCCMNC}
+ final String apnName = "apnName";
+ final String carrierName = "name";
+ final int carrierId = TEST_CARRIERID;
+
+ // Add the APN that only have carrier id
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.CARRIER_ID, carrierId);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Add MNO APN that added by user
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ contentValues.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Query DB
+ final String[] testProjection =
+ {
+ Carriers.APN,
+ Carriers.NAME,
+ Carriers.CARRIER_ID,
+ };
+ Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST, testProjection, null, null, null);
+
+ // The query based on SIM_APN_LIST will return MNO APN and the APN that has carrier id
+ assertEquals(cursor.getCount(), 2);
+ }
+
+ @Test
+ @SmallTest
+ public void testSIMAPNLIST_MatchTheCarrierAPNAndMVNOAPN() {
+ final String apnName = "apnName";
+ final String carrierName = "name";
+ final String mvnoType = "spn";
+ final String mvnoData = TEST_SPN;
+ final int carrierId = TEST_CARRIERID;
+
+ // Add the APN that only have carrier id
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.CARRIER_ID, carrierId);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Add MVNO APN that added by user
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ contentValues.put(Carriers.MVNO_TYPE, mvnoType);
+ contentValues.put(Carriers.MVNO_MATCH_DATA, mvnoData);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Add MNO APN that added by user
+ contentValues = new ContentValues();
+ contentValues.put(Carriers.APN, apnName);
+ contentValues.put(Carriers.NAME, carrierName);
+ contentValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+
+ // Query DB
+ final String[] testProjection =
+ {
+ Carriers.APN,
+ Carriers.NAME,
+ Carriers.CARRIER_ID,
+ Carriers.MVNO_TYPE,
+ };
+ Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
+ testProjection, null, null, null);
+
+ // The query based on SIM_APN_LIST will return MVNO APN and the APN that has carrier id
+ assertEquals(cursor.getCount(), 2);
+ while(cursor.moveToNext()) {
+ assertTrue(!TextUtils.isEmpty(cursor.getString(2))
+ || !TextUtils.isEmpty(cursor.getString(3)));
+ }
+ }
}