Merge "Modernizing phonetic name support"
diff --git a/res/layout-xlarge/raw_contact_editor_view.xml b/res/layout-xlarge/raw_contact_editor_view.xml
index 02c0314..3c3b9d0 100644
--- a/res/layout-xlarge/raw_contact_editor_view.xml
+++ b/res/layout-xlarge/raw_contact_editor_view.xml
@@ -77,6 +77,16 @@
                     android:layout_marginTop="6dip"
                     android:layout_marginBottom="4dip" />
 
+                <com.android.contacts.editor.PhoneticNameEditorView
+                    android:id="@+id/edit_phonetic_name"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:paddingRight="?android:attr/scrollbarSize"
+                    android:layout_marginLeft="52dip"
+                    android:layout_marginRight="48dip"
+                    android:layout_marginTop="6dip"
+                    android:layout_marginBottom="4dip" />
+
                 <FrameLayout
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
diff --git a/res/layout/raw_contact_editor_view.xml b/res/layout/raw_contact_editor_view.xml
index 022d0b4..ac30a6b 100644
--- a/res/layout/raw_contact_editor_view.xml
+++ b/res/layout/raw_contact_editor_view.xml
@@ -101,7 +101,14 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:paddingRight="?android:attr/scrollbarSize"
-            android:layout_below="@id/stub_photo"
+            android:layout_marginTop="6dip"
+            android:layout_marginBottom="4dip" />
+
+        <com.android.contacts.editor.PhoneticNameEditorView
+            android:id="@+id/edit_phonetic_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="?android:attr/scrollbarSize"
             android:layout_marginTop="6dip"
             android:layout_marginBottom="4dip" />
 
diff --git a/res/values-ja/donottranslate_config.xml b/res/values-ja/donottranslate_config.xml
index c5d3aea..7f53722 100644
--- a/res/values-ja/donottranslate_config.xml
+++ b/res/values-ja/donottranslate_config.xml
@@ -32,4 +32,7 @@
     
     <!-- If true, the order of name fields in the editor is primary (i.e. given name first) -->
     <bool name="config_editor_field_order_primary">false</bool>
+
+    <!-- If true, phonetic name is included in the contact editor by default -->
+    <bool name="config_editor_include_phonetic_name">true</bool>
 </resources>
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml
index cad2a63..f5efa13 100644
--- a/res/values/donottranslate_config.xml
+++ b/res/values/donottranslate_config.xml
@@ -96,4 +96,7 @@
 
     <!-- If true, the order of name fields in the editor is primary (i.e. given name first) -->
     <bool name="config_editor_field_order_primary">true</bool>
+
+    <!-- If true, phonetic name is included in the contact editor by default -->
+    <bool name="config_editor_include_phonetic_name">false</bool>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4c75705..ff69899 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1216,6 +1216,8 @@
     <string name="name_phonetic_middle">Phonetic middle name</string>
     <!-- Field title for the phonetic family name of a contact -->
     <string name="name_phonetic_family">Phonetic family name</string>
+    <!-- Field title for the phonetic name of a contact [CHAR LIMIT=64]-->
+    <string name="name_phonetic">Phonetic name</string>
 
     <!-- String describing which account type a contact came from when editing it -->
     <string name="account_type_format"><xliff:g id="source" example="Gmail">%1$s</xliff:g> contact</string>
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index bd49d34..97203bb 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -553,12 +553,7 @@
                     new PhotoEditorListener(editor, type.readOnly));
             if (editor instanceof RawContactEditorView) {
                 final RawContactEditorView rawContactEditor = (RawContactEditorView) editor;
-                final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor();
-                if (mRequestFocus) {
-                    nameEditor.requestFocus();
-                    mRequestFocus = false;
-                }
-                nameEditor.setEditorListener(new EditorListener() {
+                EditorListener listener = new EditorListener() {
 
                     @Override
                     public void onRequest(int request) {
@@ -570,8 +565,18 @@
                     @Override
                     public void onDeleted(Editor removedEditor) {
                     }
-                });
+                };
 
+                final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor();
+                if (mRequestFocus) {
+                    nameEditor.requestFocus();
+                    mRequestFocus = false;
+                }
+                nameEditor.setEditorListener(listener);
+
+                final TextFieldsEditorView phoneticNameEditor =
+                        rawContactEditor.getPhoneticNameEditor();
+                phoneticNameEditor.setEditorListener(listener);
                 rawContactEditor.setAutoAddToDefaultGroup(mAutoAddToDefaultGroup);
 
                 if (rawContactId == mAggregationSuggestionsRawContactId) {
diff --git a/src/com/android/contacts/editor/PhoneticNameEditorView.java b/src/com/android/contacts/editor/PhoneticNameEditorView.java
new file mode 100644
index 0000000..d3aa00d
--- /dev/null
+++ b/src/com/android/contacts/editor/PhoneticNameEditorView.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.contacts.editor;
+
+import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+
+import android.content.Context;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+/**
+ * A dedicated editor for phonetic name. It is similar to {@link StructuredNameEditorView}.
+ */
+public class PhoneticNameEditorView extends TextFieldsEditorView {
+
+    private static class PhoneticValuesDelta extends ValuesDelta {
+        private ValuesDelta mValues;
+        private String mPhoneticName;
+
+        public PhoneticValuesDelta(ValuesDelta values) {
+            mValues = values;
+            buildPhoneticName();
+        }
+
+        @Override
+        public void put(String key, String value) {
+            if (key.equals(DataKind.PSEUDO_COLUMN_PHONETIC_NAME)) {
+                mPhoneticName = value;
+                parsePhoneticName(value);
+            } else {
+                mValues.put(key, value);
+                buildPhoneticName();
+            }
+        }
+
+        @Override
+        public String getAsString(String key) {
+            if (key.equals(DataKind.PSEUDO_COLUMN_PHONETIC_NAME)) {
+                return mPhoneticName;
+            } else {
+                return mValues.getAsString(key);
+            }
+        }
+
+        private void parsePhoneticName(String value) {
+            String family = null;
+            String middle = null;
+            String given = null;
+
+            if (!TextUtils.isEmpty(value)) {
+                String[] strings = value.split(" ", 3);
+                switch (strings.length) {
+                    case 1:
+                        family = strings[0];
+                        break;
+                    case 2:
+                        family = strings[0];
+                        given = strings[1];
+                        break;
+                    case 3:
+                        family = strings[0];
+                        middle = strings[1];
+                        given = strings[2];
+                        break;
+                }
+            }
+
+            mValues.put(StructuredName.PHONETIC_FAMILY_NAME, family);
+            mValues.put(StructuredName.PHONETIC_MIDDLE_NAME, middle);
+            mValues.put(StructuredName.PHONETIC_GIVEN_NAME, given);
+        }
+
+        private void buildPhoneticName() {
+            String family = mValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
+            String middle = mValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
+            String given = mValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+
+            if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
+                    || !TextUtils.isEmpty(given)) {
+                StringBuilder sb = new StringBuilder();
+                if (!TextUtils.isEmpty(family)) {
+                    sb.append(family.trim()).append(' ');
+                }
+                if (!TextUtils.isEmpty(middle)) {
+                    sb.append(middle.trim()).append(' ');
+                }
+                if (!TextUtils.isEmpty(given)) {
+                    sb.append(given.trim()).append(' ');
+                }
+                sb.setLength(sb.length() - 1);  // Yank the last space
+                mPhoneticName = sb.toString();
+            } else {
+                mPhoneticName = null;
+            }
+        }
+
+        @Override
+        public Long getId() {
+            return mValues.getId();
+        }
+
+        @Override
+        public boolean isVisible() {
+            return mValues.isVisible();
+        }
+    }
+
+    public PhoneticNameEditorView(Context context) {
+        super(context);
+    }
+
+    public PhoneticNameEditorView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public PhoneticNameEditorView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
+            ViewIdGenerator vig) {
+        if (!(entry instanceof PhoneticValuesDelta)) {
+            entry = new PhoneticValuesDelta(entry);
+        }
+        super.setValues(kind, entry, state, readOnly, vig);
+    }
+
+    public boolean hasData() {
+        ValuesDelta entry = getEntry();
+
+        String family = entry.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
+        String middle = entry.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
+        String given = entry.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
+
+        return !TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
+                || !TextUtils.isEmpty(given);
+    }
+}
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index 496144b..633b343 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -62,7 +62,8 @@
 public class RawContactEditorView extends BaseRawContactEditorView {
     private LayoutInflater mInflater;
 
-    private TextFieldsEditorView mName;
+    private StructuredNameEditorView mName;
+    private PhoneticNameEditorView mPhoneticName;
     private GroupMembershipView mGroupMembershipView;
 
     private ViewGroup mFields;
@@ -79,6 +80,8 @@
     private DataKind mGroupMembershipKind;
     private EntityDelta mState;
 
+    private boolean mPhoneticNameAdded;
+
     public RawContactEditorView(Context context) {
         super(context);
     }
@@ -93,11 +96,15 @@
 
         View view = getPhotoEditor();
         if (view != null) {
-            view.setEnabled(isEnabled());
+            view.setEnabled(enabled);
         }
 
         if (mName != null) {
-            mName.setEnabled(isEnabled());
+            mName.setEnabled(enabled);
+        }
+
+        if (mPhoneticName != null) {
+            mPhoneticName.setEnabled(enabled);
         }
 
         if (mFields != null) {
@@ -111,7 +118,7 @@
             mGroupMembershipView.setEnabled(enabled);
         }
 
-        mAddFieldButton.setEnabled(isEnabled());
+        mAddFieldButton.setEnabled(enabled);
     }
 
     @Override
@@ -122,10 +129,12 @@
 
         final int photoSize = getResources().getDimensionPixelSize(R.dimen.edit_photo_size);
 
-        mName = (TextFieldsEditorView)findViewById(R.id.edit_name);
+        mName = (StructuredNameEditorView)findViewById(R.id.edit_name);
         mName.setMinimumHeight(photoSize);
         mName.setDeletable(false);
 
+        mPhoneticName = (PhoneticNameEditorView)findViewById(R.id.edit_phonetic_name);
+
         mFields = (ViewGroup)findViewById(R.id.sect_fields);
 
         mHeaderIcon = (ImageView) findViewById(R.id.header_icon);
@@ -185,9 +194,12 @@
         mName.setEditorTextSize(
                 mContext.getResources().getDimensionPixelSize(R.dimen.contact_name_text_size));
 
+        mPhoneticName.setEnabled(isEnabled());
+
         // Show and hide the appropriate views
         mFields.setVisibility(View.VISIBLE);
         mName.setVisibility(View.VISIBLE);
+        mPhoneticName.setVisibility(View.VISIBLE);
 
         mGroupMembershipKind = type.getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
         if (mGroupMembershipKind != null) {
@@ -206,7 +218,12 @@
             if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
                 // Handle special case editor for structured name
                 final ValuesDelta primary = state.getPrimaryEntry(mimeType);
-                mName.setValues(kind, primary, state, false, vig);
+                mName.setValues(
+                        type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME),
+                        primary, state, false, vig);
+                mPhoneticName.setValues(
+                        type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME),
+                        primary, state, false, vig);
             } else if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
                 // Handle special case editor for photos
                 final ValuesDelta primary = state.getPrimaryEntry(mimeType);
@@ -230,6 +247,8 @@
             mFields.addView(mGroupMembershipView);
         }
 
+        updatePhoneticNameVisibility();
+
         addToDefaultGroupIfNeeded();
 
         mAddFieldButton.setEnabled(isEnabled());
@@ -307,6 +326,21 @@
         return mName;
     }
 
+    public TextFieldsEditorView getPhoneticNameEditor() {
+        return mPhoneticName;
+    }
+
+    private void updatePhoneticNameVisibility() {
+        boolean showByDefault =
+                getContext().getResources().getBoolean(R.bool.config_editor_include_phonetic_name);
+
+        if (showByDefault || mPhoneticName.hasData() || mPhoneticNameAdded) {
+            mPhoneticName.setVisibility(View.VISIBLE);
+        } else {
+            mPhoneticName.setVisibility(View.GONE);
+        }
+    }
+
     @Override
     public long getRawContactId() {
         return mRawContactId;
@@ -323,18 +357,34 @@
             if (child instanceof KindSectionView) {
                 final KindSectionView sectionView = (KindSectionView) child;
                 // not a list and already exists? ignore
-                if (!sectionView.getKind().isList && sectionView.getEditorCount() != 0) {
+                DataKind kind = sectionView.getKind();
+                if (!kind.isList && sectionView.getEditorCount() != 0) {
                     continue;
                 }
+                if (DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(kind.mimeType)) {
+                    continue;
+                }
+
+                if (DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(kind.mimeType)
+                        && mPhoneticName.getVisibility() == View.VISIBLE) {
+                    continue;
+                }
+
                 menu.add(Menu.NONE, fields.size(), Menu.NONE, sectionView.getTitle());
                 fields.add(sectionView);
             }
         }
+
         popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
             @Override
             public boolean onMenuItemClick(MenuItem item) {
                 final KindSectionView view = fields.get(item.getItemId());
-                view.addItem();
+                if (DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(view.getKind().mimeType)) {
+                    mPhoneticNameAdded = true;
+                    updatePhoneticNameVisibility();
+                } else {
+                    view.addItem();
+                }
                 return true;
             }
         });
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index 1a930a1..031ab18 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -364,7 +364,7 @@
 
         ss.mHideOptional = mHideOptional;
 
-        final int numChildren = mFieldEditTexts.length;
+        final int numChildren = mFieldEditTexts == null ? 0 : mFieldEditTexts.length;
         ss.mVisibilities = new int[numChildren];
         for (int i = 0; i < numChildren; i++) {
             ss.mVisibilities[i] = mFieldEditTexts[i].getVisibility();
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index 0f67fba..aef5c06 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -166,6 +166,11 @@
      * labels and editable {@link EditField}.
      */
     public static class DataKind {
+
+        public static final String PSEUDO_MIME_TYPE_DISPLAY_NAME = "#displayName";
+        public static final String PSEUDO_MIME_TYPE_PHONETIC_NAME = "#phoneticName";
+        public static final String PSEUDO_COLUMN_PHONETIC_NAME = "#phoneticName";
+
         public String resPackageName;
         public String mimeType;
         public int titleRes;
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index 70cfa55..d4a7496 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -105,6 +105,35 @@
 
         kind.fieldList = Lists.newArrayList();
         kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
+                R.string.full_name, FLAGS_PERSON_NAME));
+        kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
+                FLAGS_PERSON_NAME).setLongForm(true));
+        kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
+                FLAGS_PERSON_NAME).setLongForm(true));
+        kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
+                FLAGS_PERSON_NAME).setLongForm(true));
+        kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
+                FLAGS_PERSON_NAME).setLongForm(true));
+        kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
+                FLAGS_PERSON_NAME).setLongForm(true));
+        kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
+                R.string.name_phonetic_family, FLAGS_PHONETIC));
+        kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
+                R.string.name_phonetic_middle, FLAGS_PHONETIC));
+        kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
+                R.string.name_phonetic_given, FLAGS_PHONETIC));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindDisplayName(Context context) {
+        DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
+                R.string.nameLabelsGroup, -1, -1, true));
+        kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
+        kind.actionBody = new SimpleInflater(Nickname.NAME);
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
                 R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true));
 
         boolean displayOrderPrimary =
@@ -133,6 +162,19 @@
             kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
                     FLAGS_PERSON_NAME).setLongForm(true));
         }
+
+        return kind;
+    }
+
+    protected DataKind addDataKindPhoneticName(Context context) {
+        DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
+                R.string.name_phonetic, -1, -1, true));
+        kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
+        kind.actionBody = new SimpleInflater(Nickname.NAME);
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(DataKind.PSEUDO_COLUMN_PHONETIC_NAME,
+                R.string.name_phonetic, FLAGS_PHONETIC).setShortForm(true));
         kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
                 R.string.name_phonetic_family, FLAGS_PHONETIC).setLongForm(true));
         kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
diff --git a/src/com/android/contacts/model/ExchangeAccountType.java b/src/com/android/contacts/model/ExchangeAccountType.java
index 9779e70..2b1a520 100644
--- a/src/com/android/contacts/model/ExchangeAccountType.java
+++ b/src/com/android/contacts/model/ExchangeAccountType.java
@@ -47,6 +47,8 @@
         this.summaryResPackageName = resPackageName;
 
         addDataKindStructuredName(context);
+        addDataKindDisplayName(context);
+        addDataKindPhoneticName(context);
         addDataKindNickname(context);
         addDataKindPhone(context);
         addDataKindEmail(context);
@@ -62,7 +64,37 @@
 
     @Override
     protected DataKind addDataKindStructuredName(Context context) {
-        final DataKind kind = super.addDataKindStructuredName(context);
+        DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
+                R.string.nameLabelsGroup, -1, -1, true));
+        kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
+        kind.actionBody = new SimpleInflater(Nickname.NAME);
+
+        kind.typeOverallMax = 1;
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
+                FLAGS_PERSON_NAME).setOptional(true));
+        kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME,
+                R.string.name_family, FLAGS_PERSON_NAME));
+        kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME,
+                R.string.name_middle, FLAGS_PERSON_NAME));
+        kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME,
+                R.string.name_given, FLAGS_PERSON_NAME));
+        kind.fieldList.add(new EditField(StructuredName.SUFFIX,
+                R.string.name_suffix, FLAGS_PERSON_NAME));
+
+        kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
+                R.string.name_phonetic_family, FLAGS_PHONETIC));
+        kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
+                R.string.name_phonetic_given, FLAGS_PHONETIC));
+
+        return kind;
+    }
+
+    @Override
+    protected DataKind addDataKindDisplayName(Context context) {
+        DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
+                R.string.nameLabelsGroup, -1, -1, true));
 
         boolean displayOrderPrimary =
                 context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
@@ -78,8 +110,6 @@
                     R.string.name_middle, FLAGS_PERSON_NAME).setOptional(true));
             kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME,
                     R.string.name_given, FLAGS_PERSON_NAME));
-            kind.fieldList.add(new EditField(StructuredName.SUFFIX,
-                    R.string.name_suffix, FLAGS_PERSON_NAME).setOptional(true));
         } else {
             kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME,
                     R.string.name_given, FLAGS_PERSON_NAME));
@@ -87,14 +117,27 @@
                     R.string.name_middle, FLAGS_PERSON_NAME).setOptional(true));
             kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME,
                     R.string.name_family, FLAGS_PERSON_NAME));
-            kind.fieldList.add(new EditField(StructuredName.SUFFIX,
-                    R.string.name_suffix, FLAGS_PERSON_NAME).setOptional(true));
         }
+        kind.fieldList.add(new EditField(StructuredName.SUFFIX,
+                R.string.name_suffix, FLAGS_PERSON_NAME).setOptional(true));
 
+        return kind;
+    }
+
+    @Override
+    protected DataKind addDataKindPhoneticName(Context context) {
+        DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
+                R.string.name_phonetic, -1, -1, true));
+        kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
+        kind.actionBody = new SimpleInflater(Nickname.NAME);
+
+        kind.typeOverallMax = 1;
+
+        kind.fieldList = Lists.newArrayList();
         kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
-                R.string.name_phonetic_family, FLAGS_PHONETIC).setOptional(true));
+                R.string.name_phonetic_family, FLAGS_PHONETIC));
         kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
-                R.string.name_phonetic_given, FLAGS_PHONETIC).setOptional(true));
+                R.string.name_phonetic_given, FLAGS_PHONETIC));
 
         return kind;
     }
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index 0b895f6..9ce6fd9 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/ExternalAccountType.java
@@ -73,6 +73,8 @@
 
         // Bring in name and photo from fallback source, which are non-optional
         addDataKindStructuredName(context);
+        addDataKindDisplayName(context);
+        addDataKindPhoneticName(context);
         addDataKindPhoto(context);
     }
 
diff --git a/src/com/android/contacts/model/FallbackAccountType.java b/src/com/android/contacts/model/FallbackAccountType.java
index 05e6556..13540be 100644
--- a/src/com/android/contacts/model/FallbackAccountType.java
+++ b/src/com/android/contacts/model/FallbackAccountType.java
@@ -31,6 +31,8 @@
         this.summaryResPackageName = resPackageName;
 
         addDataKindStructuredName(context);
+        addDataKindDisplayName(context);
+        addDataKindPhoneticName(context);
         addDataKindNickname(context);
         addDataKindPhone(context);
         addDataKindEmail(context);
diff --git a/src/com/android/contacts/model/GoogleAccountType.java b/src/com/android/contacts/model/GoogleAccountType.java
index d369b28..af25691 100644
--- a/src/com/android/contacts/model/GoogleAccountType.java
+++ b/src/com/android/contacts/model/GoogleAccountType.java
@@ -40,6 +40,8 @@
         this.summaryResPackageName = resPackageName;
 
         addDataKindStructuredName(context);
+        addDataKindDisplayName(context);
+        addDataKindPhoneticName(context);
         addDataKindNickname(context);
         addDataKindPhone(context);
         addDataKindEmail(context);