CarrierIdProvider improvements
1. handle insertion conflict. When a constraint violation occurs, the
row that contains the violation is not inserted. But the command continues
executing normally.
2. add read permission.
3. improve memory usage. not allocate a CV for every known carrier.
4. update the installed table version after setTransactionSuccessful
Bug: 64131637
Test: Unit test
Change-Id: If6d558e9263c78611b940170ba1612d8a2279b23
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 38f9fc0..7a6f683 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -111,6 +111,7 @@
android:exported="true"
android:singleUser="true"
android:multiprocess="false"
+ android:readPermission="android.permission.READ_PRIVILEGED_PHONE_STATE"
android:writePermission="android.permission.MODIFY_PHONE_STATE" />
<service
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
index a712198..4b4ce8f 100644
--- a/src/com/android/providers/telephony/CarrierIdProvider.java
+++ b/src/com/android/providers/telephony/CarrierIdProvider.java
@@ -165,7 +165,7 @@
mDbHelper.getReadableDatabase();
s_urlMatcher.addURI(AUTHORITY, "update_db", URL_UPDATE_FROM_PB);
s_urlMatcher.addURI(AUTHORITY, "get_version", URL_GET_VERSION);
- initDatabaseFromPb(mDbHelper.getWritableDatabase());
+ updateDatabaseFromPb(mDbHelper.getWritableDatabase());
return true;
}
@@ -242,7 +242,7 @@
final int match = s_urlMatcher.match(uri);
switch (match) {
case URL_UPDATE_FROM_PB:
- return initDatabaseFromPb(getWritableDatabase());
+ return updateDatabaseFromPb(getWritableDatabase());
default:
final int count = getWritableDatabase().update(CARRIER_ID_TABLE, values, selection,
selectionArgs);
@@ -308,34 +308,47 @@
* Use version number to detect file update.
* Update database with data from assets or ota only if version jumps.
*/
- private int initDatabaseFromPb(SQLiteDatabase db) {
- Log.d(TAG, "init database from pb file");
+ private int updateDatabaseFromPb(SQLiteDatabase db) {
+ Log.d(TAG, "update database from pb file");
int rows = 0;
CarrierIdProto.CarrierList carrierList = getUpdateCarrierList();
+ // No update is needed
if (carrierList == null) return rows;
- setAppliedVersion(carrierList.version);
- List<ContentValues> cvs = new ArrayList<>();
- for (CarrierIdProto.CarrierId id : carrierList.carrierId) {
- for (CarrierIdProto.CarrierAttribute attr : id.carrierAttribute) {
- ContentValues cv = new ContentValues();
- cv.put(CarrierIdentification.CID, id.canonicalId);
- cv.put(CarrierIdentification.NAME, id.carrierName);
- convertCarrierAttrToContentValues(cv, cvs, attr, 0);
- }
- }
+
+ ContentValues cv;
+ List<ContentValues> cvs;
try {
- // Batch all insertions in single transaction to improve efficiency
+ // Batch all insertions in a single transaction to improve efficiency.
db.beginTransaction();
db.delete(CARRIER_ID_TABLE, null, null);
- for (ContentValues cv : cvs) {
- if (db.insertOrThrow(CARRIER_ID_TABLE, null, cv) > 0) rows++;
+ for (CarrierIdProto.CarrierId id : carrierList.carrierId) {
+ for (CarrierIdProto.CarrierAttribute attr : id.carrierAttribute) {
+ cv = new ContentValues();
+ cv.put(CarrierIdentification.CID, id.canonicalId);
+ cv.put(CarrierIdentification.NAME, id.carrierName);
+ cvs = new ArrayList<>();
+ convertCarrierAttrToContentValues(cv, cvs, attr, 0);
+ for (ContentValues contentVal : cvs) {
+ // When a constraint violation occurs, the row that contains the violation
+ // is not inserted. But the command continues executing normally.
+ if (db.insertWithOnConflict(CARRIER_ID_TABLE, null, contentVal,
+ SQLiteDatabase.CONFLICT_IGNORE) > 0) {
+ rows++;
+ } else {
+ Log.e(TAG, "updateDatabaseFromPB insertion failure, row: "
+ + rows + "carrier id: " + id.canonicalId);
+ // TODO metrics
+ }
+ }
+ }
}
- Log.d(TAG, "init database from pb. inserted rows = " + rows);
+ Log.d(TAG, "update database from pb. inserted rows = " + rows);
if (rows > 0) {
// Notify listener of DB change
getContext().getContentResolver().notifyChange(CarrierIdentification.CONTENT_URI,
null);
}
+ setAppliedVersion(carrierList.version);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -497,4 +510,4 @@
buffer.flush();
return buffer.toByteArray();
}
-}
\ No newline at end of file
+}