Fixed up intent MIME-types, add Accounts menu, clean unused.

Cleaned up <intent-filter> entries for INSERT_OR_EDIT and
EDIT to watch for more MIME-types after legacy change-over.

Finished clean-up from display groups by removing deprecated
edit sync groups UI, and unused menu.  Changed
ContactsListActivity to use XML-based menus and added an
"Accounts" link that replaces the edit sync groups.

Finally, hooked up the INSERT case to read extras from any
incoming intents to help with SHOW_OR_CREATE intent testing.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f77a7bb..24becae 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -201,8 +201,9 @@
             <intent-filter>
                 <action android:name="android.intent.action.INSERT_OR_EDIT" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.cursor.item/contact" />
                 <data android:mimeType="vnd.android.cursor.item/person" />
+                <data android:mimeType="vnd.android.cursor.item/contact" />
+                <data android:mimeType="vnd.android.cursor.item/raw_contact" />
             </intent-filter>
 
             <intent-filter>
@@ -311,6 +312,7 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.cursor.item/person" android:host="contacts" />
                 <data android:mimeType="vnd.android.cursor.item/contact" android:host="com.android.contacts" />
+                <data android:mimeType="vnd.android.cursor.item/raw_contact" android:host="com.android.contacts" />
             </intent-filter>
         </activity>
 
@@ -324,13 +326,16 @@
                 <action android:name="android.intent.action.EDIT" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.cursor.item/person" android:host="contacts" />
+                <data android:mimeType="vnd.android.cursor.item/contact" android:host="com.android.contacts" />
                 <data android:mimeType="vnd.android.cursor.item/raw_contact" android:host="com.android.contacts" />
             </intent-filter>
+
             <intent-filter android:label="@string/insertContactDescription">
                 <action android:name="android.intent.action.INSERT" />
                 <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.cursor.dir/person" android:host="contacts" />
-                <data android:mimeType="vnd.android.cursor.dir/contact" android:host="com.android.contacts" />
+                <data android:mimeType="vnd.android.cursor.dir/person" />
+                <data android:mimeType="vnd.android.cursor.dir/contact" />
+                <data android:mimeType="vnd.android.cursor.dir/raw_contact" />
             </intent-filter>
         </activity>
 
@@ -362,11 +367,6 @@
             />
         </activity>        
 
-        <!-- Activity used to select the groups that should be synced -->
-        <activity android:name="ContactsGroupSyncSelector"
-            android:label="@string/seclectSyncGroups_title"
-        />
-
         <!-- Makes .ContactsListActivity the search target for any activity in Contacts -->
         <meta-data android:name="android.app.default_searchable" 
                    android:value=".ContactsListActivity" />
diff --git a/res/menu/display_groups.xml b/res/menu/display_groups.xml
deleted file mode 100644
index 3d1a6b0..0000000
--- a/res/menu/display_groups.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:id="@+id/menu_add"
-        android:icon="@android:drawable/ic_menu_add"
-        android:title="@string/menu_sync_add" />
-
-</menu>
diff --git a/res/menu/list.xml b/res/menu/list.xml
new file mode 100644
index 0000000..12cd28a
--- /dev/null
+++ b/res/menu/list.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/menu_search"
+        android:icon="@android:drawable/ic_menu_search"
+        android:title="@string/menu_search" />
+
+    <item
+        android:id="@+id/menu_add"
+        android:icon="@android:drawable/ic_menu_add"
+        android:title="@string/menu_newContact"
+        android:alphabeticShortcut="n" />
+
+    <item
+        android:id="@+id/menu_display_groups"
+        android:icon="@*android:drawable/ic_menu_allfriends"
+        android:title="@string/menu_displayGroup" />
+
+    <item
+        android:id="@+id/menu_accounts"
+        android:title="@string/menu_accounts" />
+
+    <item
+        android:id="@+id/menu_import"
+        android:icon="@drawable/ic_menu_import_contact"
+        android:title="@string/importFromSim" />
+
+    <item
+        android:id="@+id/menu_export"
+        android:icon="@drawable/ic_menu_export_contact"
+        android:title="@string/export_contact_list" />
+
+</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2278761..050abf9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -816,6 +816,9 @@
     <!-- Shown as the social status snippet for a person when no social updates exist. -->
     <string name="fasttrack_missing_status">No recent updates</string>
 
+    <!-- The menu item to open the list of accounts -->
+    <string name="menu_accounts">Accounts</string>
+
 <!-- TODO: add comments to each of these strings to prepare for translation -->
 <string name="nameLabelsGroup">Name</string>
 <string name="nicknameLabelsGroup">Nickname</string>
diff --git a/src/com/android/contacts/ContactsGroupSyncSelector.java b/src/com/android/contacts/ContactsGroupSyncSelector.java
deleted file mode 100644
index 0384516..0000000
--- a/src/com/android/contacts/ContactsGroupSyncSelector.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2008 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;
-
-import android.accounts.AccountManager;
-import android.accounts.AuthenticatorException;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AccountManagerCallback;
-import android.accounts.OperationCanceledException;
-import android.app.ListActivity;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.os.Bundle;
-import android.provider.Contacts;
-import android.provider.Gmail;
-import android.provider.Contacts.Groups;
-import android.provider.Contacts.Settings;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import java.util.ArrayList;
-import java.io.IOException;
-
-import com.google.android.googlelogin.GoogleLoginServiceConstants;
-
-@Deprecated
-public final class ContactsGroupSyncSelector extends ListActivity implements View.OnClickListener {
-
-    private static final String[] PROJECTION = new String[] {
-            Groups._ID, // 0
-            Groups.NAME, // 1
-            Groups.SHOULD_SYNC, // 2
-            Groups.SYSTEM_ID, // 3
-    };
-    private static final int COLUMN_INDEX_ID = 0;
-    private static final int COLUMN_INDEX_NAME = 1;
-    private static final int COLUMN_INDEX_SHOULD_SYNC = 2;
-    private static final int COLUMN_INDEX_SYSTEM_ID = 3;
-
-    ArrayList<Boolean> mChecked;
-    ArrayList<Long> mGroupIds;
-    boolean mSyncAllGroups;
-    
-    private final class GroupsAdapter extends ArrayAdapter<CharSequence> {
-        public GroupsAdapter(ArrayList<CharSequence> items) {
-            super(ContactsGroupSyncSelector.this,
-                    android.R.layout.simple_list_item_checked,
-                    android.R.id.text1, items);
-        }
-
-        @Override
-        public boolean areAllItemsEnabled() {
-            return mSyncAllGroups; 
-        }
-
-        @Override
-        public boolean isEnabled(int pos) {
-            if (mSyncAllGroups && pos != 0) {
-                return false;
-            } else {
-                return true;
-            }
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            View v = super.getView(position, convertView, parent);
-            if (mSyncAllGroups && position != 0) {
-                v.setEnabled(false);
-            } else {
-                v.setEnabled(true);
-            }
-            return v;
-        }
-    }
-
-    /**
-     * Handles clicks on the list items
-     */
-    @Override
-    protected void onListItemClick(ListView list, View view, int position, long id) {
-        boolean isChecked = list.isItemChecked(position);
-        mChecked.set(position, isChecked);
-        if (position == 0) {
-            mSyncAllGroups = isChecked;
-            adjustChecks();
-        }
-    }
-
-    /**
-     * Handles clicks on the OK and cancel buttons
-     */
-    public void onClick(View view) {
-        switch (view.getId()) {
-            case R.id.cancel: {
-                finish();
-                break;
-            }
-            
-            case R.id.ok: {
-                // The list isn't setup yet, so just return without doing anything.
-                if (mChecked == null) {
-                    finish();
-                    return;
-                }
-
-                final ContentResolver resolver = getContentResolver();
-                if (mSyncAllGroups) {
-                    // For now we only support a single account and the UI doesn't know what
-                    // the account name is, so we're using a global setting for SYNC_EVERYTHING.
-                    // Some day when we add multiple accounts to the UI this should use the per
-                    // account setting.
-                    Settings.setSetting(resolver, null, Settings.SYNC_EVERYTHING, "1");
-                } else {
-                    ContentValues values = new ContentValues();
-                    int count = mChecked.size();
-                    for (int i = 1; i < count; i++) {
-                        values.clear();
-                        values.put(Groups.SHOULD_SYNC, mChecked.get(i));
-                        resolver.update(
-                                ContentUris.withAppendedId(Groups.CONTENT_URI, mGroupIds.get(i)),
-                                values, null, null);
-                    }
-                    // For now we only support a single account and the UI doesn't know what
-                    // the account name is, so we're using a global setting for SYNC_EVERYTHING.
-                    // Some day when we add multiple accounts to the UI this should use the per
-                    // account setting.
-                    Settings.setSetting(resolver, null, Settings.SYNC_EVERYTHING, "0");
-                }
-                finish();
-                break;
-            }
-        }
-    }
-
-    @Override
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-
-        // Only look for an account on first run.
-        if (savedState == null) {
-            // This will request a Gmail account and if none are present, it will
-            // invoke SetupWizard to login or create one. The result is returned
-            // through onActivityResult().
-            Bundle bundle = new Bundle();
-            bundle.putCharSequence("optional_message", getText(R.string.contactsSyncPlug));
-            AccountManager.get(this).getAuthTokenByFeatures(
-                    GoogleLoginServiceConstants.ACCOUNT_TYPE, Gmail.GMAIL_AUTH_SERVICE,
-                    new String[]{GoogleLoginServiceConstants.FEATURE_HOSTED_OR_GOOGLE}, this,
-                    bundle, null /* loginOptions */, new AccountManagerCallback<Bundle>() {
-                public void run(AccountManagerFuture<Bundle> future) {
-                    try {
-                        // do this to check if this request succeeded or not
-                        future.getResult();
-                        // There is an account setup, build the group list
-                        buildItems();
-                        adjustChecks();
-                    } catch (OperationCanceledException e) {
-                        finish();
-                    } catch (IOException e) {
-                        finish();
-                    } catch (AuthenticatorException e) {
-                        finish();
-                    }
-                }
-            }, null /* handler */);
-        }
-
-        setContentView(R.layout.sync_settings);
-
-        findViewById(R.id.ok).setOnClickListener(this);
-        findViewById(R.id.cancel).setOnClickListener(this);
-        
-        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-    }
-
-    private void buildItems() {
-        final ContentResolver resolver = getContentResolver();
-        Cursor cursor = resolver.query(Groups.CONTENT_URI, PROJECTION, null, null, Groups.NAME);
-        if (cursor != null) {
-            try {
-                int count = cursor.getCount() + 1; // add 1 for "sync all"
-                ArrayList<CharSequence> items = new ArrayList<CharSequence>(count);
-                ArrayList<Boolean> checked = new ArrayList<Boolean>(count);
-                ArrayList<Long> groupIds = new ArrayList<Long>(count);
-
-                // The first item in the list is always "sync all"
-                items.add(getString(R.string.syncAllGroups));
-                checked.add(mSyncAllGroups);
-                groupIds.add(Long.valueOf(0)); // dummy entry
-
-                while (cursor.moveToNext()) {
-                    String name = cursor.getString(COLUMN_INDEX_NAME);
-                    String systemId = cursor.isNull(COLUMN_INDEX_SYSTEM_ID) ?
-                            null : cursor.getString(COLUMN_INDEX_SYSTEM_ID);
-                    if (systemId == null || !Groups.GROUP_MY_CONTACTS.equals(systemId)) {
-                        // Localize the "Starred in Android" string which we get from the server
-                        // side.
-                        if (Groups.GROUP_ANDROID_STARRED.equals(name)) {
-                            name = getString(R.string.starredInAndroid);
-                        }
-                        items.add(name);
-                        checked.add(cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0);
-                        groupIds.add(cursor.getLong(COLUMN_INDEX_ID));
-                    } else {
-                        // If My Contacts is around it wants to be the second list entry
-                        items.add(1, getString(R.string.groupNameMyContacts));
-                        checked.add(1, cursor.getInt(COLUMN_INDEX_SHOULD_SYNC) != 0);
-                        groupIds.add(1, cursor.getLong(COLUMN_INDEX_ID));
-                    }
-                }
-                mChecked = checked;
-                mGroupIds = groupIds;
-                mSyncAllGroups = getShouldSyncEverything(resolver);
-    
-                // Setup the adapter
-                setListAdapter(new GroupsAdapter(items));
-            } finally {
-                cursor.close();
-            }
-        }
-    }
-
-    private void adjustChecks() {
-        final ListView list = getListView();
-        if (mSyncAllGroups) {
-            int count = list.getCount();
-            for (int i = 0; i < count; i++) {
-                list.setItemChecked(i, true);
-            }
-        } else {
-            ArrayList<Boolean> checked = mChecked;
-            int count = list.getCount();
-            for (int i = 0; i < count; i++) {
-                list.setItemChecked(i, checked.get(i));
-            }
-        }
-    }
-
-    private static boolean getShouldSyncEverything(ContentResolver cr) {
-        // For now we only support a single account and the UI doesn't know what
-        // the account name is, so we're using a global setting for SYNC_EVERYTHING.
-        // Some day when we add multiple accounts to the UI this should use the per
-        // account setting.
-        String value = Contacts.Settings.getSetting(cr, null, Contacts.Settings.SYNC_EVERYTHING);
-        if (value == null) {
-            // If nothing is set yet we default to syncing everything
-            return true;
-        }
-        return !TextUtils.isEmpty(value) && !"0".equals(value);
-    }
-}
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 8718b10..936396d 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -50,6 +50,7 @@
 import android.os.Parcelable;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract;
+import android.provider.Settings;
 import android.provider.Contacts.ContactMethods;
 import android.provider.Contacts.People;
 import android.provider.Contacts.Phones;
@@ -71,6 +72,7 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
@@ -118,13 +120,6 @@
     static final int MENU_ITEM_DELETE = 7;
     static final int MENU_ITEM_TOGGLE_STAR = 8;
 
-    public static final int MENU_SEARCH = 1;
-    public static final int MENU_DIALER = 9;
-    public static final int MENU_NEW_CONTACT = 10;
-    public static final int MENU_DISPLAY_GROUP = 11;
-    public static final int MENU_IMPORT_CONTACTS = 12;
-    public static final int MENU_EXPORT_CONTACTS = 13;
-
     private static final int SUBACTIVITY_NEW_CONTACT = 1;
     private static final int SUBACTIVITY_VIEW_CONTACT = 2;
     private static final int SUBACTIVITY_DISPLAY_GROUP = 3;
@@ -147,6 +142,8 @@
     public static final String EXTRA_AGGREGATE_ID =
             "com.android.contacts.action.AGGREGATE_ID";
 
+    public static final String AUTHORITIES_FILTER_KEY = "authorities";
+
     /** Mask for picker mode */
     static final int MODE_MASK_PICKER = 0x80000000;
     /** Mask for no presence mode */
@@ -281,7 +278,7 @@
 
     private String mShortcutAction;
     private boolean mDefaultMode = false;
-    
+
     private boolean mCreateShortcut;
 
     /**
@@ -298,7 +295,7 @@
      * provided by scheme-specific part of incoming {@link Intent#getData()}.
      */
     private String mQueryData;
-    
+
     private Handler mHandler = new Handler();
 
     private class ImportTypeSelectedListener implements DialogInterface.OnClickListener {
@@ -502,7 +499,7 @@
         list.setOnCreateContextMenuListener(this);
         if ((mMode & MODE_MASK_NO_FILTER) != MODE_MASK_NO_FILTER) {
             list.setTextFilterEnabled(true);
-        }        
+        }
 
         if ((mMode & MODE_MASK_CREATE_NEW) != 0) {
             // Add the header for creating a new contact
@@ -697,63 +694,48 @@
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+
         // If Contacts was invoked by another Activity simply as a way of
         // picking a contact, don't show the options menu
         if ((mMode & MODE_MASK_PICKER) == MODE_MASK_PICKER) {
             return false;
         }
 
-        // TODO: move this into a resource-based menu
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.list, menu);
+        return true;
+    }
 
-        // Search
-        menu.add(0, MENU_SEARCH, 0, R.string.menu_search)
-                .setIcon(android.R.drawable.ic_menu_search);
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        final boolean defaultMode = (mMode == MODE_DEFAULT);
+        menu.findItem(R.id.menu_display_groups).setVisible(defaultMode);
 
-        // New contact
-        menu.add(0, MENU_NEW_CONTACT, 0, R.string.menu_newContact).setIcon(
-                android.R.drawable.ic_menu_add).setIntent(
-                new Intent(Intents.Insert.ACTION, Contacts.CONTENT_URI)).setAlphabeticShortcut('n');
+        final boolean allowExport = getResources().getBoolean(R.bool.config_allow_export_to_sdcard);
+        menu.findItem(R.id.menu_export).setVisible(allowExport);
 
-        // Display group
-        if (mMode == MODE_DEFAULT) {
-            menu.add(0, MENU_DISPLAY_GROUP, 0, R.string.menu_displayGroup)
-                    .setIcon(com.android.internal.R.drawable.ic_menu_allfriends);
-        }
-
-        // Sync settings
-        if (mSyncEnabled) {
-            Intent syncIntent = new Intent(Intent.ACTION_VIEW);
-            syncIntent.setClass(this, ContactsGroupSyncSelector.class);
-            menu.add(0, 0, 0, R.string.syncGroupPreference)
-                    .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
-                    .setIntent(syncIntent);
-        }
-        
-        // Contacts import (SIM/SDCard)
-        menu.add(0, MENU_IMPORT_CONTACTS, 0, R.string.importFromSim)
-                .setIcon(R.drawable.ic_menu_import_contact);
-
-        if (getResources().getBoolean(R.bool.config_allow_export_to_sdcard)) {
-            menu.add(0, MENU_EXPORT_CONTACTS, 0, R.string.export_contact_list)
-                    .setIcon(R.drawable.ic_menu_export_contact);
-        }
-
-        return super.onCreateOptionsMenu(menu);
+        return true;
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
-            case MENU_DISPLAY_GROUP:
+            case R.id.menu_display_groups: {
                 final Intent intent = new Intent(this, DisplayGroupsActivity.class);
                 startActivityForResult(intent, SUBACTIVITY_DISPLAY_GROUP);
                 return true;
-
-            case MENU_SEARCH:
+            }
+            case R.id.menu_search: {
                 startSearch(null, false, null, false);
                 return true;
-
-            case MENU_IMPORT_CONTACTS:
+            }
+            case R.id.menu_add: {
+                final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+                startActivity(intent);
+                return true;
+            }
+            case R.id.menu_import: {
                 if (getResources().getBoolean(R.bool.config_allow_import_from_sdcard)) {
                     ImportTypeSelectedListener listener =
                             new ImportTypeSelectedListener();
@@ -770,9 +752,19 @@
                     doImportFromSim();
                 }
                 return true;
-
-            case MENU_EXPORT_CONTACTS:
+            }
+            case R.id.menu_export: {
                 handleExportContacts();
+                return true;
+            }
+            case R.id.menu_accounts: {
+                final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
+                intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
+                    ContactsContract.AUTHORITY
+                });
+                startActivity(intent);
+                return true;
+            }
         }
         return false;
     }
@@ -793,7 +785,7 @@
         VCardExporter exporter = new VCardExporter(ContactsListActivity.this, mHandler);
         exporter.startExportVCardToSdCard();
     }
-    
+
     @Override
     protected void onActivityResult(int requestCode, int resultCode,
             Intent data) {
@@ -1050,7 +1042,7 @@
 
     private void returnPickerResult(Cursor c, String name, Uri uri, long id) {
         final Intent intent = new Intent();
-    
+
         if (mShortcutAction != null) {
             Intent shortcutIntent;
             if (Intent.ACTION_VIEW.equals(mShortcutAction)) {
@@ -1080,7 +1072,7 @@
                 // Make the URI a direct tel: URI so that it will always continue to work
                 Uri phoneUri = Uri.fromParts(scheme, number, null);
                 shortcutIntent = new Intent(mShortcutAction, phoneUri);
-                
+
                 // Find the People._ID for this phone number
 /* TODO bring back the better icon handling
                 final long personId = c.getLong(PHONES_PERSON_ID_INDEX);
@@ -1207,7 +1199,7 @@
             return null;
         }
     }
-    
+
     String[] getProjection() {
         switch (mMode) {
             case MODE_PICK_PHONE:
diff --git a/src/com/android/contacts/model/EntityDelta.java b/src/com/android/contacts/model/EntityDelta.java
index 116300f..427cf33 100644
--- a/src/com/android/contacts/model/EntityDelta.java
+++ b/src/com/android/contacts/model/EntityDelta.java
@@ -437,7 +437,8 @@
         }
 
         public boolean isPrimary() {
-            return (getAsLong(Data.IS_PRIMARY) != 0);
+            final Long isPrimary = getAsLong(Data.IS_PRIMARY);
+            return isPrimary == null ? false : isPrimary != 0;
         }
 
         public boolean beforeExists() {
diff --git a/src/com/android/contacts/model/EntityModifier.java b/src/com/android/contacts/model/EntityModifier.java
index 29f4d1c..9da140e 100644
--- a/src/com/android/contacts/model/EntityModifier.java
+++ b/src/com/android/contacts/model/EntityModifier.java
@@ -298,6 +298,11 @@
      * assuming the extras defined through {@link Intents}.
      */
     public static void parseExtras(Context context, ContactsSource source, EntityDelta state, Bundle extras) {
+        if (extras == null || extras.size() == 0) {
+            // Bail early if no useful data
+            return;
+        }
+
         {
             // StructuredName
             final DataKind kind = source.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
@@ -332,7 +337,7 @@
         {
             // Email
             final DataKind kind = source.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
-            parseExtras(state, kind, extras, Insert.EMAIL_TYPE, Insert.PHONE, Email.DATA);
+            parseExtras(state, kind, extras, Insert.EMAIL_TYPE, Insert.EMAIL, Email.DATA);
             parseExtras(state, kind, extras, Insert.SECONDARY_EMAIL_TYPE, Insert.SECONDARY_EMAIL,
                     Email.DATA);
             parseExtras(state, kind, extras, Insert.TERTIARY_EMAIL_TYPE, Insert.TERTIARY_EMAIL,
@@ -363,7 +368,7 @@
 
         // Bail when can't insert type, or value missing
         final boolean canInsert = EntityModifier.canInsert(state, kind);
-        final boolean validValue = TextUtils.isGraphic(value);
+        final boolean validValue = (value != null && TextUtils.isGraphic(value));
         if (!validValue || !canInsert) return;
 
         // Find exact type, or otherwise best type
diff --git a/src/com/android/contacts/ui/EditContactActivity.java b/src/com/android/contacts/ui/EditContactActivity.java
index 4fa6f01..03ef79a 100644
--- a/src/com/android/contacts/ui/EditContactActivity.java
+++ b/src/com/android/contacts/ui/EditContactActivity.java
@@ -23,6 +23,7 @@
 import com.android.contacts.ViewContactActivity;
 import com.android.contacts.model.ContactsSource;
 import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityModifier;
 import com.android.contacts.model.HardCodedSources;
 import com.android.contacts.model.Sources;
 import com.android.contacts.model.EntityDelta.ValuesDelta;
@@ -690,10 +691,10 @@
                     dialog.dismiss();
 
                     // Create new contact based on selected source
-                    final Account source = accountAdapter.getItem(which);
+                    final Account account = accountAdapter.getItem(which);
                     final ContentValues values = new ContentValues();
-                    values.put(RawContacts.ACCOUNT_NAME, source.name);
-                    values.put(RawContacts.ACCOUNT_TYPE, source.type);
+                    values.put(RawContacts.ACCOUNT_NAME, account.name);
+                    values.put(RawContacts.ACCOUNT_TYPE, account.type);
 
                     // Tie this directly to existing aggregate
                     // TODO: this may need to use aggregation exception rules
@@ -702,7 +703,13 @@
                         values.put(RawContacts.CONTACT_ID, aggregateId);
                     }
 
+                    // Parse any values from incoming intent
                     final EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
+                    final ContactsSource source = sources.getInflatedSource(account.type,
+                            ContactsSource.LEVEL_CONSTRAINTS);
+                    final Bundle extras = target.getIntent().getExtras();
+                    EntityModifier.parseExtras(target, source, insert, extras);
+
                     target.mState.add(insert);
 
                     target.bindTabs();