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

Commit 3a399872 authored by Murillo, Roberto's avatar Murillo, Roberto Committed by Steve Kondik
Browse files

Fix crash when separating multiple empty raw contacts

This changes the back reference logic a little bit to prevent
adding back references where there is nothing to back reference.
This fixes weird cases where a user could hit "new contact" twice
without saving data and then try to separate the two dummy
contacts.

Change-Id: I1a6b4e1a6bda99f5d8ee07ea57cace75a6bed4ab
parent b7770a45
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -130,11 +130,13 @@ public class EntitySet extends ArrayList<EntityDelta> implements Parcelable {
        // Second pass builds actual operations
        for (EntityDelta delta : this) {
            final int firstBatch = diff.size();
            backRefs[rawContactIndex++] = firstBatch;
            final boolean isInsert = delta.isContactInsert();
            backRefs[rawContactIndex++] = isInsert ? firstBatch : -1;

            delta.buildDiff(diff);

            // Only create rules for inserts
            if (!delta.isContactInsert()) continue;
            if (!isInsert) continue;

            // If we are going to split all contacts, there is no point in first combining them
            if (mSplitRawContacts) continue;
@@ -208,18 +210,25 @@ public class EntitySet extends ArrayList<EntityDelta> implements Parcelable {
        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_SEPARATE);

        Long rawContactId1 = get(index1).getValues().getAsLong(RawContacts._ID);
        int backRef1 = backRefs[index1];
        if (rawContactId1 != null && rawContactId1 >= 0) {
            builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1);
        } else if (backRef1 >= 0) {
            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1, backRef1);
        } else {
            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID1, backRefs[index1]);
            return;
        }

        Long rawContactId2 = get(index2).getValues().getAsLong(RawContacts._ID);
        int backRef2 = backRefs[index2];
        if (rawContactId2 != null && rawContactId2 >= 0) {
            builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2);
        } else if (backRef2 >= 0) {
            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, backRef2);
        } else {
            builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, backRefs[index2]);
            return;
        }

        diff.add(builder.build());
    }

+52 −0
Original line number Diff line number Diff line
@@ -358,6 +358,58 @@ public class EntitySetTests extends AndroidTestCase {
        assertEquals("Unexpected exception updates", 2, exceptionCount);
    }

    public void testInsertInsertSeparate() {
        // This assumes getInsert() will return back an "empty" raw
        // contact meaning it will contain no actual information
        final EntityDelta insertFirst = getInsert();
        final EntityDelta insertSecond = getInsert();
        final EntitySet set = buildSet(insertFirst, insertSecond);

        // This would normally build a TYPE_KEEP_SEPARATE aggregation exception,
        // but since the raw contacts won't be added because they are empty,
        // we should get 0 exceptions back
        set.splitRawContacts();

        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
        final int exceptionCount = countExceptionUpdates(diff);
        assertEquals("Unexpected exception updates", 0, exceptionCount);
    }

    public void testUpdateInsertSeparate() {
        // This assumes getInsert() will return back an "empty" raw
        // contact meaning it will contain no actual information
        final EntityDelta update = getUpdate(CONTACT_FIRST);
        final EntityDelta insert = getInsert();
        final EntitySet set = buildSet(update, insert);

        // This would normally build a KEEP_SEPARATE aggregation exception,
        // but since the insert won't be added because it is empty,
        // we should get 0 exceptions back
        set.splitRawContacts();

        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
        final int exceptionCount = countExceptionUpdates(diff);
        assertEquals("Unexpected exception updates", 0, exceptionCount);
    }

    public void testUpdateInsertInsertSeparate() {
        // This assumes getInsert() will return back an "empty" raw
        // contact meaning it will contain no actual information
        final EntityDelta update = getUpdate(CONTACT_FIRST);
        final EntityDelta insertFirst = getInsert();
        final EntityDelta insertSecond = getInsert();
        final EntitySet set = buildSet(update, insertFirst, insertSecond);

        // This would normally build a KEEP_SEPARATE aggregation exception,
        // but since the inserts won't be added because they are empty,
        // we should get 0 exceptions back
        set.splitRawContacts();

        final ArrayList<ContentProviderOperation> diff = set.buildDiff();
        final int exceptionCount = countExceptionUpdates(diff);
        assertEquals("Unexpected exception updates", 0, exceptionCount);
    }

    public void testMergeDataRemoteInsert() {
        final EntitySet first = buildSet(buildBeforeEntity(CONTACT_BOB, VER_FIRST,
                buildPhone(PHONE_RED)));