Merge "Revert "Revert "Update SIM info table to have strings for mcc mnc"""
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index d0043e2..df80276 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -95,6 +95,7 @@
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.provider.Telephony;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -128,6 +129,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.zip.CRC32;
import java.util.Set;
@@ -139,7 +141,7 @@
private static final boolean DBG = true;
private static final boolean VDBG = false; // STOPSHIP if true
- private static final int DATABASE_VERSION = 26 << 16;
+ private static final int DATABASE_VERSION = 27 << 16;
private static final int URL_UNKNOWN = 0;
private static final int URL_TELEPHONY = 1;
private static final int URL_CURRENT = 2;
@@ -345,6 +347,8 @@
+ " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
+ SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
+ SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
+ + SubscriptionManager.MCC_STRING + " TEXT,"
+ + SubscriptionManager.MNC_STRING + " TEXT,"
+ SubscriptionManager.SIM_PROVISIONING_STATUS
+ " INTEGER DEFAULT " + SubscriptionManager.SIM_PROVISIONED + ","
+ SubscriptionManager.IS_EMBEDDED + " INTEGER DEFAULT 0,"
@@ -1071,6 +1075,32 @@
}
oldVersion = 26 << 16 | 6;
}
+
+ if (oldVersion < (27 << 16 | 6)) {
+ // Add the new MCC_STRING and MNC_STRING columns into the subscription table,
+ // and attempt to populate them.
+ try {
+ // Try to update the siminfo table. It might not be there.
+ db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
+ " ADD COLUMN " + SubscriptionManager.MCC_STRING + " TEXT;");
+ db.execSQL("ALTER TABLE " + SIMINFO_TABLE +
+ " ADD COLUMN " + SubscriptionManager.MNC_STRING + " TEXT;");
+ } catch (SQLiteException e) {
+ if (DBG) {
+ log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " +
+ " The table will get created in onOpen.");
+ }
+ }
+ // Migrate the old integer values over to strings
+ String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
+ SubscriptionManager.MCC, SubscriptionManager.MNC};
+ try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) {
+ while (c.moveToNext()) {
+ fillInMccMncStringAtCursor(mContext, db, c);
+ }
+ }
+ oldVersion = 27 << 16 | 6;
+ }
if (DBG) {
log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
}
@@ -3358,12 +3388,60 @@
initDatabaseWithDatabaseHelper(db);
- // Notify listereners of DB change since DB has been updated
+ // Notify listeners of DB change since DB has been updated
getContext().getContentResolver().notifyChange(
CONTENT_URI, null, true, UserHandle.USER_ALL);
}
+ public static void fillInMccMncStringAtCursor(Context context, SQLiteDatabase db, Cursor c) {
+ int mcc, mnc;
+ String subId;
+ try {
+ mcc = c.getInt(c.getColumnIndexOrThrow(SubscriptionManager.MCC));
+ mnc = c.getInt(c.getColumnIndexOrThrow(SubscriptionManager.MNC));
+ subId = c.getString(c.getColumnIndexOrThrow(
+ SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Possible database corruption -- some columns not found.");
+ return;
+ }
+
+ String mccString = String.format(Locale.getDefault(), "%03d", mcc);
+ String mncString = getBestStringMnc(context, mccString, mnc);
+ ContentValues cv = new ContentValues(2);
+ cv.put(SubscriptionManager.MCC_STRING, mccString);
+ cv.put(SubscriptionManager.MNC_STRING, mncString);
+ db.update(SIMINFO_TABLE, cv,
+ SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?",
+ new String[]{subId});
+ }
+
+ /*
+ * Find the best string-form mnc by looking up possibilities in the carrier id db.
+ * Default to the three-digit version if neither/both are valid.
+ */
+ private static String getBestStringMnc(Context context, String mcc, int mnc) {
+ if (mnc >= 100 && mnc <= 999) {
+ return String.valueOf(mnc);
+ }
+ String twoDigitMnc = String.format(Locale.getDefault(), "%02d", mnc);
+ String threeDigitMnc = "0" + twoDigitMnc;
+
+ try (
+ Cursor twoDigitMncCursor = context.getContentResolver().query(
+ Telephony.CarrierId.All.CONTENT_URI,
+ /* projection */ null,
+ /* selection */ Telephony.CarrierId.All.MCCMNC + "=?",
+ /* selectionArgs */ new String[]{mcc + twoDigitMnc}, null)
+ ) {
+ if (twoDigitMncCursor.getCount() > 0) {
+ return twoDigitMnc;
+ }
+ return threeDigitMnc;
+ }
+ }
+
/**
* Sync the bearer bitmask and network type bitmask when inserting and updating.
* Since bearerBitmask is deprecating, map the networkTypeBitmask to bearerBitmask if
diff --git a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
index 4adcf43..44d9ec9 100644
--- a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
+++ b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
@@ -104,14 +104,10 @@
private class MockContextWithProvider extends MockContext {
private final MockContentResolver mResolver;
- public MockContextWithProvider(CarrierIdProvider carrierIdProvider) {
+ public MockContextWithProvider(CarrierIdProviderTestable carrierIdProvider) {
mResolver = new FakeContentResolver();
- ProviderInfo providerInfo = new ProviderInfo();
- providerInfo.authority = CarrierIdProvider.AUTHORITY;
-
- // Add context to given carrierIdProvider
- carrierIdProvider.attachInfoForTesting(this, providerInfo);
+ carrierIdProvider.initializeForTesting(this);
Log.d(TAG, "MockContextWithProvider: carrierIdProvider.getContext(): "
+ carrierIdProvider.getContext());
diff --git a/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java b/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java
index 8468801..9ecd93a 100644
--- a/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java
+++ b/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java
@@ -15,6 +15,8 @@
*/
package com.android.providers.telephony;
+import android.content.Context;
+import android.content.pm.ProviderInfo;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
@@ -51,6 +53,14 @@
return mDbHelper.getWritableDatabase();
}
+ void initializeForTesting(Context context) {
+ ProviderInfo providerInfo = new ProviderInfo();
+ providerInfo.authority = CarrierIdProvider.AUTHORITY;
+
+ // Add context to given carrierIdProvider
+ attachInfoForTesting(context, providerInfo);
+ }
+
/**
* An in memory DB for CarrierIdProviderTestable to use
*/
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index dde9e5c..465b5b1 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -16,59 +16,40 @@
package com.android.providers.telephony;
-import android.annotation.TargetApi;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.Manifest;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
-import android.content.SharedPreferences;
-import android.database.Cursor;
import android.database.ContentObserver;
-import android.database.DatabaseErrorHandler;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
+import android.database.Cursor;
import android.net.Uri;
-import android.os.Build;
-import android.os.FileUtils;
import android.os.Process;
+import android.provider.Telephony;
import android.provider.Telephony.Carriers;
import android.support.test.InstrumentationRegistry;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
-import android.test.mock.MockContentProvider;
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 com.android.providers.telephony.TelephonyProvider;
-
import junit.framework.TestCase;
-import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Map;
-import java.util.Set;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
/**
@@ -126,6 +107,10 @@
private final MockContentResolver mResolver;
private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
+ private final List<String> GRANTED_PERMISSIONS = Arrays.asList(
+ Manifest.permission.MODIFY_PHONE_STATE, Manifest.permission.WRITE_APN_SETTINGS,
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+
public MockContextWithProvider(TelephonyProvider telephonyProvider) {
mResolver = new MockContentResolver() {
@Override
@@ -186,7 +171,7 @@
// Gives permission to write to the APN table within the MockContext
@Override
public int checkCallingOrSelfPermission(String permission) {
- if (TextUtils.equals(permission, "android.permission.WRITE_APN_SETTINGS")) {
+ if (GRANTED_PERMISSIONS.contains(permission)) {
Log.d(TAG, "checkCallingOrSelfPermission: permission=" + permission
+ ", returning PackageManager.PERMISSION_GRANTED");
return PackageManager.PERMISSION_GRANTED;
@@ -287,6 +272,64 @@
}
/**
+ * Test migrating int-based MCC/MNCs over to Strings in the sim info table
+ */
+ @Test
+ @SmallTest
+ public void testMccMncMigration() {
+ CarrierIdProviderTestable carrierIdProvider = new CarrierIdProviderTestable();
+ carrierIdProvider.initializeForTesting(mContext);
+ mContentResolver.addProvider(Telephony.CarrierId.All.CONTENT_URI.getAuthority(),
+ carrierIdProvider);
+ // Insert a few values into the carrier ID db
+ List<String> mccMncs = Arrays.asList("99910", "999110", "999060", "99905");
+ ContentValues[] carrierIdMccMncs = mccMncs.stream()
+ .map((mccMnc) -> {
+ ContentValues cv = new ContentValues(1);
+ cv.put(Telephony.CarrierId.All.MCCMNC, mccMnc);
+ return cv;
+ }).toArray(ContentValues[]::new);
+ mContentResolver.bulkInsert(Telephony.CarrierId.All.CONTENT_URI, carrierIdMccMncs);
+
+ // Populate the sim info db with int-format entries
+ ContentValues[] existingSimInfoEntries = IntStream.range(0, mccMncs.size())
+ .mapToObj((idx) -> {
+ int mcc = Integer.valueOf(mccMncs.get(idx).substring(0, 3));
+ int mnc = Integer.valueOf(mccMncs.get(idx).substring(3));
+ ContentValues cv = new ContentValues(4);
+ cv.put(SubscriptionManager.MCC, mcc);
+ cv.put(SubscriptionManager.MNC, mnc);
+ cv.put(SubscriptionManager.ICC_ID, String.valueOf(idx));
+ cv.put(SubscriptionManager.CARD_ID, String.valueOf(idx));
+ return cv;
+ }).toArray(ContentValues[]::new);
+
+ mContentResolver.bulkInsert(SubscriptionManager.CONTENT_URI, existingSimInfoEntries);
+
+ // Run the upgrade helper on all the sim info entries.
+ String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
+ SubscriptionManager.MCC, SubscriptionManager.MNC,
+ SubscriptionManager.MCC_STRING, SubscriptionManager.MNC_STRING};
+ try (Cursor c = mContentResolver.query(SubscriptionManager.CONTENT_URI, proj,
+ null, null, null)) {
+ while (c.moveToNext()) {
+ TelephonyProvider.fillInMccMncStringAtCursor(mContext,
+ mTelephonyProviderTestable.getWritableDatabase(), c);
+ }
+ }
+
+ // Loop through and make sure that everything got filled in correctly.
+ try (Cursor c = mContentResolver.query(SubscriptionManager.CONTENT_URI, proj,
+ null, null, null)) {
+ while (c.moveToNext()) {
+ String mcc = c.getString(c.getColumnIndexOrThrow(SubscriptionManager.MCC_STRING));
+ String mnc = c.getString(c.getColumnIndexOrThrow(SubscriptionManager.MNC_STRING));
+ assertTrue(mccMncs.contains(mcc + mnc));
+ }
+ }
+ }
+
+ /**
* Test updating values in carriers table. Verify that when update hits a conflict using URL_ID
* we merge the rows.
*/