am 3e5ae0db: Show all aggreagate contact names on the editor

* commit '3e5ae0db65e842d49d047568fb5d6f331298da32':
  Show all aggreagate contact names on the editor
diff --git a/res/layout/account_type_info.xml b/res/layout/account_type_info.xml
new file mode 100644
index 0000000..64e553c
--- /dev/null
+++ b/res/layout/account_type_info.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2015 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/account_type"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:visibility="gone">
+
+    <ImageView
+            android:id="@+id/account_type_icon"
+            style="@style/AccountTypeIconStyle" />
+
+    <TextView
+            android:id="@+id/account_type_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/AccountTypeNameStyle" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/compact_contact_editor_fields.xml b/res/layout/compact_contact_editor_fields.xml
index c2c2c64..710ba94 100644
--- a/res/layout/compact_contact_editor_fields.xml
+++ b/res/layout/compact_contact_editor_fields.xml
@@ -18,13 +18,6 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
 
     <LinearLayout
-            android:id="@+id/names"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/editor_compact_first_field_padding"
-            android:orientation="vertical"/>
-
-    <LinearLayout
             android:id="@+id/kind_section_views"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/res/layout/structured_name_editor_view.xml b/res/layout/structured_name_editor_view.xml
index 2b0ee7b..2984104 100644
--- a/res/layout/structured_name_editor_view.xml
+++ b/res/layout/structured_name_editor_view.xml
@@ -19,35 +19,44 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="@dimen/editor_min_line_item_height"
-    android:orientation="horizontal">
+    android:orientation="vertical">
 
-    <!-- This isn't used in StructuredNameEditorView. It is only included so that
-        StructuredNameEditorView's base classes don't need extra null checks. -->
-    <include
-        android:id="@+id/spinner"
-        layout="@layout/edit_spinner"
-        android:visibility="gone" />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="@dimen/editor_min_line_item_height"
+        android:orientation="horizontal">
 
-    <ImageView
-        android:id="@+id/kind_icon"
-        android:src="@drawable/ic_person_black_24dp"
-        android:contentDescription="@string/header_name_entry"
-        style="@style/EditKindIconStyle" />
+        <!-- This isn't used in StructuredNameEditorView. It is only included so that
+            StructuredNameEditorView's base classes don't need extra null checks. -->
+        <include
+            android:id="@+id/spinner"
+            layout="@layout/edit_spinner"
+            android:visibility="gone" />
 
-    <include
-        layout="@layout/edit_field_list_with_anchor_view" />
+        <ImageView
+            android:id="@+id/kind_icon"
+            android:src="@drawable/ic_person_black_24dp"
+            android:contentDescription="@string/header_name_entry"
+            style="@style/EditKindIconStyle" />
 
-    <include
-        android:id="@+id/expansion_view_container"
-        layout="@layout/name_edit_expansion_view"
-        android:visibility="gone" />
+        <include
+            layout="@layout/edit_field_list_with_anchor_view" />
 
-    <!-- This isn't used in StructuredNameEditorView. It is only included so that
-        StructuredNameEditorView's base classes don't need extra null checks. -->
-    <include
-        android:id="@+id/delete_button_container"
-        layout="@layout/edit_delete_button"
-        android:visibility="gone" />
+        <include
+            android:id="@+id/expansion_view_container"
+            layout="@layout/name_edit_expansion_view"
+            android:visibility="gone" />
+
+        <!-- This isn't used in StructuredNameEditorView. It is only included so that
+            StructuredNameEditorView's base classes don't need extra null checks. -->
+        <include
+            android:id="@+id/delete_button_container"
+            layout="@layout/edit_delete_button"
+            android:visibility="gone" />
+
+    </LinearLayout>
+
+    <include layout="@layout/account_type_info"/>
 
 </com.android.contacts.editor.StructuredNameEditorView>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8fce0f1..66ddac6 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -325,4 +325,17 @@
         <item name="android:layout_marginEnd">28dp</item>
         <item name="android:layout_marginTop">@dimen/editor_kind_icon_top_margin</item>
     </style>
+
+    <style name="AccountTypeIconStyle">
+        <item name="android:layout_width">12dp</item>
+        <item name="android:layout_height">12dp</item>
+        <item name="android:layout_marginStart">2dp</item>
+        <item name="android:layout_marginEnd">4dp</item>
+    </style>
+
+    <style name="AccountTypeNameStyle">
+        <item name="android:textSize">10sp</item>
+        <item name="android:textColor">#363636</item>
+        <item name="android:fontFamily">sans-serif</item>
+    </style>
 </resources>
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index 53bfce0..fd45906 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -449,8 +449,7 @@
             } else {
                 // Otherwise launch the full contact editor.
                 startActivityAndForwardResult(EditorIntents.createEditContactIntent(
-                        contactLookupUri, /* materialPalette =*/ null, /* photoId =*/ -1,
-                        /* nameId =*/ -1));
+                        contactLookupUri, /* materialPalette =*/ null, /* photoId =*/ -1));
             }
         }
 
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index 9b79e7a..e7128a4 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -208,11 +208,8 @@
         // Add input fields for the loaded Contact
         final CompactRawContactsEditorView editorView = getContent();
         editorView.setListener(this);
-        editorView.setState(mState, getMaterialPalette(), mViewIdGenerator, mPhotoId, mNameId,
-                mReadOnlyDisplayName, mHasNewContact, mIsUserProfile, mAccountWithDataSet);
-        if (mReadOnlyDisplayName != null) {
-            mReadOnlyNameEditorView = editorView.getDefaultNameEditorView();
-        }
+        editorView.setState(mState, getMaterialPalette(), mViewIdGenerator, mPhotoId,
+                mHasNewContact, mIsUserProfile, mAccountWithDataSet);
 
         // Set up the photo widget
         mPhotoHandler = createPhotoHandler();
diff --git a/src/com/android/contacts/editor/CompactKindSectionView.java b/src/com/android/contacts/editor/CompactKindSectionView.java
index 827eb58..8959c18 100644
--- a/src/com/android/contacts/editor/CompactKindSectionView.java
+++ b/src/com/android/contacts/editor/CompactKindSectionView.java
@@ -17,6 +17,7 @@
 package com.android.contacts.editor;
 
 import android.content.Context;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -29,10 +30,13 @@
 import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.common.model.ValuesDelta;
+import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.android.contacts.editor.Editor.EditorListener;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 /**
@@ -40,19 +44,82 @@
  */
 public class CompactKindSectionView extends LinearLayout implements EditorListener {
 
+    /** Sorts google account types before others. */
+    private static final class KindSectionComparator implements Comparator<KindSectionData> {
+
+        private RawContactDeltaComparator mRawContactDeltaComparator;
+
+        private KindSectionComparator(Context context) {
+            mRawContactDeltaComparator = new RawContactDeltaComparator(context);
+        }
+
+        @Override
+        public int compare(KindSectionData kindSectionData1, KindSectionData kindSectionData2) {
+            if (kindSectionData1 == kindSectionData2) return 0;
+            if (kindSectionData1 == null) return -1;
+            if (kindSectionData2 == null) return 1;
+
+            return mRawContactDeltaComparator.compare(kindSectionData1.getRawContactDelta(),
+                    kindSectionData2.getRawContactDelta());
+        }
+    }
+
+    /**
+     * Marks a name as super primary when it is changed.
+     *
+     * This is for the case when two or more raw contacts with names are joined where neither is
+     * marked as super primary.  If the user hits back (which causes a save) after changing the
+     * name that was arbitrarily displayed, we want that to be the name that is used.
+     *
+     * Should only be set when a super primary name does not already exist since we only show
+     * one name field.
+     */
+    static final class NameEditorListener implements Editor.EditorListener {
+
+        private final ValuesDelta mValuesDelta;
+        private final long mRawContactId;
+        private final CompactRawContactsEditorView.Listener mListener;
+
+        public NameEditorListener(ValuesDelta valuesDelta, long rawContactId,
+                CompactRawContactsEditorView.Listener listener) {
+            mValuesDelta = valuesDelta;
+            mRawContactId = rawContactId;
+            mListener = listener;
+        }
+
+        @Override
+        public void onRequest(int request) {
+            if (request == Editor.EditorListener.FIELD_CHANGED) {
+                mValuesDelta.setSuperPrimary(true);
+                if (mListener != null) {
+                    mListener.onNameFieldChanged(mRawContactId, mValuesDelta);
+                }
+            } else if (request == Editor.EditorListener.FIELD_TURNED_EMPTY) {
+                mValuesDelta.setSuperPrimary(false);
+            }
+        }
+
+        @Override
+        public void onDeleteRequested(Editor editor) {
+        }
+    }
+
     private ViewGroup mEditors;
     private ImageView mIcon;
 
     private List<KindSectionData> mKindSectionDatas;
     private boolean mReadOnly;
+    private ViewIdGenerator mViewIdGenerator;
+    private CompactRawContactsEditorView.Listener mListener;
+    private String mMimeType;
+
     private boolean mShowOneEmptyEditor = false;
     private boolean mHideIfEmpty = true;
 
-    private ViewIdGenerator mViewIdGenerator;
     private LayoutInflater mInflater;
 
     public CompactKindSectionView(Context context) {
-        this(context, /** attrs =*/ null);
+        this(context, /* attrs =*/ null);
     }
 
     public CompactKindSectionView(Context context, AttributeSet attrs) {
@@ -121,10 +188,12 @@
     }
 
     public void setState(List<KindSectionData> kindSectionDatas, boolean readOnly,
-            ViewIdGenerator viewIdGenerator) {
+            ViewIdGenerator viewIdGenerator, CompactRawContactsEditorView.Listener listener) {
         mKindSectionDatas = kindSectionDatas;
+        Collections.sort(mKindSectionDatas, new KindSectionComparator(getContext()));
         mReadOnly = readOnly;
         mViewIdGenerator = viewIdGenerator;
+        mListener = listener;
 
         // Set the icon using the first DataKind (all DataKinds should be the same type)
         final DataKind dataKind = mKindSectionDatas.isEmpty()
@@ -135,6 +204,7 @@
             mIcon.setImageDrawable(EditorUiUtils.getMimeTypeDrawable(getContext(),
                     dataKind.mimeType));
             if (mIcon.getDrawable() == null) mIcon.setContentDescription(null);
+            mMimeType = dataKind.mimeType;
         }
 
         rebuildFromState();
@@ -145,7 +215,6 @@
      * Build editors for all current rows.
      */
     private void rebuildFromState() {
-        // Remove any existing editors
         mEditors.removeAllViews();
 
         // Check if we are displaying anything here
@@ -156,13 +225,16 @@
                 break;
             }
         }
+        if (!hasValuesDeltas) return;
 
-        if (hasValuesDeltas) {
-            for (KindSectionData kindSectionData : mKindSectionDatas) {
+        for (KindSectionData kindSectionData : mKindSectionDatas) {
+            if (StructuredName.CONTENT_ITEM_TYPE.equals(kindSectionData.getDataKind().mimeType)) {
                 for (ValuesDelta valuesDelta : kindSectionData.getValuesDeltas()) {
-                    // Skip entries that aren't visible
-                    if (!valuesDelta.isVisible()) continue;
-                    if (isUnchanged(kindSectionData.getDataKind(), valuesDelta)) continue;
+                    createStructuredNameEditorView(kindSectionData.getAccountType(),
+                            valuesDelta, kindSectionData.getRawContactDelta());
+                }
+            } else {
+                for (ValuesDelta valuesDelta : kindSectionData.getValuesDeltas()) {
                     createEditorView(kindSectionData.getRawContactDelta(),
                             kindSectionData.getDataKind(), valuesDelta);
                 }
@@ -170,13 +242,30 @@
         }
     }
 
+    private void createStructuredNameEditorView(AccountType accountType,
+            ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
+        final StructuredNameEditorView view = (StructuredNameEditorView) mInflater.inflate(
+                R.layout.structured_name_editor_view, mEditors, /* attachToRoot =*/ false);
+        view.setEditorListener(new NameEditorListener(valuesDelta,
+                rawContactDelta.getRawContactId(), mListener));
+        view.findViewById(R.id.kind_icon).setVisibility(View.GONE);
+        view.setDeletable(false);
+        final boolean readOnly = !accountType.areContactsWritable();
+        view.setValues(accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME),
+                valuesDelta, rawContactDelta, readOnly, mViewIdGenerator);
+        if (readOnly) {
+            view.setAccountType(accountType);
+        }
+        mEditors.addView(view);
+    }
+
     /**
      * Creates an EditorView for the given values delta. This function must be used while
      * constructing the views corresponding to the the object-model. The resulting EditorView is
      * also added to the end of mEditors
      */
     private View createEditorView(RawContactDelta rawContactDelta, DataKind dataKind,
-            ValuesDelta entry) {
+            ValuesDelta valuesDelta) {
         // Inflate the layout
         final View view;
         final int layoutResId = EditorUiUtils.getLayoutResourceId(dataKind.mimeType);
@@ -204,30 +293,17 @@
         view.setEnabled(isEnabled());
 
         if (view instanceof Editor) {
-            Editor editor = (Editor) view;
+            final Editor editor = (Editor) view;
             editor.setDeletable(true);
-            editor.setValues(dataKind, entry, rawContactDelta, !dataKind.editable, mViewIdGenerator);
             editor.setEditorListener(this);
+            editor.setValues(dataKind, valuesDelta, rawContactDelta, !dataKind.editable,
+                    mViewIdGenerator);
         }
         mEditors.addView(view);
         return view;
     }
 
     /**
-     * Whether the given values delta has no changes (i.e. it exists in the database but is empty).
-     */
-    private static boolean isUnchanged(DataKind dataKind, ValuesDelta item) {
-        if (!item.isNoop()) return false;
-        final int fieldCount = dataKind.fieldList == null ? 0 : dataKind.fieldList.size();
-        for (int i = 0; i < fieldCount; i++) {
-            final String column = dataKind.fieldList.get(i).column;
-            final String value = item.getAsString(column);
-            if (!TextUtils.isEmpty(value)) return false;
-        }
-        return true;
-    }
-
-    /**
      * Updates the editors being displayed to the user removing extra empty
      * {@link Editor}s, so there is only max 1 empty {@link Editor} view at a time.
      * If there is only 1 empty editor and {@link #setHideWhenEmpty} was set to true,
@@ -313,10 +389,9 @@
     }
 
     /**
-     * Returns the editor View at the given index.
+     * Returns the mime type the kind being edited in this section.
      */
-    public View getEditorView(int index) {
-        return mEditors == null || mEditors.getChildCount() == 0 || mEditors.getChildCount() > index
-                ? null : mEditors.getChildAt(index);
+    public String getMimeType() {
+        return mMimeType;
     }
 }
diff --git a/src/com/android/contacts/editor/CompactPhotoEditorView.java b/src/com/android/contacts/editor/CompactPhotoEditorView.java
index 5f3e9af..783e044 100644
--- a/src/com/android/contacts/editor/CompactPhotoEditorView.java
+++ b/src/com/android/contacts/editor/CompactPhotoEditorView.java
@@ -138,7 +138,7 @@
      * RawContactDelta underlying this view is not modified in any way.  Using this method allows
      * you to show one photo (from a read-only contact, for example) and yet have a different
      * raw contact updated when a new photo is set (from the new raw contact created and attached
-     * to the read-only contact). See go/editing-read-only-contacts
+     * to the read-only contact).
      */
     public void setPhoto(ValuesDelta valuesDelta) {
         if (valuesDelta == null) {
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index bf8a29c..8f268b4 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -101,46 +101,6 @@
                 AccountWithDataSet oldAccount, AccountWithDataSet newAccount);
     }
 
-    /**
-     * Marks a name as super primary when it is changed.
-     *
-     * This is for the case when two or more raw contacts with names are joined where neither is
-     * marked as super primary.  If the user hits back (which causes a save) after changing the
-     * name that was arbitrarily displayed, we want that to be the name that is used.
-     *
-     * Should only be set when a super primary name does not already exist since we only show
-     * one name field.
-     */
-    static final class NameEditorListener implements Editor.EditorListener {
-
-        private final ValuesDelta mValuesDelta;
-        private final long mRawContactId;
-        private final Listener mListener;
-
-        public NameEditorListener(ValuesDelta valuesDelta, long rawContactId,
-                Listener listener) {
-            mValuesDelta = valuesDelta;
-            mRawContactId = rawContactId;
-            mListener = listener;
-        }
-
-        @Override
-        public void onRequest(int request) {
-            if (request == Editor.EditorListener.FIELD_CHANGED) {
-                mValuesDelta.setSuperPrimary(true);
-                if (mListener != null) {
-                    mListener.onNameFieldChanged(mRawContactId, mValuesDelta);
-                }
-            } else if (request == Editor.EditorListener.FIELD_TURNED_EMPTY) {
-                mValuesDelta.setSuperPrimary(false);
-            }
-        }
-
-        @Override
-        public void onDeleteRequested(Editor editor) {
-        }
-    }
-
     /** Used to sort kind sections. */
     private static final class MimeTypeComparator implements
             Comparator<Map.Entry<String,List<KindSectionData>>> {
@@ -189,8 +149,7 @@
         }
     }
 
-
-    private Listener mListener;
+    private CompactRawContactsEditorView.Listener mListener;
 
     private AccountTypeManager mAccountTypeManager;
     private LayoutInflater mLayoutInflater;
@@ -198,8 +157,6 @@
     private ViewIdGenerator mViewIdGenerator;
     private MaterialColorMapUtils.MaterialPalette mMaterialPalette;
     private long mPhotoId;
-    private long mNameId;
-    private String mReadOnlyDisplayName;
     private boolean mHasNewContact;
     private boolean mIsUserProfile;
     private AccountWithDataSet mPrimaryAccount;
@@ -217,21 +174,12 @@
     private TextView mAccountSelectorType;
     private TextView mAccountSelectorName;
 
-    private CompactPhotoEditorView mPhoto;
-    private ViewGroup mNames;
+    private CompactPhotoEditorView mPhotoView;
     private ViewGroup mKindSectionViews;
-    // Map of mime types to KindSectionViews
-    private Map<String,LinearLayout> mKindSectionViewsMap = new HashMap<>();
     private View mMoreFields;
 
-    // The ValuesDelta for the non super primary name that was displayed to the user.
-    private ValuesDelta mNameValuesDelta;
-
     private long mPhotoRawContactId;
 
-    private boolean mUsingDefaultNameEditorView;
-    private StructuredNameEditorView mDefaultNameEditorView;
-
     public CompactRawContactsEditorView(Context context) {
         super(context);
     }
@@ -266,8 +214,7 @@
         mAccountSelectorType = (TextView) findViewById(R.id.account_type_selector);
         mAccountSelectorName = (TextView) findViewById(R.id.account_name_selector);
 
-        mPhoto = (CompactPhotoEditorView) findViewById(R.id.photo_editor);
-        mNames = (LinearLayout) findViewById(R.id.names);
+        mPhotoView = (CompactPhotoEditorView) findViewById(R.id.photo_editor);
         mKindSectionViews = (LinearLayout) findViewById(R.id.kind_section_views);
         mMoreFields = findViewById(R.id.more_fields);
         mMoreFields.setOnClickListener(this);
@@ -281,7 +228,10 @@
                 final CompactKindSectionView kindSectionView =
                         (CompactKindSectionView) mKindSectionViews.getChildAt(i);
                 kindSectionView.setHideWhenEmpty(false);
-                kindSectionView.setShowOneEmptyEditor(true);
+                // Prevent the user from adding new names
+                if (!StructuredName.CONTENT_ITEM_TYPE.equals(kindSectionView.getMimeType())) {
+                    kindSectionView.setShowOneEmptyEditor(true);
+                }
                 kindSectionView.updateEmptyEditors(/* shouldAnimate =*/ false);
             }
 
@@ -292,16 +242,9 @@
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
-        setEnabled(enabled, mNames);
-        setEnabled(enabled, mKindSectionViews);
-    }
-
-    private void setEnabled(boolean enabled, ViewGroup viewGroup) {
-        if (viewGroup != null) {
-            final int childCount = viewGroup.getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                viewGroup.getChildAt(i).setEnabled(enabled);
-            }
+        final int childCount = mKindSectionViews.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            mKindSectionViews.getChildAt(i).setEnabled(enabled);
         }
     }
 
@@ -309,28 +252,28 @@
      * Pass through to {@link CompactPhotoEditorView#setPhotoHandler}.
      */
     public void setPhotoHandler(PhotoHandler photoHandler) {
-        mPhoto.setPhotoHandler(photoHandler);
+        mPhotoView.setPhotoHandler(photoHandler);
     }
 
     /**
      * Pass through to {@link CompactPhotoEditorView#setPhoto}.
      */
     public void setPhoto(Bitmap bitmap) {
-        mPhoto.setPhoto(bitmap);
+        mPhotoView.setPhoto(bitmap);
     }
 
     /**
      * Pass through to {@link CompactPhotoEditorView#setFullSizedPhoto(Uri)}.
      */
     public void setFullSizePhoto(Uri photoUri) {
-        mPhoto.setFullSizedPhoto(photoUri);
+        mPhotoView.setFullSizedPhoto(photoUri);
     }
 
     /**
      * Pass through to {@link CompactPhotoEditorView#isWritablePhotoSet}.
      */
     public boolean isWritablePhotoSet() {
-        return mPhoto.isWritablePhotoSet();
+        return mPhotoView.isWritablePhotoSet();
     }
 
     /**
@@ -340,45 +283,31 @@
         return mPhotoRawContactId;
     }
 
-    public StructuredNameEditorView getDefaultNameEditorView() {
-        return mDefaultNameEditorView;
-    }
-
     public View getAggregationAnchorView() {
-        // Since there is only one structured name we can just return it as the anchor for
-        // the aggregation suggestions popup
-        if (mNames.getChildCount() == 0) {
-            return null;
+        // TODO: since there may be more than one structured name now we should return the one
+        // being edited instead of just the first one.
+        for (int i = 0; i < mKindSectionViews.getChildCount(); i++) {
+            final CompactKindSectionView kindSectionView =
+                    (CompactKindSectionView) mKindSectionViews.getChildAt(i);
+            if (!StructuredName.CONTENT_ITEM_TYPE.equals(kindSectionView.getMimeType())) {
+                return kindSectionView.findViewById(R.id.anchor_view);
+            }
         }
-        return mNames.getChildAt(0).findViewById(R.id.anchor_view);
+        return null;
     }
 
-    /**
-     * @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, String readOnlyDisplayName, boolean hasNewContact,
-            boolean isUserProfile, AccountWithDataSet primaryAccount) {
+            long photoId, boolean hasNewContact, boolean isUserProfile,
+            AccountWithDataSet primaryAccount) {
+        // Clear previous state and reset views
         mKindSectionDataMap.clear();
-
-        mNames.removeAllViews();
         mKindSectionViews.removeAllViews();
-        mKindSectionViewsMap.clear();
         mMoreFields.setVisibility(View.VISIBLE);
 
-        if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
-            return;
-        }
-
-        mViewIdGenerator = viewIdGenerator;
-        setId(mViewIdGenerator.getId(rawContactDeltas.get(0), /* dataKind =*/ null,
-                /* valuesDelta =*/ null, ViewIdGenerator.NO_VIEW_INDEX));
         mMaterialPalette = materialPalette;
+        mViewIdGenerator = viewIdGenerator;
         mPhotoId = photoId;
-        mNameId = nameId;
-        mReadOnlyDisplayName = readOnlyDisplayName;
         mHasNewContact = hasNewContact;
         mIsUserProfile = isUserProfile;
         mPrimaryAccount = primaryAccount;
@@ -387,48 +316,36 @@
         }
         vlog("state: primary " + mPrimaryAccount);
 
-
-        vlog("state: setting editor state from " + rawContactDeltas.size() + " RawContactDelta(s)");
-        parseRawContactDeltas(rawContactDeltas);
-        if (mKindSectionDataMap == null || mKindSectionDataMap.isEmpty()) {
-            elog("No kind section data parsed from raw contact deltas");
+        // Parse the given raw contact deltas
+        if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
+            elog("No raw contact deltas");
             return;
         }
+        vlog("state: setting state from " + rawContactDeltas.size() + " RawContactDelta(s)");
+        parseRawContactDeltas(rawContactDeltas);
+        if (mKindSectionDataMap == null || mKindSectionDataMap.isEmpty()) {
+            elog("No kind section data parsed from RawContactDelta(s)");
+            return;
+        }
+
+        // Setup the view
+        setId(mViewIdGenerator.getId(rawContactDeltas.get(0), /* dataKind =*/ null,
+                /* valuesDelta =*/ null, ViewIdGenerator.NO_VIEW_INDEX));
         addAccountInfo();
         addPhotoView();
-        addNameView();
         addKindSectionViews();
-
         updateMoreFieldsButton();
     }
 
     private void parseRawContactDeltas(RawContactDeltaList rawContactDeltas) {
-        // Get the raw contact delta for the primary account (the one displayed at the top)
-        if (mPrimaryAccount == null || TextUtils.isEmpty(mPrimaryAccount.name)
-                || !TextUtils.isEmpty(mReadOnlyDisplayName)) {
-            // Use the first writable contact if this is an insert for a read-only contact.
-            // In this case we can assume the first writable raw contact is the newly created one
-            // because inserts have a raw contact delta list of size 1 and read-only contacts have
-            // a list of size 2.
-            for (RawContactDelta rawContactDelta : rawContactDeltas) {
-                if (!rawContactDelta.isVisible()) continue;
-                final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
-                if (accountType != null && accountType.areContactsWritable()) {
-                    vlog("parse: using first writable raw contact as primary");
-                    mPrimaryRawContactDelta = rawContactDelta;
-                    break;
-                }
-            }
-        } else {
+        if (mPrimaryAccount != null) {
             // Use the first writable contact that matches the primary account
             for (RawContactDelta rawContactDelta : rawContactDeltas) {
                 if (!rawContactDelta.isVisible()) continue;
                 final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
-                if (accountType != null && accountType.areContactsWritable()
-                        && Objects.equals(mPrimaryAccount.name, rawContactDelta.getAccountName())
-                        && Objects.equals(mPrimaryAccount.type, rawContactDelta.getAccountType())
-                        && Objects.equals(mPrimaryAccount.dataSet, rawContactDelta.getDataSet())) {
-                    vlog("parse: matched the primary account raw contact");
+                if (accountType == null || !accountType.areContactsWritable()) continue;
+                if (matchesPrimaryAccount(rawContactDelta)) {
+                    vlog("parse: matched primary account raw contact");
                     mPrimaryRawContactDelta = rawContactDelta;
                     break;
                 }
@@ -446,18 +363,20 @@
                 }
             }
         }
+        if (mPrimaryRawContactDelta != null) {
+            RawContactModifier.ensureKindExists(mPrimaryRawContactDelta,
+                    mPrimaryRawContactDelta.getAccountType(mAccountTypeManager),
+                    StructuredName.CONTENT_ITEM_TYPE);
 
-        RawContactModifier.ensureKindExists(mPrimaryRawContactDelta,
-                mPrimaryRawContactDelta.getAccountType(mAccountTypeManager),
-                StructuredName.CONTENT_ITEM_TYPE);
-
-        RawContactModifier.ensureKindExists(mPrimaryRawContactDelta,
-                mPrimaryRawContactDelta.getAccountType(mAccountTypeManager),
-                Photo.CONTENT_ITEM_TYPE);
+            RawContactModifier.ensureKindExists(mPrimaryRawContactDelta,
+                    mPrimaryRawContactDelta.getAccountType(mAccountTypeManager),
+                    Photo.CONTENT_ITEM_TYPE);
+        }
 
         // Build the kind section data list map
         for (RawContactDelta rawContactDelta : rawContactDeltas) {
             if (rawContactDelta == null || !rawContactDelta.isVisible()) continue;
+            vlog("parse: " + rawContactDelta);
             final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
             if (accountType == null) continue;
             final List<DataKind> dataKinds = accountType.getSortedDataKinds();
@@ -465,25 +384,35 @@
             vlog("parse: " + dataKindSize + " dataKinds(s)");
             for (int i = 0; i < dataKindSize; i++) {
                 final DataKind dataKind = dataKinds.get(i);
-                // Don't show read only values
                 if (dataKind == null || !dataKind.editable) continue;
-                // Get the kind section data list to add the new field to
-                List<KindSectionData> kindSectionDataList =
-                        mKindSectionDataMap.get(dataKind.mimeType);
-                if (kindSectionDataList == null) {
-                    kindSectionDataList = new ArrayList<>();
-                    mKindSectionDataMap.put(dataKind.mimeType, kindSectionDataList);
-                }
+                final List<KindSectionData> kindSectionDataList =
+                        getKindSectionDataList(dataKind.mimeType);
                 final KindSectionData kindSectionData =
                         new KindSectionData(accountType, dataKind, rawContactDelta);
                 kindSectionDataList.add(kindSectionData);
                 vlog("parse: " + i + " " + dataKind.mimeType + " " +
                         (kindSectionData.hasValuesDeltas()
-                                ? kindSectionData.getValuesDeltas().size() : null) + " value(s)");
+                                ? kindSectionData.getValuesDeltas().size() : 0) + " value(s)");
             }
         }
     }
 
+    private List<KindSectionData> getKindSectionDataList(String mimeType) {
+        List<KindSectionData> kindSectionDataList = mKindSectionDataMap.get(mimeType);
+        if (kindSectionDataList == null) {
+            kindSectionDataList = new ArrayList<>();
+            mKindSectionDataMap.put(mimeType, kindSectionDataList);
+        }
+        return kindSectionDataList;
+    }
+
+    /** Whether the given RawContactDelta is from the primary account. */
+    private boolean matchesPrimaryAccount(RawContactDelta rawContactDelta) {
+        return Objects.equals(mPrimaryAccount.name, rawContactDelta.getAccountName())
+                && Objects.equals(mPrimaryAccount.type, rawContactDelta.getAccountType())
+                && Objects.equals(mPrimaryAccount.dataSet, rawContactDelta.getDataSet());
+    }
+
     private void addAccountInfo() {
         if (mPrimaryRawContactDelta == null) {
             mAccountHeaderContainer.setVisibility(View.GONE);
@@ -574,10 +503,9 @@
 
     private void addPhotoView() {
         // Get the kind section data and values delta that will back the photo view
-        final String mimeType = Photo.CONTENT_ITEM_TYPE;
-        Pair<KindSectionData,ValuesDelta> pair = getPrimaryKindSectionData(mimeType, mPhotoId);
+        Pair<KindSectionData,ValuesDelta> pair = getPrimaryKindSectionData(mPhotoId);
         if (pair == null) {
-            wlog(mimeType + ": no kind section data parsed");
+            wlog("photo: no kind section data parsed");
             return;
         }
         final KindSectionData kindSectionData = pair.first;
@@ -586,62 +514,23 @@
         // If we're editing a read-only contact we want to display the photo from the
         // read-only contact in a photo editor backed by the new raw contact
         // that was created. The new raw contact is the first writable one.
-        // See go/editing-read-only-contacts
-        if (mReadOnlyDisplayName != null) {
-            mPhotoRawContactId = mPrimaryRawContactDelta.getRawContactId();
+        if (mHasNewContact) {
+            mPhotoRawContactId = mPrimaryRawContactDelta == null
+                    ? null : mPrimaryRawContactDelta.getRawContactId();
         }
 
         mPhotoRawContactId = kindSectionData.getRawContactDelta().getRawContactId();
-        mPhoto.setValues(kindSectionData.getDataKind(), valuesDelta,
+        mPhotoView.setValues(kindSectionData.getDataKind(), valuesDelta,
                 kindSectionData.getRawContactDelta(),
                 !kindSectionData.getAccountType().areContactsWritable(), mMaterialPalette,
                 mViewIdGenerator);
     }
 
-    private void addNameView() {
-        // Get the kind section data and values delta that will back the photo view
-        final String mimeType = StructuredName.CONTENT_ITEM_TYPE;
-        Pair<KindSectionData,ValuesDelta> pair = getPrimaryKindSectionData(mimeType, mNameId);
-        if (pair == null) {
-            wlog(mimeType + ": no kind section data parsed");
-            return;
-        }
-        final KindSectionData kindSectionData = pair.first;
-        final ValuesDelta valuesDelta = pair.second;
-
-        // If we're editing a read-only contact we want to display the name from the
-        // read-only contact in the name editor backed by the new raw contact
-        // that was created. The new raw contact is the first writable one.
-        // See go/editing-read-only-contacts
-        if (!TextUtils.isEmpty(mReadOnlyDisplayName)) {
-            for (KindSectionData data : mKindSectionDataMap.get(mimeType)) {
-                if (data.getAccountType().areContactsWritable()) {
-                    vlog(mimeType + ": using name from read-only contact");
-                    mUsingDefaultNameEditorView = true;
-                    break;
-                }
-            }
-        }
-
-        final NameEditorListener nameEditorListener = new NameEditorListener(valuesDelta,
-                kindSectionData.getRawContactDelta().getRawContactId(), mListener);
-        final StructuredNameEditorView nameEditorView = inflateStructuredNameEditorView(
-                mNames, kindSectionData.getAccountType(), valuesDelta,
-                kindSectionData.getRawContactDelta(), nameEditorListener,
-                !kindSectionData.getAccountType().areContactsWritable());
-        mNames.addView(nameEditorView);
-
-        // TODO: Remove this after eliminating the full editor
-        mNameValuesDelta = valuesDelta;
-        if (mUsingDefaultNameEditorView) {
-            mDefaultNameEditorView = nameEditorView;
-        }
-    }
-
-    private Pair<KindSectionData,ValuesDelta> getPrimaryKindSectionData(String mimeType, long id) {
+    private Pair<KindSectionData,ValuesDelta> getPrimaryKindSectionData(long id) {
+        final String mimeType = Photo.CONTENT_ITEM_TYPE;
         final List<KindSectionData> kindSectionDataList = mKindSectionDataMap.get(mimeType);
         if (kindSectionDataList == null || kindSectionDataList.isEmpty()) {
-            wlog(mimeType + ": no kind section data parsed");
+            wlog("photo: no kind section data parsed");
             return null;
         }
 
@@ -652,7 +541,7 @@
             for (KindSectionData kindSectionData : kindSectionDataList) {
                 resultValuesDelta = kindSectionData.getValuesDeltaById(id);
                 if (resultValuesDelta != null) {
-                    vlog(mimeType + ": matched kind section data by ID");
+                    vlog("photo: matched kind section data by ID");
                     resultKindSectionData = kindSectionData;
                     break;
                 }
@@ -663,7 +552,7 @@
             for (KindSectionData kindSectionData : kindSectionDataList) {
                 resultValuesDelta = kindSectionData.getSuperPrimaryValuesDelta();
                 if (resultValuesDelta != null) {
-                    wlog(mimeType + ": matched super primary kind section data");
+                    wlog("photo: matched super primary kind section data");
                     resultKindSectionData = kindSectionData;
                     break;
                 }
@@ -674,7 +563,7 @@
             for (KindSectionData kindSectionData : kindSectionDataList) {
                 resultValuesDelta = kindSectionData.getFirstNonEmptyValuesDelta();
                 if (resultValuesDelta != null) {
-                    vlog(mimeType + ": using first non empty value");
+                    vlog("photo: using first non empty value");
                     resultKindSectionData = kindSectionData;
                     break;
                 }
@@ -683,7 +572,7 @@
         if (resultKindSectionData == null || resultValuesDelta == null) {
             final List<ValuesDelta> valuesDeltaList = kindSectionDataList.get(0).getValuesDeltas();
             if (valuesDeltaList != null && !valuesDeltaList.isEmpty()) {
-                vlog(mimeType + ": falling back to first empty entry");
+                vlog("photo: falling back to first empty entry");
                 resultValuesDelta = valuesDeltaList.get(0);
                 resultKindSectionData = kindSectionDataList.get(0);
             }
@@ -699,61 +588,59 @@
         entries.addAll(mKindSectionDataMap.entrySet());
 
         vlog("kind: " + entries.size() + " kindSection(s)");
-        int i = 0;
+        int i = -1;
         for (Map.Entry<String, List<KindSectionData>> entry : entries) {
+            i++;
+
             final String mimeType = entry.getKey();
             final List<KindSectionData> kindSectionDataList = entry.getValue();
-            vlog("kind: " + i++ + " " + mimeType + ": " + (kindSectionDataList == null ? 0
-                    : kindSectionDataList.size()) + " kindSectionData(s)");
 
             // Ignore mime types that we've already handled
-            if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)
-                    || StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)
-                    || DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(mimeType)) continue;
+            if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
+                vlog("kind: " + i + " " + mimeType + " dropped");
+                continue;
+            }
 
             // Ignore mime types that we don't handle
-            if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) continue;
+            if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)
+                    || DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(mimeType)) {
+                vlog("kind: " + i + " " + mimeType + " dropped");
+                continue;
+            }
 
             if (kindSectionDataList != null) {
+                vlog("kind: " + i + " " + mimeType + ": " + kindSectionDataList.size() +
+                        " kindSectionData(s)");
+
                 final CompactKindSectionView kindSectionView = inflateKindSectionView(
                         mKindSectionViews, kindSectionDataList, mimeType);
-                mKindSectionViewsMap.put(mimeType, kindSectionView);
                 mKindSectionViews.addView(kindSectionView);
             }
         }
     }
 
-    private StructuredNameEditorView inflateStructuredNameEditorView(ViewGroup viewGroup,
-            AccountType accountType, ValuesDelta valuesDelta, RawContactDelta rawContactDelta,
-            NameEditorListener nameEditorListener, boolean readOnly) {
-        final StructuredNameEditorView result = (StructuredNameEditorView) mLayoutInflater.inflate(
-                R.layout.structured_name_editor_view, viewGroup, /* attachToRoot =*/ false);
-        if (nameEditorListener != null) {
-            result.setEditorListener(nameEditorListener);
-        }
-        result.setDeletable(false);
-        result.setValues(accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME),
-                valuesDelta, rawContactDelta, readOnly, mViewIdGenerator);
-        return result;
-    }
-
     private CompactKindSectionView inflateKindSectionView(ViewGroup viewGroup,
             List<KindSectionData> kindSectionDataList, String mimeType) {
         final CompactKindSectionView kindSectionView = (CompactKindSectionView)
                 mLayoutInflater.inflate(R.layout.compact_item_kind_section, viewGroup,
                         /* attachToRoot =*/ false);
 
-        if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)
+        if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)
+                || Phone.CONTENT_ITEM_TYPE.equals(mimeType)
                 || Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
-            // Phone numbers and emails address are always displayed and are
-            // the only types you add new values to initially
+            // Names, phone numbers, and email addresses are always displayed.
+            // Phone numbers and email addresses are the only types you add new values
+            // to initially.
             kindSectionView.setHideWhenEmpty(false);
         }
-        // TODO: talk to Ricardo about when to allow adding new entries in compact mode
-        kindSectionView.setShowOneEmptyEditor(true);
 
-        kindSectionView.setState(kindSectionDataList, /* readOnly =*/ false,
-                mViewIdGenerator);
+        // Prevent the user from adding any new names
+        if (!StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
+            kindSectionView.setShowOneEmptyEditor(true);
+        }
+
+        kindSectionView.setState(kindSectionDataList, /* readOnly =*/ false, mViewIdGenerator,
+                mListener);
 
         return kindSectionView;
     }
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 011377d..22ee710 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -113,7 +113,6 @@
     private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
     private static final String KEY_MATERIAL_PALETTE = "materialPalette";
     private static final String KEY_PHOTO_ID = "photoId";
-    private static final String KEY_NAME_ID = "nameId";
 
     private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
 
@@ -182,11 +181,6 @@
     public static final String INTENT_EXTRA_PHOTO_ID = "photo_id";
 
     /**
-     * Intent key to pass the ID of the name to display on the editor.
-     */
-    public static final String INTENT_EXTRA_NAME_ID = "name_id";
-
-    /**
      * Intent extra to specify a {@link ContactEditor.SaveMode}.
      */
     public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
@@ -317,7 +311,6 @@
     protected boolean mNewLocalProfile;
     protected MaterialColorMapUtils.MaterialPalette mMaterialPalette;
     protected long mPhotoId = -1;
-    protected long mNameId = -1;
 
     //
     // Helpers
@@ -368,17 +361,6 @@
     // Join Activity
     protected long mContactIdForJoin;
 
-    //
-    // Not saved/restored on rotates
-    //
-
-    // Used to pre-populate the editor with a display name when a user edits a read-only contact.
-    protected String mReadOnlyDisplayName;
-
-    // The name editor view for the new raw contact that was created so that the user can
-    // edit a read-only contact (to which the new raw contact was joined)
-    protected StructuredNameEditorView mReadOnlyNameEditorView;
-
     /**
      * The contact data loader listener.
      */
@@ -471,7 +453,6 @@
             mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
             mMaterialPalette = savedState.getParcelable(KEY_MATERIAL_PALETTE);
             mPhotoId = savedState.getLong(KEY_PHOTO_ID);
-            mNameId = savedState.getLong(KEY_NAME_ID);
 
             mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
                     KEY_RAW_CONTACTS));
@@ -593,7 +574,6 @@
             outState.putParcelable(KEY_MATERIAL_PALETTE, mMaterialPalette);
         }
         outState.putLong(KEY_PHOTO_ID, mPhotoId);
-        outState.putLong(KEY_NAME_ID, mNameId);
 
         outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
 
@@ -1096,7 +1076,6 @@
             }
         }
 
-        String readOnlyDisplayName = null;
         // Check for writable raw contacts.  If there are none, then we need to create one so user
         // can edit.  For the user profile case, there is already an editable contact.
         if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
@@ -1104,13 +1083,11 @@
 
             // This is potentially an asynchronous call and will add deltas to list.
             selectAccountAndCreateContact();
-
-            readOnlyDisplayName = contact.getDisplayName();
         }
 
         // This also adds deltas to list.  If readOnlyDisplayName is null at this point it is
         // simply ignored later on by the editor.
-        setStateForExistingContact(readOnlyDisplayName, contact.isUserProfile(), mRawContacts);
+        setStateForExistingContact(contact.isUserProfile(), mRawContacts);
     }
 
     /**
@@ -1181,10 +1158,9 @@
     /**
      * Prepare {@link #mState} for an existing contact.
      */
-    protected void setStateForExistingContact(String readOnlyDisplayName, boolean isUserProfile,
+    protected void setStateForExistingContact(boolean isUserProfile,
             ImmutableList<RawContact> rawContacts) {
         setEnabled(true);
-        mReadOnlyDisplayName = readOnlyDisplayName;
 
         mState.addAll(rawContacts.iterator());
         setIntentExtras(mIntentExtras);
@@ -1296,8 +1272,7 @@
             setStateForNewContact(newAccount, newAccountType, oldState, oldAccountType,
                     isEditingUserProfile());
             if (mIsEdit) {
-                setStateForExistingContact(mReadOnlyDisplayName, isEditingUserProfile(),
-                        mRawContacts);
+                setStateForExistingContact(isEditingUserProfile(), mRawContacts);
             }
         }
     }
@@ -1331,7 +1306,6 @@
                         mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR));
             }
             mPhotoId = mIntentExtras.getLong(INTENT_EXTRA_PHOTO_ID);
-            mNameId = mIntentExtras.getLong(INTENT_EXTRA_NAME_ID);
         }
     }
 
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index da6eeb1..ccbf615 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -245,10 +245,6 @@
 
                 final StructuredNameEditorView nameEditor = rawContactEditor.getNameEditor();
                 nameEditor.setEditorListener(structuredNameListener);
-                if (!TextUtils.isEmpty(mReadOnlyDisplayName)) {
-                    nameEditor.setDisplayName(mReadOnlyDisplayName);
-                    mReadOnlyNameEditorView = nameEditor;
-                }
 
                 rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup);
 
diff --git a/src/com/android/contacts/editor/EditorIntents.java b/src/com/android/contacts/editor/EditorIntents.java
index e923c43..ca8d5ae 100644
--- a/src/com/android/contacts/editor/EditorIntents.java
+++ b/src/com/android/contacts/editor/EditorIntents.java
@@ -44,11 +44,10 @@
      * existing contact.
      */
     public static Intent createCompactEditContactIntent(Uri contactLookupUri,
-            MaterialPalette materialPalette, long photoId, long nameId) {
+            MaterialPalette materialPalette, long photoId) {
         final Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
         putMaterialPalette(intent, materialPalette);
         putPhotoId(intent, photoId);
-        putNameId(intent, nameId);
         return intent;
     }
 
@@ -99,12 +98,11 @@
      * existing contact.
      */
     public static Intent createEditContactIntent(Uri contactLookupUri,
-            MaterialPalette materialPalette, long photoId, long nameId) {
+            MaterialPalette materialPalette, long photoId) {
         final Intent intent = new Intent(ContactEditorBaseActivity.ACTION_EDIT, contactLookupUri);
         addContactIntentFlags(intent);
         putMaterialPalette(intent, materialPalette);
         putPhotoId(intent, photoId);
-        putNameId(intent, nameId);
         return intent;
     }
 
@@ -112,9 +110,9 @@
      * Returns an Intent to start the fully expanded {@link ContactEditorActivity} for a
      * new contact.
      */
+    // TODO: Delete this if we don't need it to load the full editor for read only accounts
     public static Intent createInsertContactIntent(RawContactDeltaList rawContactDeltaList,
-            String displayName, String phoneticName, Bundle updatedPhotos,
-            boolean isNewLocalProfile) {
+            String displayName, String phoneticName, boolean isNewLocalProfile) {
         final Intent intent = new Intent(ContactEditorBaseActivity.ACTION_INSERT,
                 Contacts.CONTENT_URI);
         intent.putExtra(ContactEditorFragment.INTENT_EXTRA_NEW_LOCAL_PROFILE, isNewLocalProfile);
@@ -143,12 +141,6 @@
         }
     }
 
-    private static void putNameId(Intent intent, long nameId) {
-        if (nameId >= 0) {
-            intent.putExtra(ContactEditorBaseFragment.INTENT_EXTRA_NAME_ID, nameId);
-        }
-    }
-
     private static void putRawContactDeltaValues(Intent intent,
             RawContactDeltaList rawContactDeltaList, String displayName, String phoneticName) {
         // Pass on all the data that has been entered so far
diff --git a/src/com/android/contacts/editor/EditorUiUtils.java b/src/com/android/contacts/editor/EditorUiUtils.java
index 7a40b1d..3da5ee9 100644
--- a/src/com/android/contacts/editor/EditorUiUtils.java
+++ b/src/com/android/contacts/editor/EditorUiUtils.java
@@ -158,6 +158,8 @@
      */
     public static Drawable getMimeTypeDrawable(Context context, String mimeType) {
         switch (mimeType) {
+            case StructuredName.CONTENT_ITEM_TYPE:
+                return context.getResources().getDrawable(R.drawable.ic_person_black_24dp);
             case StructuredPostal.CONTENT_ITEM_TYPE:
                 return context.getResources().getDrawable(R.drawable.ic_place_24dp);
             case SipAddress.CONTENT_ITEM_TYPE:
diff --git a/src/com/android/contacts/editor/KindSectionData.java b/src/com/android/contacts/editor/KindSectionData.java
index e9160de..6455ff5 100644
--- a/src/com/android/contacts/editor/KindSectionData.java
+++ b/src/com/android/contacts/editor/KindSectionData.java
@@ -65,6 +65,7 @@
         return mValuesDeltas;
     }
 
+    /** Returns the super primary ValuesDelta for the data kind this section represents. */
     public ValuesDelta getSuperPrimaryValuesDelta() {
         for (ValuesDelta valuesDelta : mValuesDeltas) {
             if (valuesDelta.isSuperPrimary()) return valuesDelta;
@@ -72,6 +73,7 @@
         return null;
     }
 
+    /** Returns the ValuesDelta with the given ID. */
     public ValuesDelta getValuesDeltaById(Long id) {
         for (ValuesDelta valuesDelta : mValuesDeltas) {
             if (valuesDelta.getId().equals(id)) return valuesDelta;
@@ -79,35 +81,26 @@
         return null;
     }
 
+    /** Returns the first non empty ValuesDelta for the data kind this section represents. */
     public ValuesDelta getFirstNonEmptyValuesDelta() {
-        if (mDataKind.fieldList != null) {
-            for (ValuesDelta valuesDelta : mValuesDeltas) {
-                for (EditField editField : mDataKind.fieldList) {
-                    final String column = editField.column;
-                    final String value = valuesDelta.getAsString(column);
-                    if (!TextUtils.isEmpty(value)) return valuesDelta;
-                }
-            }
+        for (ValuesDelta valuesDelta : mValuesDeltas) {
+            if (!isEmpty(valuesDelta)) return valuesDelta;
         }
         return null;
     }
 
-    public boolean hasNonEmptyValuesDelta() {
-        return !getNonEmptyValuesDeltas().isEmpty();
-    }
+    /** Whether the given ValuesDelta is empty for the data kind this section represents. */
+    public boolean isEmpty(ValuesDelta valuesDelta) {
+        if (valuesDelta.isNoop()) return true;
 
-    public List<ValuesDelta> getNonEmptyValuesDeltas() {
-        final List<ValuesDelta> valuesDeltas = new ArrayList<>();
         if (mDataKind.fieldList != null) {
-            for (ValuesDelta valuesDelta : mValuesDeltas) {
-                for (EditField editField : mDataKind.fieldList) {
-                    final String column = editField.column;
-                    final String value = valuesDelta.getAsString(column);
-                    if (!TextUtils.isEmpty(value)) valuesDeltas.add(valuesDelta);
-                }
+            for (EditField editField : mDataKind.fieldList) {
+                final String column = editField.column;
+                final String value = valuesDelta.getAsString(column);
+                if (TextUtils.isEmpty(value)) return true;
             }
         }
-        return valuesDeltas;
+        return false;
     }
 
     public DataKind getDataKind() {
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index bef62e3..4cc8003 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.editor;
 
+import com.android.contacts.R;
 import android.content.ContentValues;
 import android.content.Context;
 import android.os.Parcel;
@@ -23,9 +24,14 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
+import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.dataitem.DataItem;
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.android.contacts.common.util.NameConverter;
@@ -75,6 +81,18 @@
         updateEmptiness();
     }
 
+    /**
+     * Displays the icon and name for the given account under the name name input fields.
+     */
+    public void setAccountType(AccountType accountType) {
+        final LinearLayout layout = (LinearLayout) findViewById(R.id.account_type);
+        layout.setVisibility(View.VISIBLE);
+        final ImageView imageView = (ImageView) layout.findViewById(R.id.account_type_icon);
+        imageView.setImageDrawable(accountType.getDisplayIcon(getContext()));
+        final TextView textView = (TextView) layout.findViewById(R.id.account_type_name);
+        textView.setText(accountType.getDisplayLabel(getContext()));
+    }
+
     @Override
     public void onFieldChanged(String column, String value) {
         if (!isFieldChanged(column, value)) {
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index eaadc3d..091f41a 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -2267,8 +2267,7 @@
                 mContactData.getLookupUri(),
                 mHasComputedThemeColor
                         ? new MaterialPalette(mColorFilterColor, mStatusBarColor) : null,
-                mContactData.getPhotoId(),
-                mContactData.getNameRawContactId());
+                mContactData.getPhotoId());
     }
 
     private void editContact() {