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

Commit 0653de3d authored by Walter Jang's avatar Walter Jang
Browse files

Apply contact join ops before we reach the max batch op threshold

Splitting the join operations across several batches "could" lead
to some parts of the join being applied and the remaining parts
not applied because of some error.

Our new UX to join more than two contacts also increases the
possibility that the joins take a long time.  This is especially
true when a contact involved in the joined is composed of many
raw contacts since the current contact save logic creates an
operation between every pair of raw contacts.

Bug 22480225

Change-Id: Icab836f587808e018bd59909864dfd9de0d53776
parent 6a42c290
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -142,6 +142,8 @@ public class ContactSaveService extends IntentService {

    private static final int PERSIST_TRIES = 3;

    private static final int MAX_CONTACTS_PROVIDER_BATCH_SIZE = 499;

    public interface Listener {
        public void onServiceCompleted(Intent callbackIntent);
    }
@@ -1078,23 +1080,39 @@ public class ContactSaveService extends IntentService {

        // For each pair of raw contacts, insert an aggregation exception
        final ContentResolver resolver = getContentResolver();
        final ArrayList<ContentProviderOperation> operations
                = new ArrayList<ContentProviderOperation>();
        // The maximum number of operations per batch (aka yield point) is 500. See b/22480225
        final int batchSize = MAX_CONTACTS_PROVIDER_BATCH_SIZE;
        final ArrayList<ContentProviderOperation> operations = new ArrayList<>(batchSize);
        for (int i = 0; i < rawContactIds.length; i++) {
            for (int j = 0; j < rawContactIds.length; j++) {
                if (i != j) {
                    buildJoinContactDiff(operations, rawContactIds[i], rawContactIds[j]);
                }
                // Before we get to 500 we need to flush the operations list
                if (operations.size() > 0 && operations.size() % batchSize == 0) {
                    if (!applyJoinOperations(resolver, operations)) {
                        return;
                    }
                    operations.clear();
                }
            }
        }
        if (operations.size() > 0 && !applyJoinOperations(resolver, operations)) {
            return;
        }
        showToast(R.string.contactsJoinedMessage);
    }

        // Apply all aggregation exceptions as one batch
    /** Returns true if the batch was successfully applied and false otherwise. */
    private boolean applyJoinOperations(ContentResolver resolver,
            ArrayList<ContentProviderOperation> operations) {
        try {
            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
            showToast(R.string.contactsJoinedMessage);
            return true;
        } catch (RemoteException | OperationApplicationException e) {
            Log.e(TAG, "Failed to apply aggregation exception batch", e);
            showToast(R.string.contactSavedErrorToast);
            return false;
        }
    }