Merge "Let URL_DPC use CONFLICT_IGNORE algorithm for insert and update."
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 8ae3475..8242752 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -2714,9 +2714,15 @@
values.put(OWNED_BY, OWNED_BY_DPC);
// DPC records should not be user editable.
values.put(USER_EDITABLE, false);
- Pair<Uri, Boolean> ret = insertRowWithValue(values);
- result = ret.first;
- notify = ret.second;
+
+ final long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
+ SQLiteDatabase.CONFLICT_IGNORE);
+ if (rowID >= 0) {
+ result = ContentUris.withAppendedId(CONTENT_URI, rowID);
+ notify = true;
+ }
+ if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
+
break;
}
@@ -3032,7 +3038,7 @@
}
count = db.updateWithOnConflict(CARRIERS_TABLE, values,
_ID + "=?" + " and " + IS_OWNED_BY_DPC,
- new String[] { url.getLastPathSegment() }, SQLiteDatabase.CONFLICT_REPLACE);
+ new String[] { url.getLastPathSegment() }, SQLiteDatabase.CONFLICT_IGNORE);
break;
}
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 5e10917..e1a048e 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -19,6 +19,7 @@
import android.annotation.TargetApi;
import android.content.ContentProvider;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -450,17 +451,8 @@
assertEquals(0, cursor.getCount());
}
- private int parseIdFromInsertedUri(Uri uri) {
- int id = 0;
- if (uri != null) {
- try {
- id = Integer.parseInt(uri.getLastPathSegment());
- }
- catch (NumberFormatException e) {
- }
- }
- assertTrue("Can't parse ID for inserted APN", id != 0);
- return id;
+ 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) {
@@ -491,13 +483,13 @@
// Insert DPC record.
final String dpcRecordApn = "exampleApnNameDPC";
final String dpcRecordName = "exampleNameDPC";
- int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
+ final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
current, numeric);
// Insert non-DPC record.
final String othersRecordApn = "exampleApnNameOTHERS";
final String othersRecordName = "exampleNameDPOTHERS";
- int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
+ final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
current, numeric);
// Set enforced = false.
@@ -522,8 +514,8 @@
Carriers.OWNED_BY
};
final String selection = Carriers.NUMERIC + "=?";
- String[] selectionArgs = { numeric };
- Cursor cursorNotEnforced = mContentResolver.query(URI_FILTERED,
+ final String[] selectionArgs = { numeric };
+ final Cursor cursorNotEnforced = mContentResolver.query(URI_FILTERED,
testProjection, selection, selectionArgs, null);
assertNotNull(cursorNotEnforced);
assertEquals(1, cursorNotEnforced.getCount());
@@ -557,7 +549,7 @@
assertEquals(1, enforceCursor.getInt(0));
// Verify URL_FILTERED query only returns DPC record.
- Cursor cursorEnforced = mContentResolver.query(URI_FILTERED,
+ final Cursor cursorEnforced = mContentResolver.query(URI_FILTERED,
testProjection, selection, selectionArgs, null);
assertNotNull(cursorEnforced);
assertEquals(1, cursorEnforced.getCount());
@@ -581,55 +573,56 @@
assertEquals(1, numRowsDeleted);
numRowsDeleted = mContentResolver.delete(
- Uri.parse(URI_DPC + "/" + dpcRecordId),
- "", new String[]{});
+ 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() {
+ public void testTelephonyUriDpcRecordAccessControl() {
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
final int current = 1;
final String numeric = "123456789";
+ final String selection = Carriers.NUMERIC + "=?";
+ final String[] selectionArgs = { numeric };
// Insert DPC record.
final String dpcRecordApn = "exampleApnNameDPC";
final String dpcRecordName = "exampleNameDPC";
- int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
+ final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
current, numeric);
// Insert non-DPC record.
final String othersRecordApn = "exampleApnNameOTHERS";
final String othersRecordName = "exampleNameDPOTHERS";
- int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
+ final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
current, numeric);
// Verify URL_TELEPHONY query only returns non-DPC record.
- final String[] testProjection =
- {
- Carriers._ID,
- Carriers.APN,
- Carriers.NAME,
- Carriers.CURRENT,
- Carriers.OWNED_BY,
- };
- final String selection = Carriers.NUMERIC + "=?";
- String[] selectionArgs = { numeric };
- Cursor cursorTelephony = mContentResolver.query(URI_TELEPHONY,
- testProjection, selection, selectionArgs, null);
+ final Cursor cursorTelephony = queryFullTestApnRecord(URI_TELEPHONY, numeric);
assertNotNull(cursorTelephony);
assertEquals(1, cursorTelephony.getCount());
cursorTelephony.moveToFirst();
- assertEquals(othersRecordId, cursorTelephony.getInt(0));
- assertEquals(othersRecordApn, cursorTelephony.getString(1));
- assertEquals(othersRecordName, cursorTelephony.getString(2));
- assertEquals(current, cursorTelephony.getInt(3));
- assertEquals(Carriers.OWNED_BY_OTHERS, cursorTelephony.getInt(4));
+ assertApnEquals(cursorTelephony, othersRecordId, othersRecordApn, othersRecordName,
+ current, Carriers.OWNED_BY_OTHERS);
// Verify URI_TELEPHONY updates only non-DPC records.
ContentValues contentValuesOthersUpdate = new ContentValues();
@@ -637,45 +630,39 @@
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);
- Cursor cursorNonDPCUpdate = mContentResolver.query(URI_TELEPHONY,
- testProjection, selection, selectionArgs, null);
- Cursor cursorDPCUpdate = mContentResolver.query(URI_DPC,
- testProjection, selection, selectionArgs, null);
+ 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();
- assertEquals(othersRecordId, cursorNonDPCUpdate.getInt(0));
- assertEquals(othersRecordUpdatedApn, cursorNonDPCUpdate.getString(1));
- assertEquals(othersRecordUpdatedName, cursorNonDPCUpdate.getString(2));
+ assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordUpdatedApn,
+ othersRecordUpdatedName);
// Verify that DPC records are not updated.
assertNotNull(cursorDPCUpdate);
assertEquals(1, cursorDPCUpdate.getCount());
cursorDPCUpdate.moveToFirst();
- assertEquals(dpcRecordId, cursorDPCUpdate.getInt(0));
- assertEquals(dpcRecordApn, cursorDPCUpdate.getString(1));
- assertEquals(dpcRecordName, cursorDPCUpdate.getString(2));
+ assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordApn, dpcRecordName);
// Verify URI_TELEPHONY deletes only non-DPC records.
int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
assertEquals(1, numRowsDeleted);
- Cursor cursorTelephonyRemaining = mContentResolver.query(URI_TELEPHONY,
- testProjection, selection, selectionArgs, null);
+ final Cursor cursorTelephonyRemaining = queryFullTestApnRecord(URI_TELEPHONY, numeric);
assertNotNull(cursorTelephonyRemaining);
assertEquals(0, cursorTelephonyRemaining.getCount());
- Cursor cursorDPCDeleted = mContentResolver.query(URI_DPC,
- testProjection, selection, selectionArgs, null);
+ final Cursor cursorDPCDeleted = queryFullTestApnRecord(URI_DPC, numeric);
assertNotNull(cursorDPCDeleted);
assertEquals(1, cursorDPCDeleted.getCount());
// Delete remaining test records.
numRowsDeleted = mContentResolver.delete(
- Uri.parse(URI_DPC + "/" + dpcRecordId), "", new String[]{});
+ ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
assertEquals(1, numRowsDeleted);
}
@@ -686,97 +673,160 @@
@Test
@SmallTest
public void testDpcUri() {
- mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
+ int dpcRecordId = 0, othersRecordId = 0;
+ try {
+ mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
- final int current = 1;
- final String numeric = "123456789";
+ final int current = 1;
+ final String numeric = "123456789";
- // Insert DPC record.
- final String dpcRecordApn = "exampleApnNameDPC";
- final String dpcRecordName = "exampleNameDPC";
- int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
- current, numeric);
+ // 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";
- int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
- 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);
+ 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.
- // The columns to get in table.
- final String[] testProjection =
- {
- Carriers._ID,
- Carriers.APN,
- Carriers.NAME,
- Carriers.CURRENT,
- Carriers.OWNED_BY,
- };
- final String selection = Carriers.NUMERIC + "=?";
- String[] selectionArgs = { numeric };
- Cursor cursorDPC = mContentResolver.query(URI_DPC,
- testProjection, selection, selectionArgs, null);
+ // 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 DPC query returns only DPC records.
- assertNotNull(cursorDPC);
- assertEquals(1, cursorDPC.getCount());
- cursorDPC.moveToFirst();
- assertEquals(dpcRecordId, cursorDPC.getInt(0));
- assertEquals(dpcRecordApn, cursorDPC.getString(1));
- assertEquals(dpcRecordName, cursorDPC.getString(2));
- assertEquals(current, cursorDPC.getInt(3));
- assertEquals(Carriers.OWNED_BY_DPC, cursorDPC.getInt(4));
+ // 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 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(
- Uri.parse(URI_DPC + "/" + dpcRecordId),
- contentValuesDpcUpdate, null, null);
- assertEquals(1, updateCount);
- Cursor cursorNonDPCUpdate = mContentResolver.query(URI_TELEPHONY,
- testProjection, selection, selectionArgs, null);
- Cursor cursorDPCUpdate = mContentResolver.query(URI_DPC,
- testProjection, selection, selectionArgs, null);
+ // Verify that non-DPC records are not updated.
+ assertNotNull(cursorNonDPCUpdate);
+ assertEquals(1, cursorNonDPCUpdate.getCount());
+ cursorNonDPCUpdate.moveToFirst();
+ assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordApn, othersRecordName);
- // Verify that non-DPC records are not updated.
- assertNotNull(cursorNonDPCUpdate);
- assertEquals(1, cursorNonDPCUpdate.getCount());
- cursorNonDPCUpdate.moveToFirst();
- assertEquals(othersRecordId, cursorNonDPCUpdate.getInt(0));
- assertEquals(othersRecordApn, cursorNonDPCUpdate.getString(1));
- assertEquals(othersRecordName, cursorNonDPCUpdate.getString(2));
+ // Verify that DPC records are updated.
+ assertNotNull(cursorDPCUpdate);
+ assertEquals(1, cursorDPCUpdate.getCount());
+ cursorDPCUpdate.moveToFirst();
+ assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordUpdatedApn,
+ dpcRecordUpdatedName);
- // Verify that DPC records are updated.
- assertNotNull(cursorDPCUpdate);
- assertEquals(1, cursorDPCUpdate.getCount());
- cursorDPCUpdate.moveToFirst();
- assertEquals(dpcRecordId, cursorDPCUpdate.getInt(0));
- assertEquals(dpcRecordUpdatedApn, cursorDPCUpdate.getString(1));
- assertEquals(dpcRecordUpdatedName, cursorDPCUpdate.getString(2));
+ // 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);
- // Test URI_DPC_ID deletes only DPC records.
- int numRowsDeleted = mContentResolver.delete(
- Uri.parse(URI_DPC + "/" + dpcRecordId),
- null, new String[]{});
- assertEquals(1, numRowsDeleted);
- numRowsDeleted = mContentResolver.delete(
- Uri.parse(URI_DPC + "/" + dpcRecordId),
- null, new String[]{});
- assertEquals(0, numRowsDeleted);
+ } finally {
+ // Delete remaining test records.
+ int numRowsDeleted = mContentResolver.delete(
+ ContentUris.withAppendedId(URI_TELEPHONY, othersRecordId), null, null);
+ assertEquals(1, numRowsDeleted);
+ }
+ }
- // Delete remaining test records.
- numRowsDeleted = mContentResolver.delete(
- Uri.parse(URI_TELEPHONY + "/" + othersRecordId),
- null, new String[]{});
- 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() {
+ int dpcRecordId1 = 0, dpcRecordId2 = 0;
+ try {
+ mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
+
+ final int current = 1;
+ final String numeric = "123456789";
+
+ // 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);
+ }
}
/**
@@ -785,7 +835,7 @@
*/
@Test
@SmallTest
- public void testAccessURLDPCThrowSecurityExceptionFromOtherUid() {
+ public void testAccessUrlDpcThrowSecurityExceptionFromOtherUid() {
mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID + 123456);
// Test insert().