Merge "New quickContact holo theme." into honeycomb
diff --git a/res/drawable-hdpi/sym_action_audiochat_holo_light.png b/res/drawable-hdpi/sym_action_audiochat_holo_light.png
new file mode 100644
index 0000000..8bea3ec
--- /dev/null
+++ b/res/drawable-hdpi/sym_action_audiochat_holo_light.png
Binary files differ
diff --git a/res/drawable-hdpi/sym_action_videochat_holo_light.png b/res/drawable-hdpi/sym_action_videochat_holo_light.png
new file mode 100644
index 0000000..b86c435
--- /dev/null
+++ b/res/drawable-hdpi/sym_action_videochat_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/sym_action_audiochat_holo_light.png b/res/drawable-mdpi/sym_action_audiochat_holo_light.png
new file mode 100644
index 0000000..9e6e328
--- /dev/null
+++ b/res/drawable-mdpi/sym_action_audiochat_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/sym_action_videochat_holo_light.png b/res/drawable-mdpi/sym_action_videochat_holo_light.png
new file mode 100644
index 0000000..0ef40f8
--- /dev/null
+++ b/res/drawable-mdpi/sym_action_videochat_holo_light.png
Binary files differ
diff --git a/res/layout-xlarge-land/contact_detail_list_item.xml b/res/layout-xlarge-land/contact_detail_list_item.xml
index ec06c7f..394d6c0 100644
--- a/res/layout-xlarge-land/contact_detail_list_item.xml
+++ b/res/layout-xlarge-land/contact_detail_list_item.xml
@@ -122,11 +122,11 @@
 
             <ImageView
                 android:id="@+id/secondary_action_button"
-                android:layout_width="30dip"
+                android:layout_width="58dip"
                 android:layout_height="match_parent"
                 android:layout_centerVertical="true"
-                android:layout_marginLeft="14dip"
-                android:layout_marginRight="14dip"
+                android:paddingLeft="14dip"
+                android:paddingRight="14dip"
                 android:gravity="center"
                 android:scaleType="center"
                 android:background="@android:drawable/list_selector_background"
diff --git a/res/layout-xlarge/contact_browser.xml b/res/layout-xlarge/contact_browser.xml
index bb4c2fc..cc5e0eb 100644
--- a/res/layout-xlarge/contact_browser.xml
+++ b/res/layout-xlarge/contact_browser.xml
@@ -57,15 +57,15 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             ex:layout_narrowParentWidth="800dip"
-            ex:layout_narrowRightMargin="0dip"
+            ex:layout_narrowMarginRight="0dip"
             ex:layout_wideParentWidth="1280dip"
-            ex:layout_wideRightMargin="48dip"
+            ex:layout_wideMarginRight="48dip"
             ex:clipMarginLeft="0dip"
             ex:clipMarginTop="3dip"
             ex:clipMarginRight="3dip"
             ex:clipMarginBottom="9dip"
-            ex:enterAnimation="@android:anim/animator_fade_in"
-            ex:exitAnimation="@android:anim/animator_fade_out"
+            ex:enterAnimation="@android:animator/fade_in"
+            ex:exitAnimation="@android:animator/fade_out"
             ex:animationDuration="200">
             <FrameLayout
                 android:id="@+id/detail_container"
@@ -86,11 +86,11 @@
             android:layout_height="match_parent"
             android:layout_width="match_parent"
             ex:layout_narrowParentWidth="800dip"
-            ex:layout_narrowLeftMargin="80dip"
-            ex:layout_narrowRightMargin="80dip"
+            ex:layout_narrowMarginLeft="80dip"
+            ex:layout_narrowMarginRight="80dip"
             ex:layout_wideParentWidth="1280dip"
-            ex:layout_wideLeftMargin="200dip"
-            ex:layout_wideRightMargin="200dip"
+            ex:layout_wideMarginLeft="200dip"
+            ex:layout_wideMarginRight="200dip"
             android:paddingBottom="20dip" />
 
     </com.android.contacts.widget.InterpolatingLayout>
diff --git a/res/layout-xlarge/contact_detail_fragment.xml b/res/layout-xlarge/contact_detail_fragment.xml
index 4bc2a04..4c1759d 100644
--- a/res/layout-xlarge/contact_detail_fragment.xml
+++ b/res/layout-xlarge/contact_detail_fragment.xml
@@ -34,11 +34,11 @@
             android:layout_height="wrap_content"
             android:layout_marginBottom="28dip"
             ex:layout_wideParentWidth="800dip"
-            ex:layout_wideLeftMargin="80dip"
-            ex:layout_wideRightMargin="48dip"
+            ex:layout_wideMarginLeft="80dip"
+            ex:layout_wideMarginRight="48dip"
             ex:layout_narrowParentWidth="500dip"
-            ex:layout_narrowLeftMargin="15dip"
-            ex:layout_narrowRightMargin="5dip"
+            ex:layout_narrowMarginLeft="15dip"
+            ex:layout_narrowMarginRight="5dip"
         />
     </com.android.contacts.widget.InterpolatingLayout>
 
@@ -55,9 +55,9 @@
             android:textSize="20sp"
             android:textColor="?android:attr/textColorSecondary"
             ex:layout_wideParentWidth="800dip"
-            ex:layout_wideLeftMargin="64dip"
+            ex:layout_wideMarginLeft="64dip"
             ex:layout_narrowParentWidth="500dip"
-            ex:layout_narrowLeftMargin="42dip"
+            ex:layout_narrowMarginLeft="42dip"
             android:paddingTop="10dip"
             android:lineSpacingMultiplier="0.92"
         />
@@ -72,11 +72,11 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             ex:layout_wideParentWidth="800dip"
-            ex:layout_wideLeftMargin="64dip"
-            ex:layout_wideRightPadding="48dip"
+            ex:layout_wideMarginLeft="64dip"
+            ex:layout_widePaddingRight="48dip"
             ex:layout_narrowParentWidth="500dip"
-            ex:layout_narrowLeftMargin="32dip"
-            ex:layout_narrowRightPadding="0dip"
+            ex:layout_narrowMarginLeft="32dip"
+            ex:layout_narrowPaddingRight="0dip"
             android:cacheColorHint="#00000000"
             android:divider="@android:color/transparent"
         />
diff --git a/res/layout-xlarge/contact_editor_activity.xml b/res/layout-xlarge/contact_editor_activity.xml
index c146515..b9f98a3 100644
--- a/res/layout-xlarge/contact_editor_activity.xml
+++ b/res/layout-xlarge/contact_editor_activity.xml
@@ -28,11 +28,11 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             ex:layout_wideParentWidth="1280dip"
-            ex:layout_wideLeftMargin="160dip"
-            ex:layout_wideRightMargin="160dip"
+            ex:layout_wideMarginLeft="160dip"
+            ex:layout_wideMarginRight="160dip"
             ex:layout_narrowParentWidth="800dip"
-            ex:layout_narrowLeftMargin="0dip"
-            ex:layout_narrowRightMargin="0dip"
+            ex:layout_narrowMarginLeft="0dip"
+            ex:layout_narrowMarginRight="0dip"
          />
     </com.android.contacts.widget.InterpolatingLayout>
 </ScrollView>
diff --git a/res/layout-xlarge/external_raw_contact_editor_view.xml b/res/layout-xlarge/external_raw_contact_editor_view.xml
index ffda3a5..156a5a9 100644
--- a/res/layout-xlarge/external_raw_contact_editor_view.xml
+++ b/res/layout-xlarge/external_raw_contact_editor_view.xml
@@ -45,11 +45,11 @@
                 android:layout_height="wrap_content"
                 android:orientation="vertical"
                 ex:layout_wideParentWidth="960dip"
-                ex:layout_wideLeftMargin="96dip"
-                ex:layout_wideRightMargin="96dip"
+                ex:layout_wideMarginLeft="96dip"
+                ex:layout_wideMarginRight="96dip"
                 ex:layout_narrowParentWidth="800dip"
-                ex:layout_narrowLeftMargin="15dip"
-                ex:layout_narrowRightMargin="15dip">
+                ex:layout_narrowMarginLeft="15dip"
+                ex:layout_narrowMarginRight="15dip">
 
                 <TextView
                     android:id="@+id/read_only_name"
@@ -100,11 +100,11 @@
                 android:id="@+id/button_edit_externally"
                 android:text="@string/edit_contact"
                 ex:layout_wideParentWidth="960dip"
-                ex:layout_wideLeftMargin="240dip"
-                ex:layout_wideRightMargin="190dip"
+                ex:layout_wideMarginLeft="240dip"
+                ex:layout_wideMarginRight="190dip"
                 ex:layout_narrowParentWidth="800dip"
-                ex:layout_narrowLeftMargin="160dip"
-                ex:layout_narrowRightMargin="102dip"
+                ex:layout_narrowMarginLeft="160dip"
+                ex:layout_narrowMarginRight="102dip"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
             />
diff --git a/res/layout-xlarge/raw_contact_editor_photo.xml b/res/layout-xlarge/raw_contact_editor_photo.xml
index b1b86fb..4da7b4a 100644
--- a/res/layout-xlarge/raw_contact_editor_photo.xml
+++ b/res/layout-xlarge/raw_contact_editor_photo.xml
@@ -24,9 +24,9 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         ex:layout_wideParentWidth="960dip"
-        ex:layout_wideLeftMargin="96dip"
+        ex:layout_wideMarginLeft="96dip"
         ex:layout_narrowParentWidth="800dip"
-        ex:layout_narrowLeftMargin="15dip">
+        ex:layout_narrowMarginLeft="15dip">
 
         <include
             android:id="@+id/edit_photo"
diff --git a/res/layout-xlarge/raw_contact_editor_view.xml b/res/layout-xlarge/raw_contact_editor_view.xml
index 3560fa6..fecdd1f 100644
--- a/res/layout-xlarge/raw_contact_editor_view.xml
+++ b/res/layout-xlarge/raw_contact_editor_view.xml
@@ -46,11 +46,11 @@
                 android:layout_height="wrap_content"
                 android:orientation="vertical"
                 ex:layout_wideParentWidth="960dip"
-                ex:layout_wideLeftMargin="96dip"
-                ex:layout_wideRightMargin="96dip"
+                ex:layout_wideMarginLeft="96dip"
+                ex:layout_wideMarginRight="96dip"
                 ex:layout_narrowParentWidth="800dip"
-                ex:layout_narrowLeftMargin="15dip"
-                ex:layout_narrowRightMargin="15dip"
+                ex:layout_narrowMarginLeft="15dip"
+                ex:layout_narrowMarginRight="15dip"
                 >
 
                 <com.android.contacts.editor.TextFieldsEditorView
@@ -87,11 +87,11 @@
                 android:id="@+id/button_add_field"
                 android:text="@string/add_field"
                 ex:layout_wideParentWidth="960dip"
-                ex:layout_wideLeftMargin="240dip"
-                ex:layout_wideRightMargin="190dip"
+                ex:layout_wideMarginLeft="240dip"
+                ex:layout_wideMarginRight="190dip"
                 ex:layout_narrowParentWidth="800dip"
-                ex:layout_narrowLeftMargin="160dip"
-                ex:layout_narrowRightMargin="102dip"
+                ex:layout_narrowMarginLeft="160dip"
+                ex:layout_narrowMarginRight="102dip"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
             />
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index a6097aa..3b249b3 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -126,11 +126,11 @@
         />
 
         <ImageView android:id="@+id/secondary_action_button"
-            android:layout_width="30dip"
+            android:layout_width="58dip"
             android:layout_height="match_parent"
             android:layout_centerVertical="true"
-            android:layout_marginLeft="14dip"
-            android:layout_marginRight="14dip"
+            android:paddingLeft="14dip"
+            android:paddingRight="14dip"
             android:gravity="center"
             android:scaleType="center"
             android:background="@android:drawable/list_selector_background"
diff --git a/res/values-es-rUS-xlarge/strings.xml b/res/values-es-rUS-xlarge/strings.xml
index 60ca735..a079382 100644
--- a/res/values-es-rUS-xlarge/strings.xml
+++ b/res/values-es-rUS-xlarge/strings.xml
@@ -88,6 +88,10 @@
     <!-- XL -->
     <string name="delete_group_dialog_message" msgid="6739622355328278915">"¿Estás seguro de que deseas eliminar el grupo \"<xliff:g id="GROUP_LABEL">%1$s</xliff:g>\"? (Los contactos no se eliminarán)."</string>
     <!-- XL -->
+    <string name="vcard_import_will_start_message_with_default_name" msgid="1059778205923280983">"El archivo se importará en unos instantes."</string>
+    <!-- XL -->
+    <string name="vcard_unknown_filename" msgid="3712595870046783485">"contacto"</string>
+    <!-- XL -->
     <string name="cancel_confirmation_dialog_title" msgid="4188526687652041851">"Descartar cambios"</string>
     <!-- XL -->
     <string name="cancel_confirmation_dialog_message" msgid="3455412448990434834">"¿Deseas descartar las modificaciones?"</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 87f7b94..18e694b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -173,16 +173,16 @@
     <declare-styleable name="InterpolatingLayout_Layout">
         <attr name="layout_narrowParentWidth" format="dimension"/>
         <attr name="layout_narrowWidth" format="dimension"/>
-        <attr name="layout_narrowLeftMargin" format="dimension"/>
-        <attr name="layout_narrowLeftPadding" format="dimension"/>
-        <attr name="layout_narrowRightMargin" format="dimension"/>
-        <attr name="layout_narrowRightPadding" format="dimension"/>
+        <attr name="layout_narrowMarginLeft" format="dimension"/>
+        <attr name="layout_narrowMarginRight" format="dimension"/>
+        <attr name="layout_narrowPaddingLeft" format="dimension"/>
+        <attr name="layout_narrowPaddingRight" format="dimension"/>
         <attr name="layout_wideParentWidth" format="dimension"/>
         <attr name="layout_wideWidth" format="dimension"/>
-        <attr name="layout_wideLeftMargin" format="dimension"/>
-        <attr name="layout_wideLeftPadding" format="dimension"/>
-        <attr name="layout_wideRightMargin" format="dimension"/>
-        <attr name="layout_wideRightPadding" format="dimension"/>
+        <attr name="layout_wideMarginLeft" format="dimension"/>
+        <attr name="layout_wideMarginRight" format="dimension"/>
+        <attr name="layout_widePaddingLeft" format="dimension"/>
+        <attr name="layout_widePaddingRight" format="dimension"/>
     </declare-styleable>
     
     <declare-styleable name="TransitionAnimationView">
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 7157e88..309ee84 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -950,9 +950,12 @@
             Drawable secondaryActionIcon = null;
             if (entry.secondaryActionIcon != -1) {
                 secondaryActionIcon = resources.getDrawable(entry.secondaryActionIcon);
-            } else if (entry.chatCapability != 0) {
-                secondaryActionIcon = ContactPresenceIconUtil.getChatCapabilityIcon(
-                        mContext, entry.presence, entry.chatCapability);
+            } else if ((entry.chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
+                secondaryActionIcon =
+                        resources.getDrawable(R.drawable.sym_action_videochat_holo_light);
+            } else if ((entry.chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
+                secondaryActionIcon =
+                        resources.getDrawable(R.drawable.sym_action_audiochat_holo_light);
             }
 
             if (entry.secondaryIntent != null && secondaryActionIcon != null) {
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index 0563b6d..06bb9bd 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -97,7 +97,7 @@
     private Context mContext;
     private AccountManager mAccountManager;
 
-    private AccountType mFallbackAccountType = new FallbackAccountType();
+    private AccountType mFallbackAccountType;
 
     private ArrayList<Account> mAccounts = Lists.newArrayList();
     private ArrayList<Account> mWritableAccounts = Lists.newArrayList();
@@ -139,6 +139,8 @@
      */
     public AccountTypeManagerImpl(Context context) {
         mContext = context;
+        mFallbackAccountType = new FallbackAccountType(context);
+
         mAccountManager = AccountManager.get(mContext);
 
         mListenerThread = new HandlerThread("AccountChangeListener");
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
new file mode 100644
index 0000000..dbfeae4
--- /dev/null
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2009 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.model;
+
+import com.android.contacts.R;
+import com.google.android.collect.Lists;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Event;
+import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Nickname;
+import android.provider.ContactsContract.CommonDataKinds.Note;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.Relation;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
+import android.view.inputmethod.EditorInfo;
+
+public class BaseAccountType extends AccountType {
+    protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
+    protected static final int FLAGS_EMAIL = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+    protected static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
+    protected static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC;
+    protected static final int FLAGS_GENERIC_NAME = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
+    protected static final int FLAGS_NOTE = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
+    protected static final int FLAGS_EVENT = EditorInfo.TYPE_CLASS_TEXT;
+    protected static final int FLAGS_WEBSITE = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_VARIATION_URI;
+    protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS
+            | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
+    protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;  // since SIP addresses have the same
+                                                             // basic format as email addresses
+
+    public BaseAccountType() {
+        this.accountType = null;
+        this.titleRes = R.string.account_phone;
+        this.iconRes = R.mipmap.ic_launcher_contacts;
+    }
+
+    protected EditType buildPhoneType(int type) {
+        return new EditType(type, Phone.getTypeLabelResource(type))
+                .setUnspecifiedType(type == Phone.TYPE_OTHER);
+    }
+
+    protected EditType buildEmailType(int type) {
+        return new EditType(type, Email.getTypeLabelResource(type))
+                .setUnspecifiedType(type == Email.TYPE_OTHER);
+    }
+
+    protected EditType buildPostalType(int type) {
+        return new EditType(type, StructuredPostal.getTypeLabelResource(type))
+                .setUnspecifiedType(type == StructuredPostal.TYPE_OTHER);
+    }
+
+    protected EditType buildImType(int type) {
+        return new EditType(type, Im.getProtocolLabelResource(type))
+                .setUnspecifiedType(type == Im.TYPE_OTHER);
+    }
+
+    protected EditType buildEventType(int type, boolean yearOptional) {
+        return new EventEditType(type, Event.getTypeResource(type)).setYearOptional(yearOptional)
+                .setUnspecifiedType(type == Event.TYPE_OTHER);
+    }
+
+    protected EditType buildRelationType(int type) {
+        return new EditType(type, Relation.getTypeLabelResource(type));
+    }
+
+    protected DataKind addDataKindStructuredName(Context 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.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
+                R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true));
+
+        boolean displayOrderPrimary =
+                context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
+
+        if (!displayOrderPrimary) {
+            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).setLongForm(true));
+            kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
+                    R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true));
+            kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
+                    R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true));
+        } else {
+            kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
+                    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.MIDDLE_NAME, R.string.name_middle,
+                    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.SUFFIX, R.string.name_suffix,
+                    FLAGS_PERSON_NAME).setLongForm(true));
+            kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
+                    R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true));
+            kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
+                    R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true));
+            kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
+                    R.string.name_phonetic_family, FLAGS_PHONETIC).setLongForm(true));
+        }
+
+        return kind;
+    }
+
+    protected DataKind addDataKindNickname(Context context) {
+        DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
+                    R.string.nicknameLabelsGroup, -1, 115, true));
+
+        kind.isList = false;
+        kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
+        kind.actionBody = new SimpleInflater(Nickname.NAME);
+        kind.defaultValues = new ContentValues();
+        kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT);
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup,
+                FLAGS_PERSON_NAME));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindPhone(Context context) {
+        DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
+                android.R.drawable.sym_action_call, 10, true));
+        kind.iconAltRes = R.drawable.sym_action_sms;
+        kind.actionHeader = new PhoneActionInflater();
+        kind.actionAltHeader = new PhoneActionAltInflater();
+        kind.actionBody = new SimpleInflater(Phone.NUMBER);
+        kind.typeColumn = Phone.TYPE;
+        kind.typeList = Lists.newArrayList();
+        kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
+        kind.typeList.add(
+                buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Phone.LABEL));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_CALLBACK).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_ISDN).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER_FAX).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_TELEX).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_TTY_TDD).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_MOBILE).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_PAGER).setSecondary(true));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true).setCustomColumn(
+                Phone.LABEL));
+        kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true));
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindEmail(Context context) {
+        DataKind kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE, R.string.emailLabelsGroup,
+                R.drawable.sym_action_email_holo_light, 15, true));
+        kind.actionHeader = new EmailActionInflater();
+        kind.actionBody = new SimpleInflater(Email.DATA);
+        kind.typeColumn = Email.TYPE;
+        kind.typeList = Lists.newArrayList();
+        kind.typeList.add(buildEmailType(Email.TYPE_HOME));
+        kind.typeList.add(buildEmailType(Email.TYPE_WORK));
+        kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
+        kind.typeList.add(buildEmailType(Email.TYPE_MOBILE));
+        kind.typeList.add(
+                buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Email.LABEL));
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindStructuredPostal(Context context) {
+        DataKind kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
+                R.string.postalLabelsGroup, R.drawable.sym_action_show_map_holo_light, 25,
+                true));
+        kind.actionHeader = new PostalActionInflater();
+        kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
+        kind.typeColumn = StructuredPostal.TYPE;
+        kind.typeList = Lists.newArrayList();
+        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME));
+        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK));
+        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER));
+        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_CUSTOM).setSecondary(true)
+                .setCustomColumn(StructuredPostal.LABEL));
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(
+                new EditField(StructuredPostal.FORMATTED_ADDRESS, R.string.postal_address,
+                        FLAGS_POSTAL).setMinLines(3));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindIm(Context context) {
+        DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup,
+                    R.drawable.sym_action_talk_holo_light, 20, true));
+        kind.actionHeader = new ImActionInflater();
+        kind.actionBody = new SimpleInflater(Im.DATA);
+
+        // NOTE: even though a traditional "type" exists, for editing
+        // purposes we're using the protocol to pick labels
+
+        kind.defaultValues = new ContentValues();
+        kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER);
+
+        kind.typeColumn = Im.PROTOCOL;
+        kind.typeList = Lists.newArrayList();
+        kind.typeList.add(buildImType(Im.PROTOCOL_AIM));
+        kind.typeList.add(buildImType(Im.PROTOCOL_MSN));
+        kind.typeList.add(buildImType(Im.PROTOCOL_YAHOO));
+        kind.typeList.add(buildImType(Im.PROTOCOL_SKYPE));
+        kind.typeList.add(buildImType(Im.PROTOCOL_QQ));
+        kind.typeList.add(buildImType(Im.PROTOCOL_GOOGLE_TALK));
+        kind.typeList.add(buildImType(Im.PROTOCOL_ICQ));
+        kind.typeList.add(buildImType(Im.PROTOCOL_JABBER));
+        kind.typeList.add(buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true).setCustomColumn(
+                Im.CUSTOM_PROTOCOL));
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindOrganization(Context context) {
+        DataKind kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
+                    R.string.organizationLabelsGroup, -1, 5, true));
+        kind.actionHeader = new SimpleInflater(Organization.COMPANY);
+        kind.actionBody = new SimpleInflater(Organization.TITLE);
+        kind.isList = false;
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company,
+                FLAGS_GENERIC_NAME));
+        kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title,
+                FLAGS_GENERIC_NAME));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindPhoto(Context context) {
+        DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, -1, true));
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
+        return kind;
+    }
+
+    protected DataKind addDataKindNote(Context context) {
+        DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE,
+                    R.string.label_notes, -1, 110, true));
+        kind.isList = false;
+        kind.actionHeader = new SimpleInflater(R.string.label_notes);
+        kind.actionBody = new SimpleInflater(Note.NOTE);
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindWebsite(Context context) {
+        DataKind kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
+                R.string.websiteLabelsGroup, R.drawable.sym_action_goto_website_holo_light, 120,
+                true));
+        kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
+        kind.actionBody = new SimpleInflater(Website.URL);
+        kind.defaultValues = new ContentValues();
+        kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER);
+
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindSipAddress(Context context) {
+        // The icon specified here is the one that gets displayed for
+        // "Internet call" items, in the "view contact" UI within the
+        // Contacts app.
+        //
+        // This is independent of the "SIP call" icon that gets
+        // displayed in the Quick Contacts widget, which comes from
+        // the android:icon attribute of the SIP-related
+        // intent-filters in the Phone app's manifest.
+        DataKind kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
+                    R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true));
+
+        kind.isList = false;
+        kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
+        kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS);
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS,
+                                         R.string.label_sip_address, FLAGS_SIP_ADDRESS));
+
+        return kind;
+    }
+
+    protected DataKind addDataKindGroupMembership(Context context) {
+        DataKind kind = getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
+        kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE,
+                R.string.groupsLabel, android.R.drawable.sym_contact_card, 999, true));
+
+        kind.isList = false;
+        kind.fieldList = Lists.newArrayList();
+        kind.fieldList.add(new EditField(GroupMembership.GROUP_ROW_ID, -1, -1));
+
+        return kind;
+    }
+
+    /**
+     * Simple inflater that assumes a string resource has a "%s" that will be
+     * filled from the given column.
+     */
+    public static class SimpleInflater implements StringInflater {
+        private final int mStringRes;
+        private final String mColumnName;
+
+        public SimpleInflater(int stringRes) {
+            this(stringRes, null);
+        }
+
+        public SimpleInflater(String columnName) {
+            this(-1, columnName);
+        }
+
+        public SimpleInflater(int stringRes, String columnName) {
+            mStringRes = stringRes;
+            mColumnName = columnName;
+        }
+
+        public CharSequence inflateUsing(Context context, Cursor cursor) {
+            final int index = mColumnName != null ? cursor.getColumnIndex(mColumnName) : -1;
+            final boolean validString = mStringRes > 0;
+            final boolean validColumn = index != -1;
+
+            final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
+            final CharSequence columnValue = validColumn ? cursor.getString(index) : null;
+
+            if (validString && validColumn) {
+                return String.format(stringValue.toString(), columnValue);
+            } else if (validString) {
+                return stringValue;
+            } else if (validColumn) {
+                return columnValue;
+            } else {
+                return null;
+            }
+        }
+
+        public CharSequence inflateUsing(Context context, ContentValues values) {
+            final boolean validColumn = values.containsKey(mColumnName);
+            final boolean validString = mStringRes > 0;
+
+            final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
+            final CharSequence columnValue = validColumn ? values.getAsString(mColumnName) : null;
+
+            if (validString && validColumn) {
+                return String.format(stringValue.toString(), columnValue);
+            } else if (validString) {
+                return stringValue;
+            } else if (validColumn) {
+                return columnValue;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    public static abstract class CommonInflater implements StringInflater {
+        protected abstract int getTypeLabelResource(Integer type);
+
+        protected boolean isCustom(Integer type) {
+            return type == BaseTypes.TYPE_CUSTOM;
+        }
+
+        protected String getTypeColumn() {
+            return Phone.TYPE;
+        }
+
+        protected String getLabelColumn() {
+            return Phone.LABEL;
+        }
+
+        protected CharSequence getTypeLabel(Resources res, Integer type, CharSequence label) {
+            final int labelRes = getTypeLabelResource(type);
+            if (type == null) {
+                return res.getText(labelRes);
+            } else if (isCustom(type)) {
+                return res.getString(labelRes, label == null ? "" : label);
+            } else {
+                return res.getText(labelRes);
+            }
+        }
+
+        public CharSequence inflateUsing(Context context, Cursor cursor) {
+            final Integer type = cursor.getInt(cursor.getColumnIndex(getTypeColumn()));
+            final String label = cursor.getString(cursor.getColumnIndex(getLabelColumn()));
+            return getTypeLabel(context.getResources(), type, label);
+        }
+
+        public CharSequence inflateUsing(Context context, ContentValues values) {
+            final Integer type = values.getAsInteger(getTypeColumn());
+            final String label = values.getAsString(getLabelColumn());
+            return getTypeLabel(context.getResources(), type, label);
+        }
+    }
+
+    public static class PhoneActionInflater extends CommonInflater {
+        @Override
+        protected boolean isCustom(Integer type) {
+            return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
+        }
+
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            if (type == null) return R.string.call_other;
+            switch (type) {
+                case Phone.TYPE_HOME: return R.string.call_home;
+                case Phone.TYPE_MOBILE: return R.string.call_mobile;
+                case Phone.TYPE_WORK: return R.string.call_work;
+                case Phone.TYPE_FAX_WORK: return R.string.call_fax_work;
+                case Phone.TYPE_FAX_HOME: return R.string.call_fax_home;
+                case Phone.TYPE_PAGER: return R.string.call_pager;
+                case Phone.TYPE_OTHER: return R.string.call_other;
+                case Phone.TYPE_CALLBACK: return R.string.call_callback;
+                case Phone.TYPE_CAR: return R.string.call_car;
+                case Phone.TYPE_COMPANY_MAIN: return R.string.call_company_main;
+                case Phone.TYPE_ISDN: return R.string.call_isdn;
+                case Phone.TYPE_MAIN: return R.string.call_main;
+                case Phone.TYPE_OTHER_FAX: return R.string.call_other_fax;
+                case Phone.TYPE_RADIO: return R.string.call_radio;
+                case Phone.TYPE_TELEX: return R.string.call_telex;
+                case Phone.TYPE_TTY_TDD: return R.string.call_tty_tdd;
+                case Phone.TYPE_WORK_MOBILE: return R.string.call_work_mobile;
+                case Phone.TYPE_WORK_PAGER: return R.string.call_work_pager;
+                case Phone.TYPE_ASSISTANT: return R.string.call_assistant;
+                case Phone.TYPE_MMS: return R.string.call_mms;
+                default: return R.string.call_custom;
+            }
+        }
+    }
+
+    public static class PhoneActionAltInflater extends CommonInflater {
+        @Override
+        protected boolean isCustom(Integer type) {
+            return (type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT);
+        }
+
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            if (type == null) return R.string.sms_other;
+            switch (type) {
+                case Phone.TYPE_HOME: return R.string.sms_home;
+                case Phone.TYPE_MOBILE: return R.string.sms_mobile;
+                case Phone.TYPE_WORK: return R.string.sms_work;
+                case Phone.TYPE_FAX_WORK: return R.string.sms_fax_work;
+                case Phone.TYPE_FAX_HOME: return R.string.sms_fax_home;
+                case Phone.TYPE_PAGER: return R.string.sms_pager;
+                case Phone.TYPE_OTHER: return R.string.sms_other;
+                case Phone.TYPE_CALLBACK: return R.string.sms_callback;
+                case Phone.TYPE_CAR: return R.string.sms_car;
+                case Phone.TYPE_COMPANY_MAIN: return R.string.sms_company_main;
+                case Phone.TYPE_ISDN: return R.string.sms_isdn;
+                case Phone.TYPE_MAIN: return R.string.sms_main;
+                case Phone.TYPE_OTHER_FAX: return R.string.sms_other_fax;
+                case Phone.TYPE_RADIO: return R.string.sms_radio;
+                case Phone.TYPE_TELEX: return R.string.sms_telex;
+                case Phone.TYPE_TTY_TDD: return R.string.sms_tty_tdd;
+                case Phone.TYPE_WORK_MOBILE: return R.string.sms_work_mobile;
+                case Phone.TYPE_WORK_PAGER: return R.string.sms_work_pager;
+                case Phone.TYPE_ASSISTANT: return R.string.sms_assistant;
+                case Phone.TYPE_MMS: return R.string.sms_mms;
+                default: return R.string.sms_custom;
+            }
+        }
+    }
+
+    public static class EmailActionInflater extends CommonInflater {
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            if (type == null) return R.string.email;
+            switch (type) {
+                case Email.TYPE_HOME: return R.string.email_home;
+                case Email.TYPE_WORK: return R.string.email_work;
+                case Email.TYPE_OTHER: return R.string.email_other;
+                case Email.TYPE_MOBILE: return R.string.email_mobile;
+                default: return R.string.email_custom;
+            }
+        }
+    }
+
+    public static class EventActionInflater extends CommonInflater {
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            return Event.getTypeResource(type);
+        }
+    }
+
+    public static class RelationActionInflater extends CommonInflater {
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            return Relation.getTypeLabelResource(type == null ? Relation.TYPE_CUSTOM : type);
+        }
+    }
+
+    public static class PostalActionInflater extends CommonInflater {
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            if (type == null) return R.string.map_other;
+            switch (type) {
+                case StructuredPostal.TYPE_HOME: return R.string.map_home;
+                case StructuredPostal.TYPE_WORK: return R.string.map_work;
+                case StructuredPostal.TYPE_OTHER: return R.string.map_other;
+                default: return R.string.map_custom;
+            }
+        }
+    }
+
+    public static class ImActionInflater extends CommonInflater {
+        @Override
+        protected String getTypeColumn() {
+            return Im.PROTOCOL;
+        }
+
+        @Override
+        protected String getLabelColumn() {
+            return Im.CUSTOM_PROTOCOL;
+        }
+
+        @Override
+        protected int getTypeLabelResource(Integer type) {
+            if (type == null) return R.string.chat;
+            switch (type) {
+                case Im.PROTOCOL_AIM: return R.string.chat_aim;
+                case Im.PROTOCOL_MSN: return R.string.chat_msn;
+                case Im.PROTOCOL_YAHOO: return R.string.chat_yahoo;
+                case Im.PROTOCOL_SKYPE: return R.string.chat_skype;
+                case Im.PROTOCOL_QQ: return R.string.chat_qq;
+                case Im.PROTOCOL_GOOGLE_TALK: return R.string.chat_gtalk;
+                case Im.PROTOCOL_ICQ: return R.string.chat_icq;
+                case Im.PROTOCOL_JABBER: return R.string.chat_jabber;
+                case Im.PROTOCOL_NETMEETING: return R.string.chat;
+                default: return R.string.chat;
+            }
+        }
+    }
+
+    @Override
+    public int getHeaderColor(Context context) {
+        return 0xff7f93bc;
+    }
+
+    @Override
+    public int getSideBarColor(Context context) {
+        return 0xffbdc7b8;
+    }
+}
diff --git a/src/com/android/contacts/model/ExchangeAccountType.java b/src/com/android/contacts/model/ExchangeAccountType.java
index 490078a..4442a70 100644
--- a/src/com/android/contacts/model/ExchangeAccountType.java
+++ b/src/com/android/contacts/model/ExchangeAccountType.java
@@ -37,7 +37,7 @@
 
 import java.util.Locale;
 
-public class ExchangeAccountType extends FallbackAccountType {
+public class ExchangeAccountType extends BaseAccountType {
 
     public static final String ACCOUNT_TYPE = "com.android.exchange";
 
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index adf4469..0b895f6 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/ExternalAccountType.java
@@ -36,7 +36,7 @@
 /**
  * A general contacts account type descriptor.
  */
-public class ExternalAccountType extends FallbackAccountType {
+public class ExternalAccountType extends BaseAccountType {
     private static final String TAG = "ExternalAccountType";
 
     private static final String ACTION_SYNC_ADAPTER = "android.content.SyncAdapter";
diff --git a/src/com/android/contacts/model/FallbackAccountType.java b/src/com/android/contacts/model/FallbackAccountType.java
index 0c71f9b..05e6556 100644
--- a/src/com/android/contacts/model/FallbackAccountType.java
+++ b/src/com/android/contacts/model/FallbackAccountType.java
@@ -17,587 +17,30 @@
 package com.android.contacts.model;
 
 import com.android.contacts.R;
-import com.google.android.collect.Lists;
 
-import android.content.ContentValues;
 import android.content.Context;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Event;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
-import android.provider.ContactsContract.CommonDataKinds.Note;
-import android.provider.ContactsContract.CommonDataKinds.Organization;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.Relation;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.view.inputmethod.EditorInfo;
 
-public class FallbackAccountType extends AccountType {
-    protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
-    protected static final int FLAGS_EMAIL = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
-    protected static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
-    protected static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC;
-    protected static final int FLAGS_GENERIC_NAME = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
-    protected static final int FLAGS_NOTE = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
-    protected static final int FLAGS_EVENT = EditorInfo.TYPE_CLASS_TEXT;
-    protected static final int FLAGS_WEBSITE = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_VARIATION_URI;
-    protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS
-            | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
-    protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT
-            | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;  // since SIP addresses have the same
-                                                             // basic format as email addresses
+public class FallbackAccountType extends BaseAccountType {
 
-    public FallbackAccountType() {
+    public FallbackAccountType(Context context) {
         this.accountType = null;
         this.titleRes = R.string.account_phone;
         this.iconRes = R.mipmap.ic_launcher_contacts;
-    }
 
-    protected EditType buildPhoneType(int type) {
-        return new EditType(type, Phone.getTypeLabelResource(type))
-                .setUnspecifiedType(type == Phone.TYPE_OTHER);
-    }
+        this.resPackageName = null;
+        this.summaryResPackageName = resPackageName;
 
-    protected EditType buildEmailType(int type) {
-        return new EditType(type, Email.getTypeLabelResource(type))
-                .setUnspecifiedType(type == Email.TYPE_OTHER);
-    }
-
-    protected EditType buildPostalType(int type) {
-        return new EditType(type, StructuredPostal.getTypeLabelResource(type))
-                .setUnspecifiedType(type == StructuredPostal.TYPE_OTHER);
-    }
-
-    protected EditType buildImType(int type) {
-        return new EditType(type, Im.getProtocolLabelResource(type))
-                .setUnspecifiedType(type == Im.TYPE_OTHER);
-    }
-
-    protected EditType buildEventType(int type, boolean yearOptional) {
-        return new EventEditType(type, Event.getTypeResource(type)).setYearOptional(yearOptional)
-                .setUnspecifiedType(type == Event.TYPE_OTHER);
-    }
-
-    protected EditType buildRelationType(int type) {
-        return new EditType(type, Relation.getTypeLabelResource(type));
-    }
-
-    protected DataKind addDataKindStructuredName(Context 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.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
-                R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true));
-
-        boolean displayOrderPrimary =
-                context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
-
-        if (!displayOrderPrimary) {
-            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).setLongForm(true));
-            kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
-                    R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true));
-            kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
-                    R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true));
-        } else {
-            kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
-                    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.MIDDLE_NAME, R.string.name_middle,
-                    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.SUFFIX, R.string.name_suffix,
-                    FLAGS_PERSON_NAME).setLongForm(true));
-            kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
-                    R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true));
-            kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
-                    R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true));
-            kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
-                    R.string.name_phonetic_family, FLAGS_PHONETIC).setLongForm(true));
-        }
-
-        return kind;
-    }
-
-    protected DataKind addDataKindNickname(Context context) {
-        DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
-                    R.string.nicknameLabelsGroup, -1, 115, true));
-
-        kind.isList = false;
-        kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
-        kind.actionBody = new SimpleInflater(Nickname.NAME);
-        kind.defaultValues = new ContentValues();
-        kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT);
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup,
-                FLAGS_PERSON_NAME));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindPhone(Context context) {
-        DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
-                android.R.drawable.sym_action_call, 10, true));
-        kind.iconAltRes = R.drawable.sym_action_sms;
-        kind.actionHeader = new PhoneActionInflater();
-        kind.actionAltHeader = new PhoneActionAltInflater();
-        kind.actionBody = new SimpleInflater(Phone.NUMBER);
-        kind.typeColumn = Phone.TYPE;
-        kind.typeList = Lists.newArrayList();
-        kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
-        kind.typeList.add(
-                buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Phone.LABEL));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_CALLBACK).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_ISDN).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER_FAX).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_TELEX).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_TTY_TDD).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_MOBILE).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_PAGER).setSecondary(true));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true).setCustomColumn(
-                Phone.LABEL));
-        kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true));
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindEmail(Context context) {
-        DataKind kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE, R.string.emailLabelsGroup,
-                R.drawable.sym_action_email_holo_light, 15, true));
-        kind.actionHeader = new EmailActionInflater();
-        kind.actionBody = new SimpleInflater(Email.DATA);
-        kind.typeColumn = Email.TYPE;
-        kind.typeList = Lists.newArrayList();
-        kind.typeList.add(buildEmailType(Email.TYPE_HOME));
-        kind.typeList.add(buildEmailType(Email.TYPE_WORK));
-        kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
-        kind.typeList.add(buildEmailType(Email.TYPE_MOBILE));
-        kind.typeList.add(
-                buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Email.LABEL));
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindStructuredPostal(Context context) {
-        DataKind kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
-                R.string.postalLabelsGroup, R.drawable.sym_action_show_map_holo_light, 25,
-                true));
-        kind.actionHeader = new PostalActionInflater();
-        kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
-        kind.typeColumn = StructuredPostal.TYPE;
-        kind.typeList = Lists.newArrayList();
-        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME));
-        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK));
-        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER));
-        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_CUSTOM).setSecondary(true)
-                .setCustomColumn(StructuredPostal.LABEL));
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(
-                new EditField(StructuredPostal.FORMATTED_ADDRESS, R.string.postal_address,
-                        FLAGS_POSTAL).setMinLines(3));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindIm(Context context) {
-        DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup,
-                    R.drawable.sym_action_talk_holo_light, 20, true));
-        kind.actionHeader = new ImActionInflater();
-        kind.actionBody = new SimpleInflater(Im.DATA);
-
-        // NOTE: even though a traditional "type" exists, for editing
-        // purposes we're using the protocol to pick labels
-
-        kind.defaultValues = new ContentValues();
-        kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER);
-
-        kind.typeColumn = Im.PROTOCOL;
-        kind.typeList = Lists.newArrayList();
-        kind.typeList.add(buildImType(Im.PROTOCOL_AIM));
-        kind.typeList.add(buildImType(Im.PROTOCOL_MSN));
-        kind.typeList.add(buildImType(Im.PROTOCOL_YAHOO));
-        kind.typeList.add(buildImType(Im.PROTOCOL_SKYPE));
-        kind.typeList.add(buildImType(Im.PROTOCOL_QQ));
-        kind.typeList.add(buildImType(Im.PROTOCOL_GOOGLE_TALK));
-        kind.typeList.add(buildImType(Im.PROTOCOL_ICQ));
-        kind.typeList.add(buildImType(Im.PROTOCOL_JABBER));
-        kind.typeList.add(buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true).setCustomColumn(
-                Im.CUSTOM_PROTOCOL));
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindOrganization(Context context) {
-        DataKind kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
-                    R.string.organizationLabelsGroup, -1, 5, true));
-        kind.actionHeader = new SimpleInflater(Organization.COMPANY);
-        kind.actionBody = new SimpleInflater(Organization.TITLE);
-        kind.isList = false;
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company,
-                FLAGS_GENERIC_NAME));
-        kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title,
-                FLAGS_GENERIC_NAME));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindPhoto(Context context) {
-        DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, -1, true));
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
-        return kind;
-    }
-
-    protected DataKind addDataKindNote(Context context) {
-        DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE,
-                    R.string.label_notes, -1, 110, true));
-        kind.isList = false;
-        kind.actionHeader = new SimpleInflater(R.string.label_notes);
-        kind.actionBody = new SimpleInflater(Note.NOTE);
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindWebsite(Context context) {
-        DataKind kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
-                R.string.websiteLabelsGroup, R.drawable.sym_action_goto_website_holo_light, 120,
-                true));
-        kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
-        kind.actionBody = new SimpleInflater(Website.URL);
-        kind.defaultValues = new ContentValues();
-        kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER);
-
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindSipAddress(Context context) {
-        // The icon specified here is the one that gets displayed for
-        // "Internet call" items, in the "view contact" UI within the
-        // Contacts app.
-        //
-        // This is independent of the "SIP call" icon that gets
-        // displayed in the Quick Contacts widget, which comes from
-        // the android:icon attribute of the SIP-related
-        // intent-filters in the Phone app's manifest.
-        DataKind kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
-                    R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true));
-
-        kind.isList = false;
-        kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
-        kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS);
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS,
-                                         R.string.label_sip_address, FLAGS_SIP_ADDRESS));
-
-        return kind;
-    }
-
-    protected DataKind addDataKindGroupMembership(Context context) {
-        DataKind kind = getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
-        kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE,
-                R.string.groupsLabel, android.R.drawable.sym_contact_card, 999, true));
-
-        kind.isList = false;
-        kind.fieldList = Lists.newArrayList();
-        kind.fieldList.add(new EditField(GroupMembership.GROUP_ROW_ID, -1, -1));
-
-        return kind;
-    }
-
-    /**
-     * Simple inflater that assumes a string resource has a "%s" that will be
-     * filled from the given column.
-     */
-    public static class SimpleInflater implements StringInflater {
-        private final int mStringRes;
-        private final String mColumnName;
-
-        public SimpleInflater(int stringRes) {
-            this(stringRes, null);
-        }
-
-        public SimpleInflater(String columnName) {
-            this(-1, columnName);
-        }
-
-        public SimpleInflater(int stringRes, String columnName) {
-            mStringRes = stringRes;
-            mColumnName = columnName;
-        }
-
-        public CharSequence inflateUsing(Context context, Cursor cursor) {
-            final int index = mColumnName != null ? cursor.getColumnIndex(mColumnName) : -1;
-            final boolean validString = mStringRes > 0;
-            final boolean validColumn = index != -1;
-
-            final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
-            final CharSequence columnValue = validColumn ? cursor.getString(index) : null;
-
-            if (validString && validColumn) {
-                return String.format(stringValue.toString(), columnValue);
-            } else if (validString) {
-                return stringValue;
-            } else if (validColumn) {
-                return columnValue;
-            } else {
-                return null;
-            }
-        }
-
-        public CharSequence inflateUsing(Context context, ContentValues values) {
-            final boolean validColumn = values.containsKey(mColumnName);
-            final boolean validString = mStringRes > 0;
-
-            final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
-            final CharSequence columnValue = validColumn ? values.getAsString(mColumnName) : null;
-
-            if (validString && validColumn) {
-                return String.format(stringValue.toString(), columnValue);
-            } else if (validString) {
-                return stringValue;
-            } else if (validColumn) {
-                return columnValue;
-            } else {
-                return null;
-            }
-        }
-    }
-
-    public static abstract class CommonInflater implements StringInflater {
-        protected abstract int getTypeLabelResource(Integer type);
-
-        protected boolean isCustom(Integer type) {
-            return type == BaseTypes.TYPE_CUSTOM;
-        }
-
-        protected String getTypeColumn() {
-            return Phone.TYPE;
-        }
-
-        protected String getLabelColumn() {
-            return Phone.LABEL;
-        }
-
-        protected CharSequence getTypeLabel(Resources res, Integer type, CharSequence label) {
-            final int labelRes = getTypeLabelResource(type);
-            if (type == null) {
-                return res.getText(labelRes);
-            } else if (isCustom(type)) {
-                return res.getString(labelRes, label == null ? "" : label);
-            } else {
-                return res.getText(labelRes);
-            }
-        }
-
-        public CharSequence inflateUsing(Context context, Cursor cursor) {
-            final Integer type = cursor.getInt(cursor.getColumnIndex(getTypeColumn()));
-            final String label = cursor.getString(cursor.getColumnIndex(getLabelColumn()));
-            return getTypeLabel(context.getResources(), type, label);
-        }
-
-        public CharSequence inflateUsing(Context context, ContentValues values) {
-            final Integer type = values.getAsInteger(getTypeColumn());
-            final String label = values.getAsString(getLabelColumn());
-            return getTypeLabel(context.getResources(), type, label);
-        }
-    }
-
-    public static class PhoneActionInflater extends CommonInflater {
-        @Override
-        protected boolean isCustom(Integer type) {
-            return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
-        }
-
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            if (type == null) return R.string.call_other;
-            switch (type) {
-                case Phone.TYPE_HOME: return R.string.call_home;
-                case Phone.TYPE_MOBILE: return R.string.call_mobile;
-                case Phone.TYPE_WORK: return R.string.call_work;
-                case Phone.TYPE_FAX_WORK: return R.string.call_fax_work;
-                case Phone.TYPE_FAX_HOME: return R.string.call_fax_home;
-                case Phone.TYPE_PAGER: return R.string.call_pager;
-                case Phone.TYPE_OTHER: return R.string.call_other;
-                case Phone.TYPE_CALLBACK: return R.string.call_callback;
-                case Phone.TYPE_CAR: return R.string.call_car;
-                case Phone.TYPE_COMPANY_MAIN: return R.string.call_company_main;
-                case Phone.TYPE_ISDN: return R.string.call_isdn;
-                case Phone.TYPE_MAIN: return R.string.call_main;
-                case Phone.TYPE_OTHER_FAX: return R.string.call_other_fax;
-                case Phone.TYPE_RADIO: return R.string.call_radio;
-                case Phone.TYPE_TELEX: return R.string.call_telex;
-                case Phone.TYPE_TTY_TDD: return R.string.call_tty_tdd;
-                case Phone.TYPE_WORK_MOBILE: return R.string.call_work_mobile;
-                case Phone.TYPE_WORK_PAGER: return R.string.call_work_pager;
-                case Phone.TYPE_ASSISTANT: return R.string.call_assistant;
-                case Phone.TYPE_MMS: return R.string.call_mms;
-                default: return R.string.call_custom;
-            }
-        }
-    }
-
-    public static class PhoneActionAltInflater extends CommonInflater {
-        @Override
-        protected boolean isCustom(Integer type) {
-            return (type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT);
-        }
-
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            if (type == null) return R.string.sms_other;
-            switch (type) {
-                case Phone.TYPE_HOME: return R.string.sms_home;
-                case Phone.TYPE_MOBILE: return R.string.sms_mobile;
-                case Phone.TYPE_WORK: return R.string.sms_work;
-                case Phone.TYPE_FAX_WORK: return R.string.sms_fax_work;
-                case Phone.TYPE_FAX_HOME: return R.string.sms_fax_home;
-                case Phone.TYPE_PAGER: return R.string.sms_pager;
-                case Phone.TYPE_OTHER: return R.string.sms_other;
-                case Phone.TYPE_CALLBACK: return R.string.sms_callback;
-                case Phone.TYPE_CAR: return R.string.sms_car;
-                case Phone.TYPE_COMPANY_MAIN: return R.string.sms_company_main;
-                case Phone.TYPE_ISDN: return R.string.sms_isdn;
-                case Phone.TYPE_MAIN: return R.string.sms_main;
-                case Phone.TYPE_OTHER_FAX: return R.string.sms_other_fax;
-                case Phone.TYPE_RADIO: return R.string.sms_radio;
-                case Phone.TYPE_TELEX: return R.string.sms_telex;
-                case Phone.TYPE_TTY_TDD: return R.string.sms_tty_tdd;
-                case Phone.TYPE_WORK_MOBILE: return R.string.sms_work_mobile;
-                case Phone.TYPE_WORK_PAGER: return R.string.sms_work_pager;
-                case Phone.TYPE_ASSISTANT: return R.string.sms_assistant;
-                case Phone.TYPE_MMS: return R.string.sms_mms;
-                default: return R.string.sms_custom;
-            }
-        }
-    }
-
-    public static class EmailActionInflater extends CommonInflater {
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            if (type == null) return R.string.email;
-            switch (type) {
-                case Email.TYPE_HOME: return R.string.email_home;
-                case Email.TYPE_WORK: return R.string.email_work;
-                case Email.TYPE_OTHER: return R.string.email_other;
-                case Email.TYPE_MOBILE: return R.string.email_mobile;
-                default: return R.string.email_custom;
-            }
-        }
-    }
-
-    public static class EventActionInflater extends CommonInflater {
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            return Event.getTypeResource(type);
-        }
-    }
-
-    public static class RelationActionInflater extends CommonInflater {
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            return Relation.getTypeLabelResource(type == null ? Relation.TYPE_CUSTOM : type);
-        }
-    }
-
-    public static class PostalActionInflater extends CommonInflater {
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            if (type == null) return R.string.map_other;
-            switch (type) {
-                case StructuredPostal.TYPE_HOME: return R.string.map_home;
-                case StructuredPostal.TYPE_WORK: return R.string.map_work;
-                case StructuredPostal.TYPE_OTHER: return R.string.map_other;
-                default: return R.string.map_custom;
-            }
-        }
-    }
-
-    public static class ImActionInflater extends CommonInflater {
-        @Override
-        protected String getTypeColumn() {
-            return Im.PROTOCOL;
-        }
-
-        @Override
-        protected String getLabelColumn() {
-            return Im.CUSTOM_PROTOCOL;
-        }
-
-        @Override
-        protected int getTypeLabelResource(Integer type) {
-            if (type == null) return R.string.chat;
-            switch (type) {
-                case Im.PROTOCOL_AIM: return R.string.chat_aim;
-                case Im.PROTOCOL_MSN: return R.string.chat_msn;
-                case Im.PROTOCOL_YAHOO: return R.string.chat_yahoo;
-                case Im.PROTOCOL_SKYPE: return R.string.chat_skype;
-                case Im.PROTOCOL_QQ: return R.string.chat_qq;
-                case Im.PROTOCOL_GOOGLE_TALK: return R.string.chat_gtalk;
-                case Im.PROTOCOL_ICQ: return R.string.chat_icq;
-                case Im.PROTOCOL_JABBER: return R.string.chat_jabber;
-                case Im.PROTOCOL_NETMEETING: return R.string.chat;
-                default: return R.string.chat;
-            }
-        }
+        addDataKindStructuredName(context);
+        addDataKindNickname(context);
+        addDataKindPhone(context);
+        addDataKindEmail(context);
+        addDataKindStructuredPostal(context);
+        addDataKindIm(context);
+        addDataKindOrganization(context);
+        addDataKindPhoto(context);
+        addDataKindNote(context);
+        addDataKindWebsite(context);
+        addDataKindSipAddress(context);
     }
 
     @Override
diff --git a/src/com/android/contacts/model/GoogleAccountType.java b/src/com/android/contacts/model/GoogleAccountType.java
index b9d9b33..d369b28 100644
--- a/src/com/android/contacts/model/GoogleAccountType.java
+++ b/src/com/android/contacts/model/GoogleAccountType.java
@@ -29,7 +29,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Relation;
 import android.view.inputmethod.EditorInfo;
 
-public class GoogleAccountType extends FallbackAccountType {
+public class GoogleAccountType extends BaseAccountType {
     public static final String ACCOUNT_TYPE = "com.google";
     protected static final int FLAGS_RELATION = EditorInfo.TYPE_CLASS_TEXT
     | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index a00f49f..bd59856 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -141,8 +141,9 @@
 
                 if (Constants.MIME_TYPE_VIDEO_CHAT.equals(mimeType)) {
                     if (!TextUtils.isEmpty(data)) {
-                        mIntent = new Intent(
-                                Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
+                        mIntent = new Intent(Intent.ACTION_SENDTO);
+                        mIntent.setDataAndType(Uri.parse("xmpp:" + data + "?call"),
+                                Constants.MIME_TYPE_VIDEO_CHAT);
                     }
                 } else if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
                     final String authority = host.toLowerCase();
diff --git a/src/com/android/contacts/widget/InterpolatingLayout.java b/src/com/android/contacts/widget/InterpolatingLayout.java
index 63fc2f6..96d7347 100644
--- a/src/com/android/contacts/widget/InterpolatingLayout.java
+++ b/src/com/android/contacts/widget/InterpolatingLayout.java
@@ -57,16 +57,16 @@
 
         public int narrowParentWidth;
         public int narrowWidth;
-        public int narrowLeftMargin;
-        public int narrowLeftPadding;
-        public int narrowRightMargin;
-        public int narrowRightPadding;
+        public int narrowMarginLeft;
+        public int narrowPaddingLeft;
+        public int narrowMarginRight;
+        public int narrowPaddingRight;
         public int wideParentWidth;
         public int wideWidth;
-        public int wideLeftMargin;
-        public int wideLeftPadding;
-        public int wideRightMargin;
-        public int wideRightPadding;
+        public int wideMarginLeft;
+        public int widePaddingLeft;
+        public int wideMarginRight;
+        public int widePaddingRight;
         private float widthMultiplier;
         private int widthConstant;
         private float leftMarginMultiplier;
@@ -86,26 +86,26 @@
                     R.styleable.InterpolatingLayout_Layout_layout_narrowParentWidth, -1);
             narrowWidth = a.getDimensionPixelSize(
                     R.styleable.InterpolatingLayout_Layout_layout_narrowWidth, -1);
-            narrowLeftMargin = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_narrowLeftMargin, -1);
-            narrowLeftPadding = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_narrowLeftPadding, -1);
-            narrowRightMargin = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_narrowRightMargin, -1);
-            narrowRightPadding = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_narrowRightPadding, -1);
+            narrowMarginLeft = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_narrowMarginLeft, -1);
+            narrowPaddingLeft = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_narrowPaddingLeft, -1);
+            narrowMarginRight = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_narrowMarginRight, -1);
+            narrowPaddingRight = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_narrowPaddingRight, -1);
             wideParentWidth = a.getDimensionPixelSize(
                     R.styleable.InterpolatingLayout_Layout_layout_wideParentWidth, -1);
             wideWidth = a.getDimensionPixelSize(
                     R.styleable.InterpolatingLayout_Layout_layout_wideWidth, -1);
-            wideLeftMargin = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_wideLeftMargin, -1);
-            wideLeftPadding = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_wideLeftPadding, -1);
-            wideRightMargin = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_wideRightMargin, -1);
-            wideRightPadding = a.getDimensionPixelSize(
-                    R.styleable.InterpolatingLayout_Layout_layout_wideRightPadding, -1);
+            wideMarginLeft = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_wideMarginLeft, -1);
+            widePaddingLeft = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_widePaddingLeft, -1);
+            wideMarginRight = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_wideMarginRight, -1);
+            widePaddingRight = a.getDimensionPixelSize(
+                    R.styleable.InterpolatingLayout_Layout_layout_widePaddingRight, -1);
 
             a.recycle();
 
@@ -115,31 +115,31 @@
                 widthConstant = (int) (narrowWidth - narrowParentWidth * widthMultiplier);
             }
 
-            if (narrowLeftMargin != -1) {
-                leftMarginMultiplier = (float) (wideLeftMargin - narrowLeftMargin)
+            if (narrowMarginLeft != -1) {
+                leftMarginMultiplier = (float) (wideMarginLeft - narrowMarginLeft)
                         / (wideParentWidth - narrowParentWidth);
-                leftMarginConstant = (int) (narrowLeftMargin - narrowParentWidth
+                leftMarginConstant = (int) (narrowMarginLeft - narrowParentWidth
                         * leftMarginMultiplier);
             }
 
-            if (narrowLeftPadding != -1) {
-                leftPaddingMultiplier = (float) (wideLeftPadding - narrowLeftPadding)
+            if (narrowPaddingLeft != -1) {
+                leftPaddingMultiplier = (float) (widePaddingLeft - narrowPaddingLeft)
                         / (wideParentWidth - narrowParentWidth);
-                leftPaddingConstant = (int) (narrowLeftPadding - narrowParentWidth
+                leftPaddingConstant = (int) (narrowPaddingLeft - narrowParentWidth
                         * leftPaddingMultiplier);
             }
 
-            if (narrowRightMargin != -1) {
-                rightMarginMultiplier = (float) (wideRightMargin - narrowRightMargin)
+            if (narrowMarginRight != -1) {
+                rightMarginMultiplier = (float) (wideMarginRight - narrowMarginRight)
                         / (wideParentWidth - narrowParentWidth);
-                rightMarginConstant = (int) (narrowRightMargin - narrowParentWidth
+                rightMarginConstant = (int) (narrowMarginRight - narrowParentWidth
                         * rightMarginMultiplier);
             }
 
-            if (narrowRightPadding != -1) {
-                rightPaddingMultiplier = (float) (wideRightPadding - narrowRightPadding)
+            if (narrowPaddingRight != -1) {
+                rightPaddingMultiplier = (float) (widePaddingRight - narrowPaddingRight)
                         / (wideParentWidth - narrowParentWidth);
-                rightPaddingConstant = (int) (narrowRightPadding - narrowParentWidth
+                rightPaddingConstant = (int) (narrowPaddingRight - narrowParentWidth
                         * rightPaddingMultiplier);
             }
         }
@@ -162,7 +162,7 @@
         }
 
         public int resolveLeftMargin(int parentSize) {
-            if (narrowLeftMargin == -1) {
+            if (narrowMarginLeft == -1) {
                 return leftMargin;
             } else {
                 int w = (int) (parentSize * leftMarginMultiplier) + leftMarginConstant;
@@ -176,7 +176,7 @@
         }
 
         public int resolveRightMargin(int parentSize) {
-            if (narrowRightMargin == -1) {
+            if (narrowMarginRight == -1) {
                 return rightMargin;
             } else {
                 int w = (int) (parentSize * rightMarginMultiplier) + rightMarginConstant;
@@ -289,10 +289,10 @@
                 gravity = Gravity.LEFT | Gravity.TOP;
             }
 
-            if (params.narrowLeftPadding != -1 || params.narrowRightPadding != -1) {
-                int leftPadding = params.narrowLeftPadding == -1 ? child.getPaddingLeft()
+            if (params.narrowPaddingLeft != -1 || params.narrowPaddingRight != -1) {
+                int leftPadding = params.narrowPaddingLeft == -1 ? child.getPaddingLeft()
                         : params.resolveLeftPadding(width);
-                int rightPadding = params.narrowRightPadding == -1 ? child.getPaddingRight()
+                int rightPadding = params.narrowPaddingRight == -1 ? child.getPaddingRight()
                         : params.resolveRightPadding(width);
                 child.setPadding(
                         leftPadding, child.getPaddingTop(), rightPadding, child.getPaddingBottom());
@@ -305,8 +305,7 @@
                     right - left - offset - rightMargin,
                     bottom - top - params.bottomMargin);
 
-            int height = Math.max(child.getMeasuredHeight(), mInRect.height());
-            Gravity.apply(gravity, child.getMeasuredWidth(), height,
+            Gravity.apply(gravity, child.getMeasuredWidth(), child.getMeasuredHeight(),
                     mInRect, mOutRect);
             child.layout(mOutRect.left, mOutRect.top, mOutRect.right, mOutRect.bottom);
 
diff --git a/src/com/android/contacts/widget/TransitionAnimationView.java b/src/com/android/contacts/widget/TransitionAnimationView.java
index 4721c5f..a58a6c9 100644
--- a/src/com/android/contacts/widget/TransitionAnimationView.java
+++ b/src/com/android/contacts/widget/TransitionAnimationView.java
@@ -68,9 +68,9 @@
                 attrs, R.styleable.TransitionAnimationView);
 
         mEnterAnimationId = a.getResourceId(R.styleable.TransitionAnimationView_enterAnimation,
-                android.R.anim.animator_fade_in);
+                android.R.animator.fade_in);
         mExitAnimationId = a.getResourceId(R.styleable.TransitionAnimationView_exitAnimation,
-                android.R.anim.animator_fade_out);
+                android.R.animator.fade_out);
         mClipMargins.left = a.getDimensionPixelOffset(
                 R.styleable.TransitionAnimationView_clipMarginLeft, 0);
         mClipMargins.top = a.getDimensionPixelOffset(
diff --git a/tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java b/tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java
index 132f8f0..912950f 100644
--- a/tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java
+++ b/tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java
@@ -22,7 +22,7 @@
 import com.android.contacts.list.ContactBrowseListFragment;
 import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.FallbackAccountType;
+import com.android.contacts.model.BaseAccountType;
 import com.android.contacts.test.InjectedServices;
 import com.android.contacts.tests.mocks.ContactsMockContext;
 import com.android.contacts.tests.mocks.MockAccountTypeManager;
@@ -86,7 +86,7 @@
         services.setContentResolver(mContext.getContentResolver());
         services.setSharedPreferences(new MockSharedPreferences());
 
-        FallbackAccountType accountType = new FallbackAccountType();
+        AccountType accountType = new BaseAccountType();
         accountType.accountType = TEST_ACCOUNT_TYPE;
 
         Account account = new Account(TEST_ACCOUNT, TEST_ACCOUNT_TYPE);
diff --git a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
index eba60a9..4514e1e 100644
--- a/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
+++ b/tests/src/com/android/contacts/interactions/ContactDeletionInteractionTest.java
@@ -20,7 +20,7 @@
 import com.android.contacts.R;
 import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.FallbackAccountType;
+import com.android.contacts.model.BaseAccountType;
 import com.android.contacts.test.FragmentTestActivity;
 import com.android.contacts.test.InjectedServices;
 import com.android.contacts.tests.mocks.ContactsMockContext;
@@ -77,11 +77,11 @@
         InjectedServices services = new InjectedServices();
         services.setContentResolver(mContext.getContentResolver());
 
-        FallbackAccountType readOnlyAccountType = new FallbackAccountType();
+        AccountType readOnlyAccountType = new BaseAccountType();
         readOnlyAccountType.accountType = READONLY_ACCOUNT_TYPE;
         readOnlyAccountType.readOnly = true;
 
-        FallbackAccountType writableAccountType = new FallbackAccountType();
+        AccountType writableAccountType = new BaseAccountType();
         writableAccountType.accountType = WRITABLE_ACCOUNT_TYPE;
 
         services.setSystemService(AccountTypeManager.ACCOUNT_TYPE_SERVICE,