Merge "Fix apn restore issue for multi-sim"
am: 6a39c8ba87
Change-Id: Icfda508bc792f9af8f9df35c17f13db6bb3c7f7f
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 78ccd50..c33f485 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -27,6 +27,7 @@
import static android.provider.Telephony.Carriers.CARRIER_ENABLED;
import static android.provider.Telephony.Carriers.CONTENT_URI;
import static android.provider.Telephony.Carriers.CURRENT;
+import static android.provider.Telephony.Carriers.DEFAULT_SORT_ORDER;
import static android.provider.Telephony.Carriers.EDITED;
import static android.provider.Telephony.Carriers.MAX_CONNS;
import static android.provider.Telephony.Carriers.MAX_CONNS_TIME;
@@ -104,7 +105,11 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IApnSourceService;
+import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.dataconnection.ApnSetting;
+import com.android.internal.telephony.uicc.IccRecords;
+import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -211,7 +216,8 @@
private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>();
private static final Map<String, String> CARRIERS_UNIQUE_FIELDS_DEFAULTS = new HashMap();
- private static Boolean s_apnSourceServiceExists;
+ @VisibleForTesting
+ static Boolean s_apnSourceServiceExists;
protected final Object mLock = new Object();
@GuardedBy("mLock")
@@ -3095,9 +3101,19 @@
private void restoreDefaultAPN(int subId) {
SQLiteDatabase db = getWritableDatabase();
+ TelephonyManager telephonyManager =
+ (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ String where = null;
+ if (telephonyManager.getPhoneCount() > 1) {
+ where = getWhereClauseForRestoreDefaultApn(db, subId);
+ }
+ if (TextUtils.isEmpty(where)) {
+ where = IS_NOT_OWNED_BY_DPC;
+ }
+ log("restoreDefaultAPN: where: " + where);
try {
- db.delete(CARRIERS_TABLE, IS_NOT_OWNED_BY_DPC, null);
+ db.delete(CARRIERS_TABLE, where, null);
} catch (SQLException e) {
loge("got exception when deleting to restore: " + e);
}
@@ -3123,6 +3139,54 @@
}
}
+ private String getWhereClauseForRestoreDefaultApn(SQLiteDatabase db, int subId) {
+ IccRecords iccRecords = getIccRecords(subId);
+ if (iccRecords == null) {
+ return null;
+ }
+ TelephonyManager telephonyManager =
+ (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ String simOperator = telephonyManager.getSimOperator(subId);
+ Cursor cursor = db.query(CARRIERS_TABLE, new String[] {MVNO_TYPE, MVNO_MATCH_DATA},
+ NUMERIC + "='" + simOperator + "'", null, null, null, DEFAULT_SORT_ORDER);
+ String where = null;
+
+ if (cursor != null) {
+ cursor.moveToFirst();
+ while (!cursor.isAfterLast()) {
+ String mvnoType = cursor.getString(0 /* MVNO_TYPE index */);
+ String mvnoMatchData = cursor.getString(1 /* MVNO_MATCH_DATA index */);
+ if (!TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)
+ && ApnSetting.mvnoMatches(iccRecords, mvnoType, mvnoMatchData)) {
+ where = NUMERIC + "='" + simOperator + "'"
+ + " AND " + MVNO_TYPE + "='" + mvnoType + "'"
+ + " AND " + MVNO_MATCH_DATA + "='" + mvnoMatchData + "'"
+ + " AND " + IS_NOT_OWNED_BY_DPC;
+ break;
+ }
+ cursor.moveToNext();
+ }
+ cursor.close();
+
+ if (TextUtils.isEmpty(where)) {
+ where = NUMERIC + "='" + simOperator + "'"
+ + " AND (" + MVNO_TYPE + "='' OR " + MVNO_MATCH_DATA + "='')"
+ + " AND " + IS_NOT_OWNED_BY_DPC;
+ }
+ }
+ return where;
+ }
+
+ @VisibleForTesting
+ IccRecords getIccRecords(int subId) {
+ TelephonyManager telephonyManager =
+ TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+ int family = telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ?
+ UiccController.APP_FAM_3GPP : UiccController.APP_FAM_3GPP2;
+ return UiccController.getInstance().getIccRecords(
+ SubscriptionManager.getPhoneId(subId), family);
+ }
+
private synchronized void updateApnDb() {
if (apnSourceServiceExists(getContext())) {
loge("called updateApnDb when apn source service exists");
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 14e2491..5e10917 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -90,6 +90,10 @@
private static final Uri CONTENT_URI_WITH_SUBID = Uri.parse(
"content://telephony/carriers/subId/" + TEST_SUBID);
+ // Used to test the "restore to default"
+ private static final Uri URL_RESTOREAPN_USING_SUBID = Uri.parse(
+ "content://telephony/carriers/restore/subId/" + TEST_SUBID);
+
// Constants for DPC related tests.
private static final Uri URI_DPC = Uri.parse("content://telephony/carriers/dpc");
private static final Uri URI_TELEPHONY = Carriers.CONTENT_URI;
@@ -971,4 +975,94 @@
Cursor cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
assertEquals(0, cur.getCount());
}
+
+ /**
+ * Test URL_RESTOREAPN_USING_SUBID works correctly.
+ */
+ @Test
+ @SmallTest
+ public void testRestoreDefaultApn() {
+ // setup for multi-SIM
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(2).when(telephonyManager).getPhoneCount();
+
+ // create APN to be deleted (including MVNO values)
+ ContentValues targetValues = new ContentValues();
+ targetValues.put(Carriers.APN, "apnName");
+ targetValues.put(Carriers.NAME, "name");
+ targetValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ targetValues.put(Carriers.MVNO_TYPE, "spn");
+ targetValues.put(Carriers.MVNO_MATCH_DATA, TelephonyProviderTestable.TEST_SPN);
+ // create other operator APN (sama MCCMNC)
+ ContentValues otherValues = new ContentValues();
+ final String otherApn = "otherApnName";
+ final String otherName = "otherName";
+ final String otherMvnoTyp = "spn";
+ final String otherMvnoMatchData = "testOtherOperator";
+ otherValues.put(Carriers.APN, otherApn);
+ otherValues.put(Carriers.NAME, otherName);
+ otherValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+ otherValues.put(Carriers.MVNO_TYPE, otherMvnoTyp);
+ otherValues.put(Carriers.MVNO_MATCH_DATA, otherMvnoMatchData);
+
+ // insert APNs
+ Log.d(TAG, "testRestoreDefaultApn: Bulk inserting contentValues=" + targetValues + ", "
+ + otherValues);
+ ContentValues[] values = new ContentValues[]{ targetValues, otherValues };
+ mContentResolver.bulkInsert(Carriers.CONTENT_URI, values);
+
+ // restore to default
+ mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
+
+ // get values in table
+ final String[] testProjection =
+ {
+ Carriers.APN,
+ Carriers.NAME,
+ Carriers.MVNO_TYPE,
+ Carriers.MVNO_MATCH_DATA,
+ };
+ // verify that deleted result match results of query
+ Cursor cursor = mContentResolver.query(
+ Carriers.CONTENT_URI, testProjection, null, null, null);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertEquals(otherApn, cursor.getString(0));
+ assertEquals(otherName, cursor.getString(1));
+ assertEquals(otherMvnoTyp, cursor.getString(2));
+ assertEquals(otherMvnoMatchData, cursor.getString(3));
+
+ // create APN to be deleted (not include MVNO values)
+ ContentValues targetValues2 = new ContentValues();
+ targetValues2.put(Carriers.APN, "apnName");
+ targetValues2.put(Carriers.NAME, "name");
+ targetValues2.put(Carriers.NUMERIC, TEST_OPERATOR);
+
+ // insert APN
+ mContentResolver.insert(Carriers.CONTENT_URI, targetValues2);
+
+ // restore to default
+ mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
+
+ // verify that deleted result match results of query
+ cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection, null, null, null);
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ assertEquals(otherApn, cursor.getString(0));
+ assertEquals(otherName, cursor.getString(1));
+ assertEquals(otherMvnoTyp, cursor.getString(2));
+ assertEquals(otherMvnoMatchData, cursor.getString(3));
+
+ // setup for single-SIM
+ doReturn(1).when(telephonyManager).getPhoneCount();
+
+ // restore to default
+ mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
+
+ // verify that deleted values are gone
+ cursor = mContentResolver.query(
+ Carriers.CONTENT_URI, testProjection, null, null, null);
+ assertEquals(0, cursor.getCount());
+ }
}
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java b/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
index 2d3acd7..0a12831 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
@@ -26,8 +26,12 @@
import java.util.List;
import java.util.ArrayList;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.uicc.IccRecords;
import com.android.providers.telephony.TelephonyProvider;
import static android.provider.Telephony.Carriers.*;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
/**
* A subclass of TelephonyProvider used for testing on an in-memory database
@@ -35,6 +39,9 @@
public class TelephonyProviderTestable extends TelephonyProvider {
private static final String TAG = "TelephonyProviderTestable";
+ @VisibleForTesting
+ public static final String TEST_SPN = "testspn";
+
private InMemoryTelephonyProviderDbHelper mDbHelper;
private MockInjector mMockInjector;
@@ -51,6 +58,7 @@
public boolean onCreate() {
Log.d(TAG, "onCreate called: mDbHelper = new InMemoryTelephonyProviderDbHelper()");
mDbHelper = new InMemoryTelephonyProviderDbHelper();
+ s_apnSourceServiceExists = false;
return true;
}
@@ -82,6 +90,14 @@
return false;
}
+ @Override
+ IccRecords getIccRecords(int subId) {
+ Log.d(TAG, "getIccRecords called");
+ IccRecords iccRecords = mock(IccRecords.class);
+ doReturn(TEST_SPN).when(iccRecords).getServiceProviderName();
+ return iccRecords;
+ }
+
public void fakeCallingUid(int uid) {
mMockInjector.fakeCallingUid(uid);
}