Apply contact save ops before we reach the max batch op threshold
In order to test the special case handled by this CL, you may want
to use a contact consisting of at least 23 contacts.
Bug: 22986058
Change-Id: Ic141a7b52907be930d898d1710e95aa5ffe9be8a
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 12ae150..d014087 100755
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -56,7 +56,6 @@
import com.android.contacts.common.model.RawContactModifier;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.PermissionsUtil;
-import com.android.contacts.editor.ContactEditorFragment;
import com.android.contacts.util.ContactPhotoUtils;
import com.google.common.collect.Lists;
@@ -375,6 +374,7 @@
Uri lookupUri = null;
final ContentResolver resolver = getContentResolver();
+
boolean succeeded = false;
// Keep track of the id of a newly raw-contact (if any... there can be at most one).
@@ -386,6 +386,7 @@
try {
// Build operations and try applying
final ArrayList<ContentProviderOperation> diff = state.buildDiff();
+
if (DEBUG) {
Log.v(TAG, "Content Provider Operations:");
for (ContentProviderOperation operation : diff) {
@@ -393,16 +394,25 @@
}
}
- ContentProviderResult[] results = null;
- if (!diff.isEmpty()) {
- results = resolver.applyBatch(ContactsContract.AUTHORITY, diff);
- if (results == null) {
+ int numberProcessed = 0;
+ boolean batchFailed = false;
+ final ContentProviderResult[] results = new ContentProviderResult[diff.size()];
+ while (numberProcessed < diff.size()) {
+ final int subsetCount = applyDiffSubset(diff, numberProcessed, results, resolver);
+ if (subsetCount == -1) {
Log.w(TAG, "Resolver.applyBatch failed in saveContacts");
- // Retry save
- continue;
+ batchFailed = true;
+ break;
+ } else {
+ numberProcessed += subsetCount;
}
}
+ if (batchFailed) {
+ // Retry save
+ continue;
+ }
+
final long rawContactId = getRawContactId(state, diff, results);
if (rawContactId == -1) {
throw new IllegalStateException("Could not determine RawContact ID after save");
@@ -526,6 +536,29 @@
}
/**
+ * Splits "diff" into subsets based on "MAX_CONTACTS_PROVIDER_BATCH_SIZE", applies each of the
+ * subsets, adds the returned array to "results".
+ *
+ * @return the size of the array, if not null; -1 when the array is null.
+ */
+ private int applyDiffSubset(ArrayList<ContentProviderOperation> diff, int offset,
+ ContentProviderResult[] results, ContentResolver resolver)
+ throws RemoteException, OperationApplicationException {
+ final int subsetCount = Math.min(diff.size() - offset, MAX_CONTACTS_PROVIDER_BATCH_SIZE);
+ final ArrayList<ContentProviderOperation> subset = new ArrayList<>();
+ subset.addAll(diff.subList(offset, offset + subsetCount));
+ final ContentProviderResult[] subsetResult = resolver.applyBatch(ContactsContract
+ .AUTHORITY, subset);
+ if (subsetResult == null || (offset + subsetResult.length) > results.length) {
+ return -1;
+ }
+ for (ContentProviderResult c : subsetResult) {
+ results[offset++] = c;
+ }
+ return subsetResult.length;
+ }
+
+ /**
* Save updated photo for the specified raw-contact.
* @return true for success, false for failure
*/