Ignore new raw contact display names when saving contacts

Now that we have logic to ignore the display name
we add to newly created raw contacts (when the
user wants to edit a read-only contact) when
determining whether the user made any edits,
we can enable changing the display on the compact
editor again.

Note, there is one glitch -- the name disappears
on the compact editor after you click more fields
(but only when editing read-only contacts).

Tested scenarios:

1) Edit read-only contact, more fields, back, back

   No bogus contact is created and the read-only
   name is displayed on both editors.

2) Edit read-only contact, change name on compact
   editor, back, re-edit read-only contact, and split

   The read-only contact is unchanged and a new
   contact with the edited name is created.

3) Edit read-only contact, more fields, change name on
   full editor, back, back, re-edit read-only contact,
   and split

   Same result as (2)

4) Edit read-only contact, add phone on compact
   editor, back, re-edit read-only contact, and split

   The read-only contact is unchanged and a new
   contact with the read-only name and phone number is
   created.

5) Edit read-only contact, more fields, add phone on full
   editor, back, back, re-edit read-only contact, and split

   Same result as (4)

Bug 21858251
Bug 21464081

Change-Id: I9028fee38b8ea7569968654a756eb98025318e69
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index 669e400..49cd2a2 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -137,6 +137,8 @@
 
     private long mPhotoRawContactId;
 
+    private StructuredNameEditorView mDefaultNameEditorView;
+
     public CompactRawContactsEditorView(Context context) {
         super(context);
     }
@@ -233,6 +235,10 @@
         return mPhotoRawContactId;
     }
 
+    public StructuredNameEditorView getDefaultNameEditorView() {
+        return mDefaultNameEditorView;
+    }
+
     public StructuredNameEditorView getStructuredNameEditorView() {
         // We only ever show one StructuredName
         return mNames.getChildCount() == 0
@@ -254,9 +260,13 @@
         return mNames.getChildAt(0).findViewById(R.id.anchor_view);
     }
 
+    /**
+     * @param readOnlyDisplayName The display name to set on the new raw contact created in order
+     *         to edit a read-only contact.
+     */
     public void setState(RawContactDeltaList rawContactDeltas,
-            MaterialColorMapUtils.MaterialPalette materialPalette,
-            ViewIdGenerator viewIdGenerator, long photoId, long nameId) {
+            MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
+            long photoId, long nameId, String readOnlyDisplayName) {
         mNames.removeAllViews();
         mPhoneticNames.removeAllViews();
         mNicknames.removeAllViews();
@@ -275,7 +285,7 @@
 
         vlog("Setting compact editor state from " + rawContactDeltas);
         addPhotoView(rawContactDeltas, viewIdGenerator, photoId);
-        addStructuredNameView(rawContactDeltas, nameId);
+        addStructuredNameView(rawContactDeltas, nameId, readOnlyDisplayName);
         addEditorViews(rawContactDeltas);
         removeExtraEmptyTextFields(mPhoneNumbers);
         removeExtraEmptyTextFields(mEmails);
@@ -364,7 +374,42 @@
         mPhoto.setVisibility(View.GONE);
     }
 
-    private void addStructuredNameView(RawContactDeltaList rawContactDeltas, long nameId) {
+    private void addStructuredNameView(RawContactDeltaList rawContactDeltas, long nameId,
+            String readOnlyDisplayName) {
+        // If we're editing a read-only contact we want to display the name from the read-only
+        // contact in a structured name editor backed by the new raw contact that was created.
+        // The new raw contact is writable and merging it with the read-only contact allows us
+        // to edit the read-only contact. See go/editing-read-only-contacts
+        if (!TextUtils.isEmpty(readOnlyDisplayName)) {
+            for (RawContactDelta rawContactDelta : rawContactDeltas) {
+                if (!rawContactDelta.isVisible()) continue;
+                final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
+
+                // Make sure we have a structured name
+                RawContactModifier.ensureKindExists(
+                        rawContactDelta, accountType, StructuredName.CONTENT_ITEM_TYPE);
+
+                if (accountType.areContactsWritable()) {
+                    for (ValuesDelta valuesDelta : rawContactDelta.getMimeEntries(
+                            StructuredName.CONTENT_ITEM_TYPE)) {
+                        if (valuesDelta != null) {
+                            mNameValuesDelta = valuesDelta;
+                            final NameEditorListener nameEditorListener = new NameEditorListener(
+                                    mNameValuesDelta, rawContactDelta.getRawContactId(), mListener);
+                            final StructuredNameEditorView nameEditorView =
+                                    inflateStructuredNameEditorView(mNames, accountType,
+                                            mNameValuesDelta, rawContactDelta, nameEditorListener,
+                                            !accountType.areContactsWritable());
+                            nameEditorView.setDisplayName(readOnlyDisplayName);
+                            mNames.addView(nameEditorView);
+                            mDefaultNameEditorView = nameEditorView;
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
         // Look for a match for the name ID that was passed in
         for (RawContactDelta rawContactDelta : rawContactDeltas) {
             if (!rawContactDelta.isVisible()) continue;