Merge "Include data set when getting raw contacts to add to label" into ub-contactsdialer-g-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index becab16..0f9f16e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -300,19 +300,19 @@
     <string name="contactUnlinkedToast">Contacts unlinked</string>
 
     <!-- Toast displayed when saving a contact failed. [CHAR LIMIT=NONE] -->
-    <string name="contactSavedErrorToast">Couldn\'t save contact changes.</string>
+    <string name="contactSavedErrorToast">Couldn\'t save contact changes</string>
 
     <!-- Toast displayed when unlinking a contact failed. [CHAR LIMIT=NONE] -->
-    <string name="contactUnlinkErrorToast">Couldn\'t unlink contact.</string>
+    <string name="contactUnlinkErrorToast">Couldn\'t unlink contact</string>
 
     <!-- Toast displayed when linking a contact failed. [CHAR LIMIT=NONE] -->
-    <string name="contactJoinErrorToast">Couldn\'t link contact.</string>
+    <string name="contactJoinErrorToast">Couldn\'t link contact</string>
 
     <!-- Generic error default clause displayed when saving a contact failed. [CHAR LIMIT=NONE] -->
-    <string name="contactGenericErrorToast">Error saving contact.</string>
+    <string name="contactGenericErrorToast">Error saving contact</string>
 
     <!-- Toast displayed when saving a contact photo failed. [CHAR LIMIT=NONE] -->
-    <string name="contactPhotoSavedErrorToast">Couldn\'t save contact photo changes.</string>
+    <string name="contactPhotoSavedErrorToast">Couldn\'t save contact photo changes</string>
 
     <!-- Toast displayed when something goes wrong while loading a label. [CHAR LIMIT=70] -->
     <string name="groupLoadErrorToast">Failed to load label</string>
@@ -339,7 +339,7 @@
     <string name="groupMembersAddedToast">Added to label</string>
 
     <!-- Toast displayed when saving a label failed [CHAR LIMIT=70] -->
-    <string name="groupSavedErrorToast">Couldn\'t save label changes.</string>
+    <string name="groupSavedErrorToast">Couldn\'t save label changes</string>
 
     <!-- Message displayed when creating a group with the same name as an existing group -->
     <string name="groupExistsErrorMessage">That label already exists</string>
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index b34f384..c514a45 100755
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -1359,17 +1359,26 @@
             return;
         }
 
-        if (receiver != null) {
-            final Bundle result = new Bundle();
-            result.putSerializable(EXTRA_RAW_CONTACT_IDS, separatedRawContactIds);
-            result.putString(EXTRA_DISPLAY_NAME, queryNameOfLinkedContacts(contactIds));
-            receiver.send(CONTACTS_LINKED, result);
+
+        final String name = queryNameOfLinkedContacts(contactIds);
+        if (name != null) {
+            if (receiver != null) {
+                final Bundle result = new Bundle();
+                result.putSerializable(EXTRA_RAW_CONTACT_IDS, separatedRawContactIds);
+                result.putString(EXTRA_DISPLAY_NAME, name);
+                receiver.send(CONTACTS_LINKED, result);
+            } else {
+                showToast(R.string.contactsJoinedMessage);
+            }
         } else {
-            showToast(R.string.contactsJoinedMessage);
+            if (receiver != null) {
+                receiver.send(CP2_ERROR, new Bundle());
+            }
+            showToast(R.string.contactJoinErrorToast);
         }
     }
 
-    // Get the display name of the top-level contact after the contacts have been linked.
+    /** Get the display name of the top-level contact after the contacts have been linked. */
     private String queryNameOfLinkedContacts(long[] contactIds) {
         final StringBuilder whereBuilder = new StringBuilder(Contacts._ID).append(" IN (");
         final String[] whereArgs = new String[contactIds.length];
@@ -1379,23 +1388,41 @@
         }
         whereBuilder.deleteCharAt(whereBuilder.length() - 1).append(')');
         final Cursor cursor = getContentResolver().query(Contacts.CONTENT_URI,
-                new String[]{Contacts.DISPLAY_NAME}, whereBuilder.toString(), whereArgs, null);
+                new String[]{Contacts._ID, Contacts.DISPLAY_NAME},
+                whereBuilder.toString(), whereArgs, null);
+
+        String name = null;
+        long contactId = 0;
         try {
             if (cursor.moveToFirst()) {
-                return cursor.getString(0);
+                contactId = cursor.getLong(0);
+                name = cursor.getString(1);
             }
-            return null;
+            while(cursor.moveToNext()) {
+                if (cursor.getLong(0) != contactId) {
+                    return null;
+                }
+            }
+            return name == null ? "" : name;
         } finally {
-            cursor.close();
+            if (cursor != null) {
+                cursor.close();
+            }
         }
     }
 
-
     /** Returns true if the batch was successfully applied and false otherwise. */
     private boolean applyOperations(ContentResolver resolver,
             ArrayList<ContentProviderOperation> operations) {
         try {
-            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
+            final ContentProviderResult[] result =
+                    resolver.applyBatch(ContactsContract.AUTHORITY, operations);
+            for (int i = 0; i < result.length; ++i) {
+                // if no rows were modified in the operation then we count it as fail.
+                if (result[i].count < 0) {
+                    throw new OperationApplicationException();
+                }
+            }
             return true;
         } catch (RemoteException | OperationApplicationException e) {
             Log.e(TAG, "Failed to apply aggregation exception batch", e);
@@ -1460,19 +1487,12 @@
             operations.add(builder.build());
         }
 
-        boolean success = false;
         // Apply all aggregation exceptions as one batch
-        try {
-            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
-            showToast(R.string.contactsJoinedMessage);
-            success = true;
-        } catch (RemoteException | OperationApplicationException e) {
-            Log.e(TAG, "Failed to apply aggregation exception batch", e);
-            showToast(R.string.contactSavedErrorToast);
-        }
+        final boolean success = applyOperations(resolver, operations);
 
+        final String name = queryNameOfLinkedContacts(new long[] {contactId1, contactId2});
         Intent callbackIntent = intent.getParcelableExtra(EXTRA_CALLBACK_INTENT);
-        if (success) {
+        if (success && name != null) {
             Uri uri = RawContacts.getContactLookupUri(resolver,
                     ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactIds[0]));
             callbackIntent.setData(uri);