blob: 58b05ec02b7ceefd8535ca57fa692449063f8116 [file] [log] [blame]
/*
* Copyright (C) 2016 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.providers.telephony;
import static org.mockito.ArgumentMatchers.anyInt;
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 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.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Process;
import android.provider.Telephony;
import android.provider.Telephony.Carriers;
import android.provider.Telephony.SimInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
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;
import junit.framework.TestCase;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
/**
* Tests for testing CRUD operations of TelephonyProvider.
* Uses a MockContentResolver to get permission WRITE_APN_SETTINGS in order to test insert/delete
* Uses TelephonyProviderTestable to set up in-memory database
*
* Build, install and run the tests by running the commands below:
* runtest --path <dir or file>
* runtest --path <dir or file> --test-method <testMethodName>
* e.g.)
* runtest --path tests/src/com/android/providers/telephony/TelephonyProviderTest.java \
* --test-method testInsertCarriers
*/
public class TelephonyProviderTest extends TestCase {
private static final String TAG = "TelephonyProviderTest";
private MockContextWithProvider mContext;
private MockContentResolver mContentResolver;
private TelephonyProviderTestable mTelephonyProviderTestable;
private int notifyChangeCount;
private int notifyChangeRestoreCount;
private int notifyWfcCount;
private int notifyWfcCountWithTestSubId;
private static final String TEST_SUBID = "1";
private static final String TEST_OPERATOR = "123456";
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(
"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);
// Used to test the preferred apn
private static final Uri URL_PREFERAPN_USING_SUBID = Uri.parse(
"content://telephony/carriers/preferapn/subId/" + TEST_SUBID);
private static final Uri URL_WFC_ENABLED_USING_SUBID = Uri.parse(
"content://telephony/siminfo/" + TEST_SUBID);
private static final Uri URL_SIM_APN_LIST = Uri.parse(
"content://telephony/carriers/sim_apn_list");
private static final String COLUMN_APN_ID = "apn_id";
// 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;
private static final Uri URI_FILTERED = Uri.parse("content://telephony/carriers/filtered");
private static final Uri URI_ENFORCE_MANAGED= Uri.parse("content://telephony/carriers/enforce_managed");
private static final String ENFORCED_KEY = "enforced";
/**
* This is used to give the TelephonyProviderTest a mocked context which takes a
* TelephonyProvider and attaches it to the ContentResolver with telephony authority.
* The mocked context also gives WRITE_APN_SETTINGS permissions
*/
private class MockContextWithProvider extends MockContext {
private final MockContentResolver mResolver;
private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
private SubscriptionManager mSubscriptionManager = mock(SubscriptionManager.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,
Boolean isActiveSubscription) {
mResolver = new MockContentResolver() {
@Override
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
int userHandle) {
notifyChangeCount++;
if (URL_RESTOREAPN_USING_SUBID.equals(uri)) {
notifyChangeRestoreCount++;
} else if (SubscriptionManager.WFC_ENABLED_CONTENT_URI.equals(uri)) {
notifyWfcCount++;
} else if (URL_WFC_ENABLED_USING_SUBID.equals(uri)) {
notifyWfcCountWithTestSubId++;
}
}
};
// return test subId 0 for all operators
doReturn(TEST_OPERATOR).when(mTelephonyManager).getSimOperator(anyInt());
doReturn(isActiveSubscription).when(mSubscriptionManager)
.isActiveSubscriptionId(anyInt());
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
doReturn(TEST_OPERATOR).when(mTelephonyManager).getSimOperator();
doReturn(TEST_CARRIERID).when(mTelephonyManager).getSimCarrierId();
// Add authority="telephony" to given telephonyProvider
ProviderInfo providerInfo = new ProviderInfo();
providerInfo.authority = "telephony";
// Add context to given telephonyProvider
telephonyProvider.attachInfoForTesting(this, providerInfo);
Log.d(TAG, "MockContextWithProvider: telephonyProvider.getContext(): "
+ telephonyProvider.getContext());
// Add given telephonyProvider to mResolver with authority="telephony" so that
// mResolver can send queries to mTelephonyProvider
mResolver.addProvider("telephony", telephonyProvider);
Log.d(TAG, "MockContextWithProvider: Add telephonyProvider to mResolver");
}
@Override
public Object getSystemService(String name) {
if (name.equals(Context.TELEPHONY_SERVICE)) {
Log.d(TAG, "getSystemService: returning mock TM");
return mTelephonyManager;
} else if (name.equals(Context.TELEPHONY_SUBSCRIPTION_SERVICE)){
Log.d(TAG, "getSystemService: returning mock SubscriptionManager");
return mSubscriptionManager;
} else {
Log.d(TAG, "getSystemService: returning null");
return null;
}
}
@Override
public String getSystemServiceName(Class<?> serviceClass) {
if (serviceClass.equals(TelephonyManager.class)) {
return Context.TELEPHONY_SERVICE;
} else if (serviceClass.equals(SubscriptionManager.class)) {
return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
} else {
Log.d(TAG, "getSystemServiceName: returning null");
return null;
}
}
@Override
public Resources getResources() {
Log.d(TAG, "getResources: returning null");
return null;
}
@Override
public MockContentResolver getContentResolver() {
return mResolver;
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return InstrumentationRegistry.getContext().getSharedPreferences(name, mode);
}
// Gives permission to write to the APN table within the MockContext
@Override
public int checkCallingOrSelfPermission(String permission) {
if (GRANTED_PERMISSIONS.contains(permission)) {
Log.d(TAG, "checkCallingOrSelfPermission: permission=" + permission
+ ", returning PackageManager.PERMISSION_GRANTED");
return PackageManager.PERMISSION_GRANTED;
} else {
Log.d(TAG, "checkCallingOrSelfPermission: permission=" + permission
+ ", returning PackageManager.PERMISSION_DENIED");
return PackageManager.PERMISSION_DENIED;
}
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
mTelephonyProviderTestable = new TelephonyProviderTestable();
notifyChangeCount = 0;
notifyChangeRestoreCount = 0;
}
private void setUpMockContext(boolean isActiveSubId) {
mContext = new MockContextWithProvider(mTelephonyProviderTestable, isActiveSubId);
mContentResolver = mContext.getContentResolver();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mTelephonyProviderTestable.closeDatabase();
}
/**
* Test bulk inserting, querying;
* Verify that the inserted values match the result of the query.
*/
@Test
@SmallTest
public void testBulkInsertCarriers() {
setUpMockContext(true);
// insert 2 test contentValues
ContentValues contentValues = new ContentValues();
final String insertApn = "exampleApnName";
final String insertName = "exampleName";
final Integer insertCurrent = 1;
final String insertNumeric = TEST_OPERATOR;
contentValues.put(Carriers.APN, insertApn);
contentValues.put(Carriers.NAME, insertName);
contentValues.put(Carriers.CURRENT, insertCurrent);
contentValues.put(Carriers.NUMERIC, insertNumeric);
ContentValues contentValues2 = new ContentValues();
final String insertApn2 = "exampleApnName2";
final String insertName2 = "exampleName2";
final Integer insertCurrent2 = 1;
final String insertNumeric2 = "789123";
contentValues2.put(Carriers.APN, insertApn2);
contentValues2.put(Carriers.NAME, insertName2);
contentValues2.put(Carriers.CURRENT, insertCurrent2);
contentValues2.put(Carriers.NUMERIC, insertNumeric2);
Log.d(TAG, "testInsertCarriers: Bulk inserting contentValues=" + contentValues
+ ", " + contentValues2);
ContentValues[] values = new ContentValues[]{ contentValues, contentValues2 };
int rows = mContentResolver.bulkInsert(Carriers.CONTENT_URI, values);
assertEquals(2, rows);
assertEquals(1, notifyChangeCount);
// get values in table
final String[] testProjection =
{
Carriers.APN,
Carriers.NAME,
Carriers.CURRENT,
};
final String selection = Carriers.NUMERIC + "=?";
String[] selectionArgs = { insertNumeric };
Log.d(TAG, "testInsertCarriers query projection: " + testProjection
+ "\ntestInsertCarriers selection: " + selection
+ "\ntestInsertCarriers selectionArgs: " + selectionArgs);
Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI,
testProjection, selection, selectionArgs, null);
// verify that inserted values match results of query
assertNotNull(cursor);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
final String resultApn = cursor.getString(0);
final String resultName = cursor.getString(1);
final Integer resultCurrent = cursor.getInt(2);
assertEquals(insertApn, resultApn);
assertEquals(insertName, resultName);
assertEquals(insertCurrent, resultCurrent);
}
/**
* Test inserting, querying, and deleting values in carriers table.
* Verify that the inserted values match the result of the query and are deleted.
*/
@Test
@SmallTest
public void testInsertCarriers() {
doSimpleTestForUri(Carriers.CONTENT_URI);
}
/**
* Test migrating int-based MCC/MNCs over to Strings in the sim info table
*/
@Test
@SmallTest
public void testMccMncMigration() {
setUpMockContext(true);
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(SimInfo.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(SimInfo.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(SimInfo.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.
*/
@Test
@SmallTest
public void testUpdateConflictingCarriers() {
setUpMockContext(true);
// insert 2 test contentValues
ContentValues contentValues = new ContentValues();
final String insertApn = "exampleApnName";
final String insertName = "exampleName";
final String insertNumeric = TEST_OPERATOR;
final String insertMcc = TEST_MCC;
final String insertMnc = TEST_MNC;
contentValues.put(Carriers.APN, insertApn);
contentValues.put(Carriers.NAME, insertName);
contentValues.put(Carriers.NUMERIC, insertNumeric);
contentValues.put(Carriers.MCC, insertMcc);
contentValues.put(Carriers.MNC, insertMnc);
ContentValues contentValues2 = new ContentValues();
final String insertName2 = "exampleName2";
contentValues2.put(Carriers.NAME, insertName2);
Uri row1 = mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
Uri row2 = mContentResolver.insert(Carriers.CONTENT_URI, contentValues2);
// use URL_ID to update row2 apn so it conflicts with row1
Log.d(TAG, "testUpdateConflictingCarriers: update row2=" + row2);
contentValues.put(Carriers.NAME, insertName2);
mContentResolver.update(row2, contentValues, null, null);
// verify that only 1 APN now exists and it has the fields from row1 and row2
final String[] testProjection =
{
Carriers.APN,
Carriers.NAME,
Carriers.NUMERIC,
Carriers.MCC,
Carriers.MNC
};
Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection, null, null,
null);
assertNotNull(cursor);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals(insertApn, cursor.getString(0 /* APN */));
assertEquals(insertName2, cursor.getString(1 /* NAME */));
assertEquals(insertNumeric, cursor.getString(2 /* NUMERIC */));
assertEquals(insertMcc, cursor.getString(3 /* MCC */));
assertEquals(insertMnc, cursor.getString(4 /* MNC */));
}
/**
* Test inserting, querying, and deleting values in carriers table.
* Verify that the inserted values match the result of the query and are deleted.
*/
@Test
@SmallTest
public void testInsertCarriersWithSubId() {
doSimpleTestForUri(CONTENT_URI_WITH_SUBID);
}
private void doSimpleTestForUri(Uri uri) {
setUpMockContext(true);
// insert test contentValues
ContentValues contentValues = new ContentValues();
final String insertApn = "exampleApnName";
final String insertName = "exampleName";
final String insertNumeric = TEST_OPERATOR;
contentValues.put(Carriers.APN, insertApn);
contentValues.put(Carriers.NAME, insertName);
contentValues.put(Carriers.NUMERIC, insertNumeric);
Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues);
mContentResolver.insert(uri, contentValues);
// get values in table
final String[] testProjection =
{
Carriers.APN,
Carriers.NAME,
};
final String selection = Carriers.NUMERIC + "=?";
String[] selectionArgs = { insertNumeric };
Log.d(TAG, "testInsertCarriers query projection: " + testProjection
+ "\ntestInsertCarriers selection: " + selection
+ "\ntestInsertCarriers selectionArgs: " + selectionArgs);
Cursor cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
// verify that inserted values match results of query
assertNotNull(cursor);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
final String resultApn = cursor.getString(0);
final String resultName = cursor.getString(1);
assertEquals(insertApn, resultApn);
assertEquals(insertName, resultName);
// delete test content
final String selectionToDelete = Carriers.NUMERIC + "=?";
String[] selectionArgsToDelete = { insertNumeric };
Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
+ "testInsertCarriers selectionArgs: " + selectionArgs);
int numRowsDeleted = mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
assertEquals(1, numRowsDeleted);
// verify that deleted values are gone
cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
assertEquals(0, cursor.getCount());
}
@Test
@SmallTest
public void testOwnedBy() {
setUpMockContext(true);
// insert test contentValues
ContentValues contentValues = new ContentValues();
final String insertApn = "exampleApnName";
final String insertName = "exampleName";
final String insertNumeric = TEST_OPERATOR;
final Integer insertOwnedBy = Carriers.OWNED_BY_OTHERS;
contentValues.put(Carriers.APN, insertApn);
contentValues.put(Carriers.NAME, insertName);
contentValues.put(Carriers.NUMERIC, insertNumeric);
contentValues.put(Carriers.OWNED_BY, insertOwnedBy);
Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues);
mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
// get values in table
final String[] testProjection =
{
Carriers.APN,
Carriers.NAME,
Carriers.OWNED_BY,
};
final String selection = Carriers.NUMERIC + "=?";
String[] selectionArgs = { insertNumeric };
Log.d(TAG, "testInsertCarriers query projection: " + testProjection
+ "\ntestInsertCarriers selection: " + selection
+ "\ntestInsertCarriers selectionArgs: " + selectionArgs);
Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI,
testProjection, selection, selectionArgs, null);
// verify that inserted values match results of query
assertNotNull(cursor);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
final String resultApn = cursor.getString(0);
final String resultName = cursor.getString(1);
final Integer resultOwnedBy = cursor.getInt(2);
assertEquals(insertApn, resultApn);
assertEquals(insertName, resultName);
// Verify that OWNED_BY is force set to OWNED_BY_OTHERS when inserted with general uri
assertEquals(insertOwnedBy, resultOwnedBy);
// delete test content
final String selectionToDelete = Carriers.NUMERIC + "=?";
String[] selectionArgsToDelete = { insertNumeric };
Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
+ "testInsertCarriers selectionArgs: " + selectionArgs);
int numRowsDeleted = mContentResolver.delete(Carriers.CONTENT_URI,
selectionToDelete, selectionArgsToDelete);
assertEquals(1, numRowsDeleted);
// verify that deleted values are gone
cursor = mContentResolver.query(Carriers.CONTENT_URI,
testProjection, selection, selectionArgs, null);
assertEquals(0, cursor.getCount());
}
/**
* Test inserting, querying, and deleting values in carriers table.
* Verify that the inserted values match the result of the query and are deleted.
*/
@Test
@SmallTest
public void testSimTable() {
setUpMockContext(true);
// insert test contentValues
ContentValues contentValues = new ContentValues();
final int insertSubId = 11;
final String insertDisplayName = "exampleDisplayName";
final String insertCarrierName = "exampleCarrierName";
final String insertIccId = "exampleIccId";
final String insertCardId = "exampleCardId";
final int insertProfileClass = SubscriptionManager.PROFILE_CLASS_DEFAULT;
contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
contentValues.put(SubscriptionManager.DISPLAY_NAME, insertDisplayName);
contentValues.put(SubscriptionManager.CARRIER_NAME, insertCarrierName);
contentValues.put(SubscriptionManager.ICC_ID, insertIccId);
contentValues.put(SubscriptionManager.CARD_ID, insertCardId);
contentValues.put(SubscriptionManager.PROFILE_CLASS, insertProfileClass);
Log.d(TAG, "testSimTable Inserting contentValues: " + contentValues);
mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
// get values in table
final String[] testProjection =
{
SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
SubscriptionManager.CARRIER_NAME,
SubscriptionManager.CARD_ID,
SubscriptionManager.PROFILE_CLASS,
};
final String selection = SubscriptionManager.DISPLAY_NAME + "=?";
String[] selectionArgs = { insertDisplayName };
Log.d(TAG,"\ntestSimTable selection: " + selection
+ "\ntestSimTable selectionArgs: " + selectionArgs.toString());
Cursor cursor = mContentResolver.query(SimInfo.CONTENT_URI,
testProjection, selection, selectionArgs, null);
// verify that inserted values match results of query
assertNotNull(cursor);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
final int resultSubId = cursor.getInt(0);
final String resultCarrierName = cursor.getString(1);
final String resultCardId = cursor.getString(2);
final int resultProfileClass = cursor.getInt(3);
assertEquals(insertSubId, resultSubId);
assertEquals(insertCarrierName, resultCarrierName);
assertEquals(insertCardId, resultCardId);
assertEquals(insertProfileClass, resultProfileClass);
// delete test content
final String selectionToDelete = SubscriptionManager.DISPLAY_NAME + "=?";
String[] selectionArgsToDelete = { insertDisplayName };
Log.d(TAG, "testSimTable deleting selection: " + selectionToDelete
+ "testSimTable selectionArgs: " + selectionArgs);
int numRowsDeleted = mContentResolver.delete(SimInfo.CONTENT_URI,
selectionToDelete, selectionArgsToDelete);
assertEquals(1, numRowsDeleted);
// verify that deleted values are gone
cursor = mContentResolver.query(SimInfo.CONTENT_URI,
testProjection, selection, selectionArgs, null);
assertEquals(0, cursor.getCount());
}
private int parseIdFromInsertedUri(Uri uri) throws NumberFormatException {
return (uri != null) ? Integer.parseInt(uri.getLastPathSegment()) : -1;
}
private int insertApnRecord(Uri uri, String apn, String name, int current, String numeric) {
ContentValues contentValues = new ContentValues();
contentValues.put(Carriers.APN, apn);
contentValues.put(Carriers.NAME, name);
contentValues.put(Carriers.CURRENT, current);
contentValues.put(Carriers.NUMERIC, numeric);
Uri resultUri = mContentResolver.insert(uri, contentValues);
return parseIdFromInsertedUri(resultUri);
}
/**
* Test URL_ENFORCE_MANAGED and URL_FILTERED works correctly.
* Verify that when enforce is set true via URL_ENFORCE_MANAGED, only DPC records are returned
* for URL_FILTERED and URL_FILTERED_ID.
* Verify that when enforce is set false via URL_ENFORCE_MANAGED, only non-DPC records
* are returned for URL_FILTERED and URL_FILTERED_ID.
*/
@Test
@SmallTest
public void testEnforceManagedUri() {
setUpMockContext(true);
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
final int current = 1;
final String numeric = TEST_OPERATOR;
// Insert DPC record.
final String dpcRecordApn = "exampleApnNameDPC";
final String dpcRecordName = "exampleNameDPC";
final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
current, numeric);
// Insert non-DPC record.
final String othersRecordApn = "exampleApnNameOTHERS";
final String othersRecordName = "exampleNameDPOTHERS";
final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
current, numeric);
// Set enforced = false.
ContentValues enforceManagedValue = new ContentValues();
enforceManagedValue.put(ENFORCED_KEY, false);
Log.d(TAG, "testEnforceManagedUri Updating enforced = false: "
+ enforceManagedValue);
mContentResolver.update(URI_ENFORCE_MANAGED, enforceManagedValue, "", new String[]{});
// Verify that enforced is set to false in TelephonyProvider.
Cursor enforceCursor = mContentResolver.query(URI_ENFORCE_MANAGED,
null, null, null, null);
assertNotNull(enforceCursor);
assertEquals(1, enforceCursor.getCount());
enforceCursor.moveToFirst();
assertEquals(0, enforceCursor.getInt(0));
// Verify URL_FILTERED query only returns non-DPC record.
final String[] testProjection =
{
Carriers._ID,
Carriers.OWNED_BY
};
final String selection = Carriers.NUMERIC + "=?";
final String[] selectionArgs = { numeric };
final Cursor cursorNotEnforced = mContentResolver.query(URI_FILTERED,
testProjection, selection, selectionArgs, null);
assertNotNull(cursorNotEnforced);
assertEquals(1, cursorNotEnforced.getCount());
cursorNotEnforced.moveToFirst();
assertEquals(othersRecordId, cursorNotEnforced.getInt(0));
assertEquals(Carriers.OWNED_BY_OTHERS, cursorNotEnforced.getInt(1));
// Verify that URL_FILTERED_ID cannot get DPC record.
Cursor cursorNotEnforcedDpc = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
Integer.toString(dpcRecordId)), null, null, null, null);
assertNotNull(cursorNotEnforcedDpc);
assertTrue(cursorNotEnforcedDpc.getCount() == 0);
// Verify that URL_FILTERED_ID can get non-DPC record.
Cursor cursorNotEnforcedOthers = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
Integer.toString(othersRecordId)), null, null, null, null);
assertNotNull(cursorNotEnforcedOthers);
assertTrue(cursorNotEnforcedOthers.getCount() == 1);
// Set enforced = true.
enforceManagedValue.put(ENFORCED_KEY, true);
Log.d(TAG, "testEnforceManagedUri Updating enforced = true: "
+ enforceManagedValue);
mContentResolver.update(URI_ENFORCE_MANAGED, enforceManagedValue, "", new String[]{});
// Verify that enforced is set to true in TelephonyProvider.
enforceCursor = mContentResolver.query(URI_ENFORCE_MANAGED,
null, null, null, null);
assertNotNull(enforceCursor);
assertEquals(1, enforceCursor.getCount());
enforceCursor.moveToFirst();
assertEquals(1, enforceCursor.getInt(0));
// Verify URL_FILTERED query only returns DPC record.
final Cursor cursorEnforced = mContentResolver.query(URI_FILTERED,
testProjection, selection, selectionArgs, null);
assertNotNull(cursorEnforced);
assertEquals(1, cursorEnforced.getCount());
cursorEnforced.moveToFirst();
assertEquals(dpcRecordId, cursorEnforced.getInt(0));
assertEquals(Carriers.OWNED_BY_DPC, cursorEnforced.getInt(1));
// Verify that URL_FILTERED_ID can get DPC record.
cursorNotEnforcedDpc = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
Integer.toString(dpcRecordId)), null, null, null, null);
assertNotNull(cursorNotEnforcedDpc);
assertTrue(cursorNotEnforcedDpc.getCount() == 1);
// Verify that URL_FILTERED_ID cannot get non-DPC record.
cursorNotEnforcedOthers = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
Integer.toString(othersRecordId)), null, null, null, null);
assertNotNull(cursorNotEnforcedOthers);
assertTrue(cursorNotEnforcedOthers.getCount() == 0);
// Delete testing records.
int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
assertEquals(1, numRowsDeleted);
numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
assertEquals(1, numRowsDeleted);
}
private Cursor queryFullTestApnRecord(Uri uri, String numeric) {
final String selection = Carriers.NUMERIC + "=?";
String[] selectionArgs = { numeric };
final String[] testProjection =
{
Carriers._ID,
Carriers.APN,
Carriers.NAME,
Carriers.CURRENT,
Carriers.OWNED_BY,
};
return mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
}
@Test
@SmallTest
/**
* Test URL_TELEPHONY cannot insert, query, update or delete DPC records.
*/
public void testTelephonyUriDpcRecordAccessControl() {
setUpMockContext(true);
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
final int current = 1;
final String numeric = TEST_OPERATOR;
final String selection = Carriers.NUMERIC + "=?";
final String[] selectionArgs = { numeric };
// Insert DPC record.
final String dpcRecordApn = "exampleApnNameDPC";
final String dpcRecordName = "exampleNameDPC";
final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
current, numeric);
// Insert non-DPC record.
final String othersRecordApn = "exampleApnNameOTHERS";
final String othersRecordName = "exampleNameDPOTHERS";
final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
current, numeric);
// Verify URL_TELEPHONY query only returns non-DPC record.
final Cursor cursorTelephony = queryFullTestApnRecord(URI_TELEPHONY, numeric);
assertNotNull(cursorTelephony);
assertEquals(1, cursorTelephony.getCount());
cursorTelephony.moveToFirst();
assertApnEquals(cursorTelephony, othersRecordId, othersRecordApn, othersRecordName,
current, Carriers.OWNED_BY_OTHERS);
// Verify URI_TELEPHONY updates only non-DPC records.
ContentValues contentValuesOthersUpdate = new ContentValues();
final String othersRecordUpdatedApn = "exampleApnNameOTHERSUpdated";
final String othersRecordUpdatedName = "exampleNameOTHERSpdated";
contentValuesOthersUpdate.put(Carriers.APN, othersRecordUpdatedApn);
contentValuesOthersUpdate.put(Carriers.NAME, othersRecordUpdatedName);
final int updateCount = mContentResolver.update(URI_TELEPHONY, contentValuesOthersUpdate,
selection, selectionArgs);
assertEquals(1, updateCount);
final Cursor cursorNonDPCUpdate = queryFullTestApnRecord(URI_TELEPHONY, numeric);
final Cursor cursorDPCUpdate = queryFullTestApnRecord(URI_DPC, numeric);
// Verify that non-DPC records are updated.
assertNotNull(cursorNonDPCUpdate);
assertEquals(1, cursorNonDPCUpdate.getCount());
cursorNonDPCUpdate.moveToFirst();
assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordUpdatedApn,
othersRecordUpdatedName);
// Verify that DPC records are not updated.
assertNotNull(cursorDPCUpdate);
assertEquals(1, cursorDPCUpdate.getCount());
cursorDPCUpdate.moveToFirst();
assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordApn, dpcRecordName);
// Verify URI_TELEPHONY deletes only non-DPC records.
int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
assertEquals(1, numRowsDeleted);
final Cursor cursorTelephonyRemaining = queryFullTestApnRecord(URI_TELEPHONY, numeric);
assertNotNull(cursorTelephonyRemaining);
assertEquals(0, cursorTelephonyRemaining.getCount());
final Cursor cursorDPCDeleted = queryFullTestApnRecord(URI_DPC, numeric);
assertNotNull(cursorDPCDeleted);
assertEquals(1, cursorDPCDeleted.getCount());
// Delete remaining test records.
numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
assertEquals(1, numRowsDeleted);
}
/**
* Test URL_DPC cannot insert or query non-DPC records.
* Test URL_DPC_ID cannot update or delete non-DPC records.
*/
@Test
@SmallTest
public void testDpcUri() {
setUpMockContext(true);
int dpcRecordId = 0, othersRecordId = 0;
try {
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
final int current = 1;
final String numeric = TEST_OPERATOR;
// Insert DPC record.
final String dpcRecordApn = "exampleApnNameDPC";
final String dpcRecordName = "exampleNameDPC";
dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
current, numeric);
// Insert non-DPC record.
final String othersRecordApn = "exampleApnNameOTHERS";
final String othersRecordName = "exampleNameDPOTHERS";
othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
current, numeric);
Log.d(TAG, "testDPCIdUri Id for inserted DPC record: " + dpcRecordId);
Log.d(TAG, "testDPCIdUri Id for inserted non-DPC record: " + othersRecordId);
// Verify that URI_DPC query only returns DPC records.
final Cursor cursorDPC = queryFullTestApnRecord(URI_DPC, numeric);
assertNotNull(cursorDPC);
assertEquals(1, cursorDPC.getCount());
cursorDPC.moveToFirst();
assertApnEquals(cursorDPC, dpcRecordId, dpcRecordApn, dpcRecordName, current,
Carriers.OWNED_BY_DPC);
// Verify that URI_DPC_ID updates only DPC records.
ContentValues contentValuesDpcUpdate = new ContentValues();
final String dpcRecordUpdatedApn = "exampleApnNameDPCUpdated";
final String dpcRecordUpdatedName = "exampleNameDPCUpdated";
contentValuesDpcUpdate.put(Carriers.APN, dpcRecordUpdatedApn);
contentValuesDpcUpdate.put(Carriers.NAME, dpcRecordUpdatedName);
final int updateCount = mContentResolver.update(
ContentUris.withAppendedId(URI_DPC, dpcRecordId),
contentValuesDpcUpdate, null, null);
assertEquals(1, updateCount);
final Cursor cursorNonDPCUpdate = queryFullTestApnRecord(URI_TELEPHONY, numeric);
final Cursor cursorDPCUpdate = queryFullTestApnRecord(URI_DPC, numeric);
// Verify that non-DPC records are not updated.
assertNotNull(cursorNonDPCUpdate);
assertEquals(1, cursorNonDPCUpdate.getCount());
cursorNonDPCUpdate.moveToFirst();
assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordApn, othersRecordName);
// Verify that DPC records are updated.
assertNotNull(cursorDPCUpdate);
assertEquals(1, cursorDPCUpdate.getCount());
cursorDPCUpdate.moveToFirst();
assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordUpdatedApn,
dpcRecordUpdatedName);
// Test URI_DPC_ID deletes only DPC records.
int numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_DPC, dpcRecordId), null, null);
assertEquals(1, numRowsDeleted);
numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_DPC, dpcRecordId), null, null);
assertEquals(0, numRowsDeleted);
} finally {
// Delete remaining test records.
int numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_TELEPHONY, othersRecordId), null, null);
assertEquals(1, numRowsDeleted);
}
}
private void assertApnEquals(Cursor cursor, Object... values) {
assertTrue(values.length <= cursor.getColumnCount());
for (int i = 0; i < values.length; i ++) {
if (values[i] instanceof Integer) {
assertEquals(values[i], cursor.getInt(i));
} else if (values[i] instanceof String) {
assertEquals(values[i], cursor.getString(i));
} else {
fail("values input type not correct");
}
}
}
/**
* Test URL_DPC does not change database on conflict for insert and update.
*/
@Test
@SmallTest
public void testDpcUriOnConflict() {
setUpMockContext(true);
int dpcRecordId1 = 0, dpcRecordId2 = 0;
try {
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
final int current = 1;
final String numeric = TEST_OPERATOR;
// Insert DPC record 1.
final String dpcRecordApn1 = "exampleApnNameDPC";
final String dpcRecordName = "exampleNameDPC";
dpcRecordId1 = insertApnRecord(URI_DPC, dpcRecordApn1, dpcRecordName,
current, numeric);
Log.d(TAG, "testDpcUriOnConflict Id for DPC record 1: " + dpcRecordId1);
// Insert conflicting DPC record.
final String dpcRecordNameConflict = "exampleNameDPCConflict";
final int dpcRecordIdConflict = insertApnRecord(URI_DPC, dpcRecordApn1,
dpcRecordNameConflict, current, numeric);
// Verity that conflicting DPC record is not inserted.
assertEquals(-1, dpcRecordIdConflict);
// Verify that APN 1 is not replaced or updated.
Cursor cursorDPC1 = queryFullTestApnRecord(URI_DPC, numeric);
assertNotNull(cursorDPC1);
assertEquals(1, cursorDPC1.getCount());
cursorDPC1.moveToFirst();
assertApnEquals(cursorDPC1, dpcRecordId1, dpcRecordApn1, dpcRecordName, current,
Carriers.OWNED_BY_DPC);
// Insert DPC record 2.
final String dpcRecordApn2 = "exampleApnNameDPC2";
dpcRecordId2 = insertApnRecord(URI_DPC, dpcRecordApn2, dpcRecordName,
current, numeric);
Log.d(TAG, "testDpcUriOnConflict Id for DPC record 2: " + dpcRecordId2);
// Update DPC record 2 to the values of DPC record 1.
ContentValues contentValuesDpcUpdate = new ContentValues();
contentValuesDpcUpdate.put(Carriers.APN, dpcRecordApn1);
contentValuesDpcUpdate.put(Carriers.NAME, dpcRecordNameConflict);
final int updateCount = mContentResolver.update(
ContentUris.withAppendedId(URI_DPC, dpcRecordId2),
contentValuesDpcUpdate, null, null);
// Verify that database is not updated.
assertEquals(0, updateCount);
Cursor cursorDPC2 = queryFullTestApnRecord(URI_DPC, numeric);
assertNotNull(cursorDPC2);
assertEquals(2, cursorDPC2.getCount());
cursorDPC2.moveToFirst();
assertApnEquals(cursorDPC2, dpcRecordId1, dpcRecordApn1, dpcRecordName, current,
Carriers.OWNED_BY_DPC);
cursorDPC2.moveToNext();
assertApnEquals(cursorDPC2, dpcRecordId2, dpcRecordApn2, dpcRecordName, current,
Carriers.OWNED_BY_DPC);
} finally {
// Delete test records.
int numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_DPC, dpcRecordId1), null, null);
assertEquals(1, numRowsDeleted);
numRowsDeleted = mContentResolver.delete(
ContentUris.withAppendedId(URI_DPC, dpcRecordId2), null, null);
assertEquals(1, numRowsDeleted);
}
}
/**
* Verify that SecurityException is thrown if URL_DPC, URL_FILTERED and
* URL_ENFORCE_MANAGED is accessed from neither SYSTEM_UID nor PHONE_UID.
*/
@Test
@SmallTest
public void testAccessUrlDpcThrowSecurityExceptionFromOtherUid() {
setUpMockContext(true);
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID + 123456);
// Test insert().
ContentValues contentValuesDPC = new ContentValues();
try {
mContentResolver.insert(URI_DPC, contentValuesDPC);
assertFalse("SecurityException should be thrown when URI_DPC is called from"
+ " neither SYSTEM_UID nor PHONE_UID", true);
} catch (SecurityException e) {
// Should catch SecurityException.
}
// Test query().
try {
mContentResolver.query(URI_DPC,
new String[]{}, "", new String[]{}, null);
assertFalse("SecurityException should be thrown when URI_DPC is called from"
+ " neither SYSTEM_UID nor PHONE_UID", true);
} catch (SecurityException e) {
// Should catch SecurityException.
}
try {
mContentResolver.query(URI_ENFORCE_MANAGED,
new String[]{}, "", new String[]{}, null);
assertFalse("SecurityException should be thrown when URI_ENFORCE_MANAGED is "
+ "called from neither SYSTEM_UID nor PHONE_UID", true);
} catch (SecurityException e) {
// Should catch SecurityException.
}
// Test update().
ContentValues contentValuesDPCUpdate = new ContentValues();
try {
mContentResolver.update(
Uri.parse(URI_DPC + "/1"),
contentValuesDPCUpdate, "", new String[]{});
assertFalse("SecurityException should be thrown when URI_DPC is called"
+ " from neither SYSTEM_UID nor PHONE_UID", true);
} catch (SecurityException e) {
// Should catch SecurityException.
}
try {
mContentResolver.update(URI_ENFORCE_MANAGED, contentValuesDPCUpdate,
"", new String[]{});
assertFalse("SecurityException should be thrown when URI_DPC is called"
+ " from neither SYSTEM_UID nor PHONE_UID", true);
} catch (SecurityException e) {
// Should catch SecurityException.
}
// Test delete().
try {
mContentResolver.delete(
Uri.parse(URI_DPC + "/0"), "", new String[]{});
assertFalse("SecurityException should be thrown when URI_DPC is called"
+ " from neither SYSTEM_UID nor PHONE_UID", true);
} catch (SecurityException e) {
// Should catch SecurityException.
}
}
/**
* Verify that user/carrier edited/deleted APNs have priority in the EDITED field over
* insertions which set EDITED=UNEDITED. In these cases instead of merging the APNs using the
* new APN's value we keep the old value.
*/
@Test
@SmallTest
public void testPreserveEdited() {
preserveEditedValueInMerge(Carriers.USER_EDITED);
}
@Test
@SmallTest
public void testPreserveUserDeleted() {
preserveDeletedValueInMerge(Carriers.USER_DELETED);
}
@Test
@SmallTest
public void testPreserveUserDeletedButPresentInXml() {
preserveDeletedValueInMerge(Carriers.USER_DELETED_BUT_PRESENT_IN_XML);
}
@Test
@SmallTest
public void testPreserveCarrierEdited() {
preserveEditedValueInMerge(Carriers.CARRIER_EDITED);
}
@Test
@SmallTest
public void testPreserveCarrierDeleted() {
preserveDeletedValueInMerge(Carriers.CARRIER_DELETED);
}
@Test
@SmallTest
public void testPreserveCarrierDeletedButPresentInXml() {
preserveDeletedValueInMerge(Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML);
}
private void preserveEditedValueInMerge(int value) {
setUpMockContext(true);
// insert user deleted APN
String carrierName1 = "carrier1";
String numeric1 = "123234";
String mcc1 = "123";
String mnc1 = "234";
ContentValues editedValue = new ContentValues();
editedValue.put(Carriers.NAME, carrierName1);
editedValue.put(Carriers.NUMERIC, numeric1);
editedValue.put(Carriers.MCC, mcc1);
editedValue.put(Carriers.MNC, mnc1);
editedValue.put(Carriers.EDITED_STATUS, value);
assertNotNull(mContentResolver.insert(URI_TELEPHONY, editedValue));
Cursor cur = mContentResolver.query(URI_TELEPHONY, null, null, null, null);
assertEquals(1, cur.getCount());
// insert APN that conflicts with edited APN
String carrierName2 = "carrier2";
ContentValues values = new ContentValues();
values.put(Carriers.NAME, carrierName2);
values.put(Carriers.NUMERIC, numeric1);
values.put(Carriers.MCC, mcc1);
values.put(Carriers.MNC, mnc1);
values.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
mContentResolver.insert(URI_TELEPHONY, values);
String[] testProjection = {
Carriers.NAME,
Carriers.APN,
Carriers.EDITED_STATUS,
Carriers.TYPE,
Carriers.PROTOCOL,
Carriers.BEARER_BITMASK,
};
final int indexOfName = 0;
final int indexOfEdited = 2;
// Assert that the conflicting APN is merged into the existing user-edited APN, so only 1
// APN exists in the db
cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
assertEquals(1, cur.getCount());
cur.moveToFirst();
assertEquals(carrierName2, cur.getString(indexOfName));
assertEquals(value, cur.getInt(indexOfEdited));
}
private void preserveDeletedValueInMerge(int value) {
setUpMockContext(true);
// insert user deleted APN
String carrierName1 = "carrier1";
String numeric1 = "123234";
String mcc1 = "123";
String mnc1 = "234";
ContentValues editedValue = new ContentValues();
editedValue.put(Carriers.NAME, carrierName1);
editedValue.put(Carriers.NUMERIC, numeric1);
editedValue.put(Carriers.MCC, mcc1);
editedValue.put(Carriers.MNC, mnc1);
editedValue.put(Carriers.EDITED_STATUS, value);
assertNotNull(mContentResolver.insert(URI_TELEPHONY, editedValue));
// insert APN that conflicts with edited APN
String carrierName2 = "carrier2";
ContentValues values = new ContentValues();
values.put(Carriers.NAME, carrierName2);
values.put(Carriers.NUMERIC, numeric1);
values.put(Carriers.MCC, mcc1);
values.put(Carriers.MNC, mnc1);
values.put(Carriers.EDITED_STATUS, Carriers.UNEDITED);
mContentResolver.insert(URI_TELEPHONY, values);
String[] testProjection = {
Carriers.NAME,
Carriers.APN,
Carriers.EDITED_STATUS,
Carriers.TYPE,
Carriers.PROTOCOL,
Carriers.BEARER_BITMASK,
};
final int indexOfEdited = 2;
// Assert that the conflicting APN is merged into the existing user-deleted APN.
// Entries marked deleted will not show up in queries so we verify that no APNs can
// be seen
Cursor cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
assertEquals(0, cur.getCount());
}
/**
* Test URL_PREFERAPN_USING_SUBID works correctly.
*/
@Test
@SmallTest
public void testQueryPreferredApn() {
setUpMockContext(true);
// create APNs
ContentValues preferredValues = new ContentValues();
final String preferredApn = "preferredApn";
final String preferredName = "preferredName";
preferredValues.put(Carriers.APN, preferredApn);
preferredValues.put(Carriers.NAME, preferredName);
preferredValues.put(Carriers.NUMERIC, TEST_OPERATOR);
ContentValues otherValues = new ContentValues();
final String otherApn = "otherApnName";
final String otherName = "otherName";
otherValues.put(Carriers.APN, otherApn);
otherValues.put(Carriers.NAME, otherName);
otherValues.put(Carriers.NUMERIC, TEST_OPERATOR);
// insert APNs
// TODO if using URL_TELEPHONY, SubscriptionManager.getDefaultSubscriptionId() returns -1
Log.d(TAG, "testQueryPreferredApn: Bulk inserting contentValues=" + preferredValues + ", "
+ otherValues);
Uri uri = mContentResolver.insert(CONTENT_URI_WITH_SUBID, preferredValues);
mContentResolver.insert(CONTENT_URI_WITH_SUBID, otherValues);
final String preferredApnIdString = uri.getLastPathSegment();
final long preferredApnId = Long.parseLong(preferredApnIdString);
Log.d(TAG, "testQueryPreferredApn: preferredApnString=" + preferredApnIdString);
// set preferred apn
preferredValues.put(COLUMN_APN_ID, preferredApnIdString);
mContentResolver.insert(URL_PREFERAPN_USING_SUBID, preferredValues);
// query preferred APN
final String[] testProjection = { Carriers.APN, Carriers.NAME };
Cursor cursor = mContentResolver.query(
URL_PREFERAPN_USING_SUBID, testProjection, null, null, null);
// verify that preferred apn was set and retreived
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals(preferredApn, cursor.getString(0));
assertEquals(preferredName, cursor.getString(1));
}
/**
* Test that APN_SET_ID works correctly.
*/
@Test
@SmallTest
public void testApnSetId() {
setUpMockContext(true);
// create APNs
ContentValues values1 = new ContentValues();
final String apn = "apnName";
final String apnName = "name";
values1.put(Carriers.APN, apn);
values1.put(Carriers.NAME, apnName);
values1.put(Carriers.NUMERIC, TEST_OPERATOR);
ContentValues values2 = new ContentValues();
final String otherApn = "otherApnName";
final String otherName = "otherName";
values2.put(Carriers.APN, otherApn);
values2.put(Carriers.NAME, otherName);
values2.put(Carriers.NUMERIC, TEST_OPERATOR);
values2.put(Carriers.APN_SET_ID, 1);
// insert APNs
// TODO if using URL_TELEPHONY, SubscriptionManager.getDefaultSubscriptionId() returns -1
Log.d(TAG, "testApnSetId: inserting contentValues=" + values1 + ", " + values2);
mContentResolver.insert(CONTENT_URI_WITH_SUBID, values1);
mContentResolver.insert(CONTENT_URI_WITH_SUBID, values2);
// query APN with default APN_SET_ID
final String[] testProjection = { Carriers.NAME };
Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection,
Carriers.APN_SET_ID + "=?", new String[] { "0" }, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals(apnName, cursor.getString(0));
// query APN with APN_SET_ID=1
cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection,
Carriers.APN_SET_ID + "=?", new String[] { "1" }, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals(otherName, cursor.getString(0));
}
/**
* Test that querying with the PREFERAPNSET url yields all APNs in the preferred set.
*/
@Test
@SmallTest
public void testPreferApnSetUrl() {
setUpMockContext(true);
// create APNs
ContentValues values1 = new ContentValues();
final String apn = "apnName";
final String apnName = "name";
values1.put(Carriers.APN, apn);
values1.put(Carriers.NAME, apnName);
values1.put(Carriers.NUMERIC, TEST_OPERATOR);
ContentValues values2 = new ContentValues();
final String apn2 = "otherApnName";
final String name2 = "name2";
values2.put(Carriers.APN, apn2);
values2.put(Carriers.NAME, name2);
values2.put(Carriers.NUMERIC, TEST_OPERATOR);
values2.put(Carriers.APN_SET_ID, 1);
ContentValues values3 = new ContentValues();
final String apn3 = "thirdApnName";
final String name3 = "name3";
values3.put(Carriers.APN, apn3);
values3.put(Carriers.NAME, name3);
values3.put(Carriers.NUMERIC, TEST_OPERATOR);
values3.put(Carriers.APN_SET_ID, 1);
// values4 has a matching setId but it belongs to a different carrier
ContentValues values4 = new ContentValues();
final String apn4 = "fourthApnName";
final String name4 = "name4";
values4.put(Carriers.APN, apn4);
values4.put(Carriers.NAME, name4);
values4.put(Carriers.NUMERIC, "999888");
values4.put(Carriers.APN_SET_ID, 1);
// insert APNs
// we explicitly include subid, as SubscriptionManager.getDefaultSubscriptionId() returns -1
Log.d(TAG, "testPreferApnSetUrl: inserting contentValues=" + values1 + ", " + values2
+ ", " + values3 + ", " + values4);
mContentResolver.insert(CONTENT_URI_WITH_SUBID, values1);
mContentResolver.insert(CONTENT_URI_WITH_SUBID, values2);
mContentResolver.insert(CONTENT_URI_WITH_SUBID, values4);
Uri uri = mContentResolver.insert(CONTENT_URI_WITH_SUBID, values3);
// verify all APNs were correctly inserted
final String[] testProjection = { Carriers.NAME };
Cursor cursor = mContentResolver.query(
Carriers.CONTENT_URI, testProjection, null, null, null);
assertEquals(4, cursor.getCount());
// preferapnset/subId returns null when there is no preferred APN
cursor = mContentResolver.query(
Uri.withAppendedPath(Carriers.CONTENT_URI, "preferapnset/subId/" + TEST_SUBID),
testProjection, null, null, null);
assertNull(cursor);
// set the APN from values3 (apn_set_id = 1) to the preferred APN
final String preferredApnIdString = uri.getLastPathSegment();
final long preferredApnId = Long.parseLong(preferredApnIdString);
ContentValues prefer = new ContentValues();
prefer.put("apn_id", preferredApnId);
int count = mContentResolver.update(URL_PREFERAPN_USING_SUBID, prefer, null, null);
assertEquals(1, count);
// query APN with PREFERAPNSET url
// explicitly include SUB_ID, as SubscriptionManager.getDefaultSubscriptionId() returns -1
cursor = mContentResolver.query(
Uri.withAppendedPath(Carriers.CONTENT_URI, "preferapnset/subId/" + TEST_SUBID),
testProjection, null, null, null);
// values4 which was inserted with a different carrier is not included in the results
assertEquals(2, cursor.getCount());
cursor.moveToFirst();
assertEquals(name2, cursor.getString(0));
cursor.moveToNext();
assertEquals(name3, cursor.getString(0));
}
/**
* Test URL_RESTOREAPN_USING_SUBID works correctly.
*/
@Test
@SmallTest
public void testRestoreDefaultApn() {
setUpMockContext(true);
// 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);
doReturn(true).when(telephonyManager).isCurrentSimOperator(
anyString(), anyInt(), eq(TelephonyProviderTestable.TEST_SPN));
doReturn(false).when(telephonyManager).isCurrentSimOperator(
anyString(), anyInt(), eq(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());
assertEquals(3, notifyChangeRestoreCount);
}
/**
* Test changes to siminfo/WFC_IMS_ENABLED and simInfo/ENHANCED_4G
*/
@Test
@SmallTest
public void testUpdateWfcEnabled() {
setUpMockContext(true);
// insert test contentValues
ContentValues contentValues = new ContentValues();
final int insertSubId = 1;
final String insertDisplayName = "exampleDisplayName";
final String insertCarrierName = "exampleCarrierName";
final String insertIccId = "exampleIccId";
final String insertCardId = "exampleCardId";
contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
contentValues.put(SubscriptionManager.DISPLAY_NAME, insertDisplayName);
contentValues.put(SubscriptionManager.CARRIER_NAME, insertCarrierName);
contentValues.put(SubscriptionManager.ICC_ID, insertIccId);
contentValues.put(SubscriptionManager.CARD_ID, insertCardId);
Log.d(TAG, "testSimTable Inserting wfc contentValues: " + contentValues);
mContentResolver.insert(SimInfo.CONTENT_URI, contentValues);
assertEquals(0, notifyWfcCount);
// update wfc_enabled
ContentValues values = new ContentValues();
values.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, true);
final String selection = SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=?";
final String[] selectionArgs = { "" + insertSubId };
mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
assertEquals(1, notifyWfcCount);
assertEquals(0, notifyWfcCountWithTestSubId);
// update other fields
values = new ContentValues();
values.put(SubscriptionManager.DISPLAY_NAME, "exampleDisplayNameNew");
mContentResolver.update(SimInfo.CONTENT_URI, values, selection, selectionArgs);
// expect no change on wfc count
assertEquals(1, notifyWfcCount);
assertEquals(0, notifyWfcCountWithTestSubId);
// update WFC using subId
values = new ContentValues();
values.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, false);
mContentResolver.update(SubscriptionManager.getUriForSubscriptionId(insertSubId),
values, null, null);
assertEquals(1, notifyWfcCount);
assertEquals(0, notifyWfcCountWithTestSubId);
}
@Test
@SmallTest
public void testSIMAPNLIST_MatchTheMVNOAPN() {
setUpMockContext(true);
// 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 MVNO APN
ContentValues contentValues = new ContentValues();
contentValues.put(Carriers.APN, apnName);
contentValues.put(Carriers.NAME, carrierName);
contentValues.put(Carriers.NUMERIC, numeric);
contentValues.put(Carriers.MVNO_TYPE, mvnoType);
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);
TelephonyManager telephonyManager =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
doReturn(true).when(telephonyManager).isCurrentSimOperator(
anyString(), anyInt(), eq(mvnoData));
doReturn(false).when(telephonyManager).isCurrentSimOperator(
anyString(), anyInt(), eq(""));
// Query DB
final String[] testProjection =
{
Carriers.APN,
Carriers.NAME,
Carriers.NUMERIC,
Carriers.MVNO_MATCH_DATA
};
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));
assertEquals(mvnoData, cursor.getString(3));
}
@Test
@SmallTest
public void testSIMAPNLIST_MatchTheMNOAPN() {
setUpMockContext(true);
// Test on getSubscriptionMatchingAPNList() step 2
final String apnName = "apnName";
final String carrierName = "name";
final String numeric = TEST_OPERATOR;
// Insert the MNO APN
ContentValues 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 =
{
Carriers.APN,
Carriers.NAME,
Carriers.NUMERIC,
};
Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
testProjection, null, null, null);
cursor.moveToFirst();
assertEquals(apnName, cursor.getString(0));
assertEquals(carrierName, cursor.getString(1));
assertEquals(numeric, cursor.getString(2));
}
@Test
@SmallTest
public void testSIMAPNLIST_MatchTheCarrierIDANDMNOAPN() {
setUpMockContext(true);
// 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() {
setUpMockContext(true);
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)));
}
}
@Test
@SmallTest
public void testSIMAPNLIST_isNotActiveSubscription() {
setUpMockContext(false);
// Test on getSubscriptionMatchingAPNList() step 2
final String apnName = "apnName";
final String carrierName = "name";
final String numeric = TEST_OPERATOR;
// Insert the MNO APN
ContentValues 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 =
{
Carriers.APN,
Carriers.NAME,
Carriers.NUMERIC,
};
Cursor cursor = mContentResolver.query(URL_SIM_APN_LIST,
testProjection, null, null, null);
assertNull(cursor);
}
}