Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccdf69cb authored by Wenyi Wang's avatar Wenyi Wang
Browse files

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
parent 0d9c24b7
Loading
Loading
Loading
Loading
+40 −7
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@ import com.android.contacts.common.model.RawContactDeltaList;
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 @@ public class ContactSaveService extends IntentService {
        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 @@ public class ContactSaveService extends IntentService {
            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,15 +394,24 @@ public class ContactSaveService extends IntentService {
                    }
                }

                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");
                        batchFailed = true;
                        break;
                    } else {
                        numberProcessed += subsetCount;
                    }
                }

                if (batchFailed) {
                    // Retry save
                    continue;
                }
                }

                final long rawContactId = getRawContactId(state, diff, results);
                if (rawContactId == -1) {
@@ -525,6 +535,29 @@ public class ContactSaveService extends IntentService {
        }
    }

    /**
     * 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