Move handling of primary to quickcontacts

Bug:3212270

Change-Id: I2d35aef0407e02cc4612a66ca09dbcd89b2fe714
diff --git a/res/drawable-hdpi/badge_action_clear_defaults_holo_light.png b/res/drawable-hdpi/badge_action_clear_defaults_holo_light.png
new file mode 100644
index 0000000..6f67b7f
--- /dev/null
+++ b/res/drawable-hdpi/badge_action_clear_defaults_holo_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_default_number.png b/res/drawable-hdpi/ic_default_number.png
deleted file mode 100755
index cdc05a8..0000000
--- a/res/drawable-hdpi/ic_default_number.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/badge_action_clear_defaults_holo_light.png b/res/drawable-mdpi/badge_action_clear_defaults_holo_light.png
new file mode 100644
index 0000000..aba60df
--- /dev/null
+++ b/res/drawable-mdpi/badge_action_clear_defaults_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_default_number.png b/res/drawable-mdpi/ic_default_number.png
deleted file mode 100644
index 30ead23..0000000
--- a/res/drawable-mdpi/ic_default_number.png
+++ /dev/null
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 38221be..252e8d8 100644
--- a/res/layout-xlarge-land/contact_detail_list_item.xml
+++ b/res/layout-xlarge-land/contact_detail_list_item.xml
@@ -72,14 +72,6 @@
             android:textAppearance="?android:attr/textAppearanceSmall"
         />
 
-        <ImageView android:id="@+id/primary_icon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
-            android:paddingLeft="3dip"
-            android:src="@drawable/ic_default_number"
-        />
-
         <TextView
             android:id="@+id/footer"
             android:layout_width="wrap_content"
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index 65d3faa..52744cb 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -76,28 +76,12 @@
             android:gravity="center_vertical"
         >
 
-            <LinearLayout
+            <TextView android:id="@+id/data"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:orientation="horizontal"
-            >
-
-                <TextView android:id="@+id/data"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    android:textAppearance="?android:attr/textAppearanceLarge"
-                />
-
-                <ImageView android:id="@+id/primary_icon"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    android:paddingLeft="3dip"
-                    android:src="@drawable/ic_default_number"
-                />
-
-            </LinearLayout>
+                android:layout_gravity="center_vertical"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+            />
 
             <TextView android:id="@+id/type"
                 android:layout_width="wrap_content"
diff --git a/res/layout/quickcontact.xml b/res/layout/quickcontact.xml
index 94b09df..a74424c 100644
--- a/res/layout/quickcontact.xml
+++ b/res/layout/quickcontact.xml
@@ -68,33 +68,69 @@
             android:orientation="horizontal" />
     </HorizontalScrollView>
 
-    <LinearLayout
-        android:id="@+id/footer_disambig"
+    <FrameLayout
+        android:id="@+id/footer"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
         android:visibility="gone">
-
-        <ListView
-            android:id="@android:id/list"
-            android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:layout_weight="1"
-            android:layout_marginLeft="5dip"
-            android:layout_marginRight="5dip"
-            android:cacheColorHint="@null" />
-
-        <CheckBox
-            android:id="@android:id/checkbox"
+        <LinearLayout
+            android:id="@+id/footer_disambig"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="19dip"
-            android:layout_marginRight="19dip"
-            android:minHeight="60dip"
-            android:textColor="#f000"
-            android:textStyle="bold"
-            android:text="@string/quickcontact_remember_choice"
-            android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+            android:orientation="vertical"
+            android:visibility="gone">
 
-    </LinearLayout>
+            <ListView
+                android:id="@android:id/list"
+                android:layout_width="match_parent"
+                android:layout_height="0dip"
+                android:layout_weight="1"
+                android:layout_marginLeft="5dip"
+                android:layout_marginRight="5dip"
+                android:cacheColorHint="@null" />
+
+            <CheckBox
+                android:id="@android:id/checkbox"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="19dip"
+                android:layout_marginRight="19dip"
+                android:minHeight="60dip"
+                android:textColor="#f000"
+                android:textStyle="bold"
+                android:text="@string/quickcontact_remember_choice"
+                android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/footer_clear_defaults"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:visibility="gone">
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="30dip"
+                android:layout_marginRight="5dip"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:text="@string/quickcontact_clear_defaults_caption" />
+            <ListView
+                android:id="@+id/defaults_list"
+                android:layout_width="match_parent"
+                android:layout_height="0dip"
+                android:layout_weight="1"
+                android:layout_marginLeft="5dip"
+                android:layout_marginRight="5dip"
+                android:cacheColorHint="@null" />
+            <Button
+                android:id="@+id/clear_defaults_button"
+                android:layout_marginLeft="20dip"
+                android:layout_marginBottom="20dip"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/quickcontact_clear_defaults_button" />
+        </LinearLayout>
+    </FrameLayout>
 </view>
diff --git a/res/layout/quickcontact_default_item.xml b/res/layout/quickcontact_default_item.xml
new file mode 100755
index 0000000..25b6910
--- /dev/null
+++ b/res/layout/quickcontact_default_item.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingLeft="25dip"
+    android:paddingRight="25dip"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical">
+
+    <TextView
+        android:id="@android:id/text1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textStyle="bold"
+        android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+
+    <TextView
+        android:id="@android:id/text2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="-4dip"
+        android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+
+</LinearLayout>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 35d5f54..febfb36 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -56,9 +56,6 @@
     <item type="id" name="dialog_manager_id_1"/>
     <item type="id" name="dialog_manager_id_2"/>
 
-    <!-- ContactDetailFragment ContextMenu Ids -->
-    <item type="id" name="menu_detail_makeDefault" />
-
     <!-- Loader ID for contact filters -->
     <item type="id" name="contact_list_filter_loader" />
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fdcc6a7..efabff6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -108,16 +108,6 @@
     <!-- Menu item used to send an SMS or MMS message to a specific phone number or a contacts default phone number -->
     <string name="menu_sendSMS">Text contact</string>
 
-    <!-- Menu item used to send an email message to a specific email address -->
-    <string name="menu_sendEmail">Send email</string>
-
-    <!-- Menu item used to view a contact's address on a map -->
-    <string name="menu_viewAddress">Map address</string>
-
-    <!-- Menu item that makes a phone the default for a contact. The default number used when you
-         try to call a contact without specifying a specific number. -->
-    <string name="menu_makeDefaultNumber">Make default number</string>
-
     <!-- Menu item that makes an email address the default for a contact. The default email used
          when you try to email a contact without specifying a specific address. -->
     <string name="menu_makeDefaultEmail">Make default email</string>
@@ -163,9 +153,6 @@
     <!-- Menu item that opens the Options activity for a given contact -->
     <string name="menu_contactOptions">Options</string>
 
-    <!-- Title for the Options activity for a given contact -->
-    <string name="contactOptionsTitle">Options</string>
-
     <!-- Confirmation dialog title after users selects to delete a contact. -->
     <string name="deleteConfirmation_title">Delete</string>
 
@@ -962,6 +949,17 @@
     <!-- Text that is shown in the Badge, when there is no data to display -->
     <string name="quickcontact_no_data">No data</string>
 
+    <!-- Accessibility description for the button in QuickContacts that allows the user to clear
+    defaults of a contact (like primary email). [CHAR LIMIT=100] -->
+    <string name="quickcontact_clear_defaults_description">Clear defaults</string>
+
+    <!-- Caption that shows above the list of defaults (like primary email). [CHAR LIMIT=40] -->
+    <string name="quickcontact_clear_defaults_caption">Defaults set for this contact:</string>
+
+    <!-- Button caption that allows the user to clear the defaults  (like primary email) of one
+    contact. [CHAR LIMIT=15] -->
+    <string name="quickcontact_clear_defaults_button">Clear</string>
+    
     <!-- The menu item to open the list of accounts -->
     <string name="menu_accounts">Accounts</string>
 
@@ -1454,5 +1452,4 @@
     <string name="toast_join_with_empty_contact">Please enter contact name before joining
       with another contact.
     </string>
-
 </resources>
diff --git a/src/com/android/contacts/interactions/PhoneNumberInteraction.java b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
index c9fe0c6..6a340f3 100644
--- a/src/com/android/contacts/interactions/PhoneNumberInteraction.java
+++ b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
@@ -23,11 +23,11 @@
 import com.android.contacts.model.AccountType.DataKind;
 import com.android.contacts.model.AccountType.StringInflater;
 import com.android.contacts.model.AccountTypes;
+import com.android.contacts.views.ContactSaveService;
 
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.CursorLoader;
@@ -338,11 +338,8 @@
      * Makes the selected phone number primary.
      */
     void makePrimary(long id) {
-        // TODO use a Saver
-        ContentValues values = new ContentValues(1);
-        values.put(Data.IS_SUPER_PRIMARY, 1);
-        Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, id);
-        mContext.getContentResolver().update(uri, values, null, null);
+        final Intent intent = ContactSaveService.createSetSuperPrimaryIntent(mContext, id);
+        mContext.startService(intent);
     }
 
     /* Visible for testing */
diff --git a/src/com/android/contacts/quickcontact/Action.java b/src/com/android/contacts/quickcontact/Action.java
index c9823b7..bdfbe48 100644
--- a/src/com/android/contacts/quickcontact/Action.java
+++ b/src/com/android/contacts/quickcontact/Action.java
@@ -44,7 +44,14 @@
     public Boolean isPrimary();
 
     /**
-     * Returns a lookup (@link Uri) for the contact data item.
+     * Returns a lookup (@link Uri) for the contact data item or null if there is no data item
+     * corresponding to this row
      */
     public Uri getDataUri();
+
+    /**
+     * Returns the id of the contact data item or -1 of there is no data item corresponding to this
+     * row
+     */
+    public long getDataId();
 }
diff --git a/src/com/android/contacts/quickcontact/ClearDefaultsAction.java b/src/com/android/contacts/quickcontact/ClearDefaultsAction.java
new file mode 100644
index 0000000..d1acc6b
--- /dev/null
+++ b/src/com/android/contacts/quickcontact/ClearDefaultsAction.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.quickcontact;
+
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+
+/**
+ * Action that expands to show and allow clearing the currently selected defaults.
+ */
+public class ClearDefaultsAction implements Action {
+    /**
+     * This is a pseudo-mimetype that is only needed for the action list. It has to be
+     * different from the real mime-types used
+     */
+    public static final String PSEUDO_MIME_TYPE = "__clear_defaults_mime_type";
+
+    @Override
+    public boolean collapseWith(Action t) {
+        return false;
+    }
+
+    @Override
+    public boolean shouldCollapseWith(Action t) {
+        return false;
+    }
+
+    @Override
+    public CharSequence getHeader() {
+        return null;
+    }
+
+    @Override
+    public CharSequence getBody() {
+        return null;
+    }
+
+    @Override
+    public String getMimeType() {
+        return PSEUDO_MIME_TYPE;
+    }
+
+    @Override
+    public Drawable getFallbackIcon() {
+        return null;
+    }
+
+    @Override
+    public Intent getIntent() {
+        return null;
+    }
+
+    @Override
+    public Boolean isPrimary() {
+        return null;
+    }
+
+    @Override
+    public Uri getDataUri() {
+        return null;
+    }
+
+    @Override
+    public long getDataId() {
+        return -1;
+    }
+}
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index b4d5454..4593591 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -39,6 +39,7 @@
 
     private boolean mAlternate;
     private Uri mDataUri;
+    private long mDataId;
     private boolean mIsPrimary;
 
     /**
@@ -66,6 +67,7 @@
             mBody = mKind.actionBody.inflateUsing(context, cursor);
         }
 
+        mDataId = dataId;
         mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId);
 
         // Handle well-known MIME-types with special care
@@ -203,6 +205,12 @@
 
     /** {@inheritDoc} */
     @Override
+    public long getDataId() {
+        return mDataId;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public Boolean isPrimary() {
         return mIsPrimary;
     }
diff --git a/src/com/android/contacts/quickcontact/ProfileAction.java b/src/com/android/contacts/quickcontact/ProfileAction.java
index 47102a5..a04e522 100644
--- a/src/com/android/contacts/quickcontact/ProfileAction.java
+++ b/src/com/android/contacts/quickcontact/ProfileAction.java
@@ -82,6 +82,12 @@
 
     /** {@inheritDoc} */
     @Override
+    public long getDataId() {
+        return -1;
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public boolean collapseWith(Action t) {
         return false; // Never dup.
     }
diff --git a/src/com/android/contacts/quickcontact/QuickContactWindow.java b/src/com/android/contacts/quickcontact/QuickContactWindow.java
index cf7f126..d3fdd42 100644
--- a/src/com/android/contacts/quickcontact/QuickContactWindow.java
+++ b/src/com/android/contacts/quickcontact/QuickContactWindow.java
@@ -25,15 +25,17 @@
 import com.android.contacts.util.Constants;
 import com.android.contacts.util.DataStatus;
 import com.android.contacts.util.NotifyingAsyncQueryHandler;
+import com.android.contacts.views.ContactSaveService;
 import com.android.internal.policy.PolicyManager;
+import com.google.android.collect.Lists;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.ActivityNotFoundException;
 import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -64,6 +66,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -73,8 +76,9 @@
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
+import android.widget.Button;
 import android.widget.CheckBox;
-import android.widget.CompoundButton;
+import android.widget.FrameLayout;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -84,6 +88,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -94,8 +99,8 @@
  */
 public class QuickContactWindow implements Window.Callback,
         NotifyingAsyncQueryHandler.AsyncQueryListener, View.OnClickListener,
-        AbsListView.OnItemClickListener, CompoundButton.OnCheckedChangeListener, KeyEvent.Callback,
-        OnGlobalLayoutListener, QuickContactRootLayout.Listener {
+        AbsListView.OnItemClickListener, KeyEvent.Callback, OnGlobalLayoutListener,
+        QuickContactRootLayout.Listener {
     private static final String TAG = "QuickContactWindow";
 
     /**
@@ -133,7 +138,6 @@
     private int mRequestedY;
 
     private boolean mHasValidSocial = false;
-    private boolean mMakePrimary = false;
 
     private int mMode;
     private QuickContactRootLayout mRootView;
@@ -142,10 +146,19 @@
     private HorizontalScrollView mTrackScroll;
     private ViewGroup mTrack;
 
+    private FrameLayout mFooter;
     private LinearLayout mFooterDisambig;
+    private LinearLayout mFooterClearDefaults;
     private ListView mResolveList;
     private CheckableImageView mLastAction;
     private CheckBox mSetPrimaryCheckBox;
+    private ListView mDefaultsListView;
+    private Button mClearDefaultsButton;
+
+    /**
+     * Keeps the default action per mimetype. Empty if no default actions are set
+     */
+    private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>();
 
     private int mWindowRecycled = 0;
     private int mActionRecycled = 0;
@@ -161,7 +174,7 @@
      * Pool of unused {@link CheckableImageView} that have previously been
      * inflated, and are ready to be recycled through {@link #obtainView()}.
      */
-    private LinkedList<View> mActionPool = new LinkedList<View>();
+    private LinkedList<CheckableImageView> mActionPool = new LinkedList<CheckableImageView>();
 
     private String[] mExcludeMimes;
 
@@ -192,6 +205,13 @@
             Website.CONTENT_ITEM_TYPE,
     };
 
+    /**
+     * List of MIMETYPES that do not represent real data rows and can therefore not be set
+     * as defaults
+     */
+    private static final ArrayList<String> VIRTUAL_MIMETYPES = Lists.newArrayList(new String[] {
+            Im.CONTENT_ITEM_TYPE, Constants.MIME_SMS_ADDRESS
+    });
     private static final int TOKEN_DATA = 1;
 
     static final boolean TRACE_LAUNCH = false;
@@ -230,11 +250,22 @@
         mTrack = (ViewGroup) mWindow.findViewById(R.id.quickcontact);
         mTrackScroll = (HorizontalScrollView) mWindow.findViewById(R.id.scroll);
 
+        mFooter = (FrameLayout) mWindow.findViewById(R.id.footer);
         mFooterDisambig = (LinearLayout) mWindow.findViewById(R.id.footer_disambig);
+        mFooterClearDefaults = (LinearLayout) mWindow.findViewById(R.id.footer_clear_defaults);
         mResolveList = (ListView) mWindow.findViewById(android.R.id.list);
         mSetPrimaryCheckBox = (CheckBox) mWindow.findViewById(android.R.id.checkbox);
 
-        mSetPrimaryCheckBox.setOnCheckedChangeListener(this);
+        mDefaultsListView = (ListView) mWindow.findViewById(R.id.defaults_list);
+        mClearDefaultsButton = (Button) mWindow.findViewById(R.id.clear_defaults_button);
+        mClearDefaultsButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                clearDefaults();
+            }
+        });
+
+        mResolveList.setOnItemClickListener(QuickContactWindow.this);
 
         mHandler = new NotifyingAsyncQueryHandler(mContext, this);
     }
@@ -512,18 +543,17 @@
 
         // Recycle any chiclets in use
         for (int i = mTrack.getChildCount() - 1; i >= 0; i--) {
-            releaseView(mTrack.getChildAt(i));
+            releaseView((CheckableImageView)mTrack.getChildAt(i));
             mTrack.removeViewAt(i);
         }
 
         mTrackScroll.fullScroll(View.FOCUS_LEFT);
 
         // Clear any primary requests
-        mMakePrimary = false;
         mSetPrimaryCheckBox.setChecked(false);
 
         setNewActionViewChecked(null);
-        mFooterDisambig.setVisibility(View.GONE);
+        mFooter.setVisibility(View.GONE);
     }
 
     /**
@@ -620,6 +650,8 @@
             mActions.put(Contacts.CONTENT_ITEM_TYPE, action);
         }
 
+        mDefaultsMap.clear();
+
         final DataStatus status = new DataStatus();
         final AccountTypes sources = AccountTypes.getInstance(mContext);
         final ImageView photoView = (ImageView)mHeader.findViewById(R.id.photo);
@@ -629,6 +661,8 @@
             final long dataId = cursor.getLong(DataQuery._ID);
             final String accountType = cursor.getString(DataQuery.ACCOUNT_TYPE);
             final String mimeType = cursor.getString(DataQuery.MIMETYPE);
+            final boolean isPrimary = cursor.getInt(DataQuery.IS_PRIMARY) != 0;
+            final boolean isSuperPrimary = cursor.getInt(DataQuery.IS_SUPER_PRIMARY) != 0;
 
             // Handle any social status updates from this row
             status.possibleUpdate(cursor);
@@ -654,14 +688,20 @@
                 // element, build its summary from the cursor, and collect it
                 // along with all others of this MIME-type.
                 final Action action = new DataAction(mContext, mimeType, kind, dataId, cursor);
-                considerAdd(action, mimeType, cache);
+                final boolean wasAdded = considerAdd(action, cache);
+                if (wasAdded) {
+                    // Remember the default
+                    if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) {
+                        mDefaultsMap.put(mimeType, action);
+                    }
+                }
             }
 
             // If phone number, also insert as text message action
             if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && kind != null) {
-                final Action action = new DataAction(mContext, Constants.MIME_SMS_ADDRESS,
+                final DataAction action = new DataAction(mContext, Constants.MIME_SMS_ADDRESS,
                         kind, dataId, cursor);
-                considerAdd(action, Constants.MIME_SMS_ADDRESS, cache);
+                considerAdd(action, cache);
             }
 
             // Handle Email rows with presence data as Im entry
@@ -670,13 +710,18 @@
                 final DataKind imKind = sources.getKindOrFallback(accountType,
                         Im.CONTENT_ITEM_TYPE, mContext, AccountType.LEVEL_MIMETYPES);
                 if (imKind != null) {
-                    final Action action = new DataAction(mContext, Im.CONTENT_ITEM_TYPE, imKind,
+                    final DataAction action = new DataAction(mContext, Im.CONTENT_ITEM_TYPE, imKind,
                             dataId, cursor);
-                    considerAdd(action, Im.CONTENT_ITEM_TYPE, cache);
+                    considerAdd(action, cache);
                 }
             }
         }
 
+        if (mDefaultsMap.size() != 0) {
+            final Action action = new ClearDefaultsAction();
+            mActions.put(action.getMimeType(), action);
+        }
+
         if (cursor.moveToLast()) {
             // Read contact information from last data row
             final String name = cursor.getString(DataQuery.DISPLAY_NAME);
@@ -702,9 +747,6 @@
 
         // Turn our list of actions into UI elements
 
-        // Index where we start adding child views.
-        int index = mTrack.getChildCount() - 1;
-
         // All the mime-types to add.
         final Set<String> containedTypes = new HashSet<String>(mActions.keySet());
 
@@ -714,25 +756,41 @@
         for (String mimeType : PRECEDING_MIMETYPES) {
             if (containedTypes.contains(mimeType)) {
                 hasData = true;
-                mTrack.addView(inflateAction(mimeType, cache), index++);
+                mTrack.addView(inflateAction(mimeType, cache));
                 containedTypes.remove(mimeType);
             }
         }
 
         // Keep the current index to append non PRECEDING/FOLLOWING items.
-        final int indexAfterPreceding = index;
+        final int indexAfterPreceding = mTrack.getChildCount() - 1;
 
         // Then, add FOLLOWING_MIMETYPES, which are least common.
         for (String mimeType : FOLLOWING_MIMETYPES) {
             if (containedTypes.contains(mimeType)) {
                 hasData = true;
-                mTrack.addView(inflateAction(mimeType, cache), index++);
+                mTrack.addView(inflateAction(mimeType, cache));
                 containedTypes.remove(mimeType);
             }
         }
 
+        // Show the clear-defaults button? If yes, it goes to the end of the list
+        if (containedTypes.contains(ClearDefaultsAction.PSEUDO_MIME_TYPE)) {
+            final ClearDefaultsAction action = (ClearDefaultsAction) mActions.get(
+                    ClearDefaultsAction.PSEUDO_MIME_TYPE).get(0);
+            final CheckableImageView view = obtainView();
+            view.setChecked(false);
+            final String description = mContext.getResources().getString(
+                    R.string.quickcontact_clear_defaults_description);
+            view.setContentDescription(description);
+            view.setImageResource(R.drawable.badge_action_clear_defaults_holo_light);
+            view.setOnClickListener(this);
+            view.setTag(action);
+            mTrack.addView(view);
+            containedTypes.remove(ClearDefaultsAction.PSEUDO_MIME_TYPE);
+        }
+
         // Go back to just after PRECEDING_MIMETYPES, and append the rest.
-        index = indexAfterPreceding;
+        int index = indexAfterPreceding;
         final String[] remainingTypes = containedTypes.toArray(new String[containedTypes.size()]);
         if (remainingTypes.length > 0) hasData = true;
         Arrays.sort(remainingTypes);
@@ -740,34 +798,72 @@
             mTrack.addView(inflateAction(mimeType, cache), index++);
         }
 
-        // When there is no data to display, add a TextView to show the user there's no data
         if (!hasData) {
+            // When there is no data to display, add a TextView to show the user there's no data
             View view = mInflater.inflate(R.layout.quickcontact_item_nodata, mTrack, false);
             mTrack.addView(view, index++);
         }
     }
 
     /**
+     * Clears the defaults currently set on the Contact
+     */
+    private void clearDefaults() {
+        final Set<String> mimeTypesKeySet = mDefaultsMap.keySet();
+        // Copy to array so that we can modify the HashMap below
+        final String[] mimeTypes = new String[mimeTypesKeySet.size()];
+        mimeTypesKeySet.toArray(mimeTypes);
+
+        // Send clear default Intents, one by one
+        for (String mimeType : mimeTypes) {
+            final Action action = mDefaultsMap.get(mimeType);
+            final Intent intent =
+                    ContactSaveService.createClearPrimaryIntent(mContext, action.getDataId());
+            mContext.startService(intent);
+            mDefaultsMap.remove(mimeType);
+        }
+
+        // Close up and remove the configure default button
+        animateCollapse(new Runnable() {
+            @Override
+            public void run() {
+                for (int i = mTrack.getChildCount() - 1; i >= 0; i--) {
+                    final CheckableImageView button = (CheckableImageView) mTrack.getChildAt(i);
+                    if (button.getTag() instanceof ClearDefaultsAction) {
+                        releaseView(button);
+                        mTrack.removeViewAt(i);
+                        break;
+                    }
+                }
+            }
+        });
+    }
+
+    /**
      * Consider adding the given {@link Action}, which will only happen if
      * {@link PackageManager} finds an application to handle
      * {@link Action#getIntent()}.
+     * @return true if action has been added
      */
-    private void considerAdd(Action action, String mimeType, ResolveCache resolveCache) {
+    private boolean considerAdd(Action action, ResolveCache resolveCache) {
         if (resolveCache.hasResolve(action)) {
-            mActions.put(mimeType, action);
+            mActions.put(action.getMimeType(), action);
+            return true;
         }
+        return false;
     }
 
     /**
      * Obtain a new {@link CheckableImageView} for a new chiclet, either by
      * recycling one from {@link #mActionPool}, or by inflating a new one. When
-     * finished, use {@link #releaseView(View)} to return back into the pool for
+     * finished, use {@link #releaseView(CheckableImageView)} to return back into the pool for
      * later recycling.
      */
-    private synchronized View obtainView() {
-        View view = mActionPool.poll();
+    private synchronized CheckableImageView obtainView() {
+        CheckableImageView view = mActionPool.poll();
         if (view == null || QuickContactActivity.FORCE_CREATE) {
-            view = mInflater.inflate(R.layout.quickcontact_item, mTrack, false);
+            view = (CheckableImageView) mInflater.inflate(R.layout.quickcontact_item, mTrack,
+                    false);
         }
         return view;
     }
@@ -776,11 +872,7 @@
      * Return the given {@link CheckableImageView} into our internal pool for
      * possible recycling during another pass.
      */
-    private synchronized void releaseView(View view) {
-        // Only add CheckableImageViews
-        if (!(view instanceof CheckableImageView)) {
-            return;
-        }
+    private synchronized void releaseView(CheckableImageView view) {
         mActionPool.offer(view);
         mActionRecycled++;
     }
@@ -790,29 +882,15 @@
      * Will use the icon provided by the {@link DataKind}.
      */
     private View inflateAction(String mimeType, ResolveCache resolveCache) {
-        final CheckableImageView view = (CheckableImageView)obtainView();
-        boolean isActionSet = false;
+        final CheckableImageView view = obtainView();
 
         // Add direct intent if single child, otherwise flag for multiple
         List<Action> children = mActions.get(mimeType);
         if (children.size() > 1) {
             Collapser.collapseList(children);
         }
-        Action firstInfo = children.get(0);
-        if (children.size() == 1) {
-            view.setTag(firstInfo);
-        } else {
-            for (Action action : children) {
-                if (action.isPrimary()) {
-                    view.setTag(action);
-                    isActionSet = true;
-                    break;
-                }
-            }
-            if (!isActionSet) {
-                view.setTag(children);
-            }
-        }
+        view.setTag(mimeType);
+        final Action firstInfo = children.get(0);
 
         // Set icon and listen for clicks
         final CharSequence descrip = resolveCache.getDescription(firstInfo);
@@ -832,7 +910,7 @@
     }
 
     /**
-     * Helper for showing and hiding {@link #mFooterDisambig}
+     * Helper for checking an action view
      */
     private void setNewActionViewChecked(CheckableImageView actionView) {
         if (mLastAction != null) mLastAction.setChecked(false);
@@ -847,13 +925,13 @@
         final int oldBottom = mBackground.getBounds().bottom;
         mBackground.setBottomOverride(oldBottom);
 
-        final ObjectAnimator fadeOutAnimator = ObjectAnimator.ofFloat(mFooterDisambig, "alpha",
+        final ObjectAnimator fadeOutAnimator = ObjectAnimator.ofFloat(mFooter, "alpha",
                 1.0f, 0.0f);
         fadeOutAnimator.setDuration(ANIMATION_FADE_OUT_TIME);
         fadeOutAnimator.start();
 
         final ObjectAnimator collapseAnimator = ObjectAnimator.ofInt(mBackground,
-                "bottomOverride", oldBottom, oldBottom - mFooterDisambig.getHeight());
+                "bottomOverride", oldBottom, oldBottom - mFooter.getHeight());
         collapseAnimator.setDuration(ANIMATION_COLLAPSE_TIME);
         collapseAnimator.setStartDelay(ANIMATION_FADE_OUT_TIME);
         collapseAnimator.start();
@@ -861,7 +939,7 @@
         collapseAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                mFooterDisambig.setVisibility(View.GONE);
+                mFooter.setVisibility(View.GONE);
                 new Handler().post(whenDone);
             }
         });
@@ -869,12 +947,15 @@
 
     /**
      * Animates expansion of the disambig area.
+     * @param showClearDefaults true to expand to clear defaults. false to expand to intent disambig
      */
-    private void animateExpand() {
-        mFooterDisambig.setVisibility(View.VISIBLE);
+    private void animateExpand(boolean showClearDefaults) {
+        mFooter.setVisibility(View.VISIBLE);
+        mFooterDisambig.setVisibility(showClearDefaults ? View.GONE : View.VISIBLE);
+        mFooterClearDefaults.setVisibility(showClearDefaults ? View.VISIBLE : View.GONE);
         final int oldBottom = mBackground.getBounds().bottom;
         mBackground.setBottomOverride(oldBottom);
-        mFooterDisambig.setAlpha(0.0f);
+        mFooter.setAlpha(0.0f);
         new Handler().post(new Runnable() {
             @Override
             public void run() {
@@ -884,7 +965,7 @@
                 expandAnimator.setDuration(ANIMATION_EXPAND_TIME);
                 expandAnimator.start();
 
-                final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat(mFooterDisambig,
+                final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat(mFooter,
                         "alpha", 0.0f, 1.0f);
                 fadeInAnimator.setDuration(ANIMATION_FADE_IN_TIME);
                 fadeInAnimator.setStartDelay(ANIMATION_EXPAND_TIME);
@@ -899,12 +980,116 @@
         final boolean isActionView = (view instanceof CheckableImageView);
         final CheckableImageView actionView = isActionView ? (CheckableImageView)view : null;
         final Object tag = view.getTag();
+        if (tag instanceof ClearDefaultsAction) {
+            // Do nothing if already open
+            if (actionView == mLastAction) return;
+            // collapse any disambig that may already be open. the open clearing-defaults
+            final Runnable expandClearDefaultsRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    // Show resolution list and set adapter
+                    setNewActionViewChecked(actionView);
+                    final Action[] actions = new Action[mDefaultsMap.size()];
+                    mDefaultsMap.values().toArray(actions);
+
+                    mDefaultsListView.setAdapter(new BaseAdapter() {
+                        @Override
+                        public int getCount() {
+                            return actions.length;
+                        }
+
+                        @Override
+                        public Object getItem(int position) {
+                            return actions[position];
+                        }
+
+                        @Override
+                        public long getItemId(int position) {
+                            return position;
+                        }
+
+                        @Override
+                        public boolean areAllItemsEnabled() {
+                            return false;
+                        }
+
+                        @Override
+                        public boolean isEnabled(int position) {
+                            return false;
+                        }
+
+                        @Override
+                        public View getView(int position, View convertView, ViewGroup parent) {
+                            final View result = convertView != null ? convertView :
+                                    mInflater.inflate(R.layout.quickcontact_default_item,
+                                    parent, false);
+                            // Set action title based on summary value
+                            final Action defaultAction = actions[position];
+
+                            TextView text1 = (TextView)result.findViewById(android.R.id.text1);
+                            TextView text2 = (TextView)result.findViewById(android.R.id.text2);
+
+                            text1.setText(defaultAction.getHeader());
+                            text2.setText(defaultAction.getBody());
+
+                            result.setTag(defaultAction);
+                            return result;
+                        }
+                    });
+
+                    animateExpand(true);
+                    // Make sure we resize to make room for ListView
+                    if (mDecor != null) {
+                        mDecor.forceLayout();
+                        mDecor.invalidate();
+                    }
+                }
+            };
+            if (mFooter.getVisibility() == View.VISIBLE) {
+                animateCollapse(expandClearDefaultsRunnable);
+            } else {
+                new Handler().post(expandClearDefaultsRunnable);
+            }
+            return;
+        }
+
+        // Determine whether to launch a specific Action or show a disambig-List
+        final Action action;
+        final List<Action> actionList;
+        final boolean fromDisambigList;
+        final String mimeType;
         if (tag instanceof Action) {
+            action = (Action) tag;
+            actionList = null;
+            fromDisambigList = true;
+            mimeType = action.getMimeType();
+        } else if (tag instanceof String) {
+            mimeType = (String) tag;
+            actionList = mActions.get(mimeType);
+
+            if (actionList.size() == 1) {
+                // Just one item? Pick that one
+                action = actionList.get(0);
+            } else if (mDefaultsMap.containsKey(mimeType)) {
+                // Default item? pick that one
+                action = mDefaultsMap.get(mimeType);
+            } else {
+                // Several actions and none is default.
+                action = null;
+            }
+            fromDisambigList = false;
+        } else {
+            throw new IllegalStateException("tag is neither Action nor (mimetype-) String");
+        }
+
+        if (action != null) {
+            final boolean isVirtual = VIRTUAL_MIMETYPES.contains(mimeType);
+            final boolean makePrimary = fromDisambigList && mSetPrimaryCheckBox.isChecked() &&
+                    !isVirtual;
             final Runnable startAppRunnable = new Runnable() {
                 @Override
                 public void run() {
                     // Incoming tag is concrete intent, so try launching
-                    final Action action = (Action)tag;
                     try {
                         mContext.startActivity(action.getIntent());
                     } catch (ActivityNotFoundException e) {
@@ -915,100 +1100,95 @@
                     // Hide the resolution list, if present
                     setNewActionViewChecked(null);
                     dismiss();
-                    mFooterDisambig.setVisibility(View.GONE);
+                    mFooter.setVisibility(View.GONE);
 
-                    if (mMakePrimary) {
-                        ContentValues values = new ContentValues(1);
-                        values.put(Data.IS_SUPER_PRIMARY, 1);
-                        final Uri dataUri = action.getDataUri();
-                        if (dataUri != null) {
-                            mContext.getContentResolver().update(dataUri, values, null, null);
-                        }
+                    // Set default?
+                    final long dataId = action.getDataId();
+                    if (makePrimary && dataId != -1) {
+                        Intent serviceIntent = ContactSaveService.createSetSuperPrimaryIntent(
+                                mContext, dataId);
+                        mContext.startService(serviceIntent);
                     }
                 }
             };
-            if (isActionView && mFooterDisambig.getVisibility() == View.VISIBLE) {
-                // If the expansion list is currently opened, animate its collapse and then
+            if (isActionView && mFooter.getVisibility() == View.VISIBLE) {
+                // If the footer is currently opened, animate its collapse and then
                 // execute the target app
                 animateCollapse(startAppRunnable);
             } else {
                 // Defer the action to make the window properly repaint
                 new Handler().post(startAppRunnable);
             }
-        } else if (tag instanceof ArrayList<?>) {
-            // Don't do anything if already open
-            if (actionView != mLastAction) {
-                final Runnable configureListRunnable = new Runnable() {
+            return;
+        }
+
+        // This was not a specific Action. Expand the disambig-list
+        if (actionList == null) throw new IllegalStateException();
+
+        // Don't do anything if already open
+        if (actionView == mLastAction) return;
+        final Runnable configureListRunnable = new Runnable() {
+            @Override
+            public void run() {
+                // Show resolution list and set adapter
+                setNewActionViewChecked(actionView);
+                final boolean isVirtual = VIRTUAL_MIMETYPES.contains(mimeType);
+                mSetPrimaryCheckBox.setVisibility(isVirtual ? View.GONE : View.VISIBLE);
+
+                mResolveList.setAdapter(new BaseAdapter() {
                     @Override
-                    public void run() {
-                        // Show resolution list and set adapter
-                        setNewActionViewChecked(actionView);
-
-                        // Incoming tag is a MIME-type, so show resolution list
-                        final ArrayList<?> children = (ArrayList<?>)tag;
-
-                        mResolveList.setOnItemClickListener(QuickContactWindow.this);
-                        mResolveList.setAdapter(new BaseAdapter() {
-                            @Override
-                            public int getCount() {
-                                return children.size();
-                            }
-
-                            @Override
-                            public Object getItem(int position) {
-                                return children.get(position);
-                            }
-
-                            @Override
-                            public long getItemId(int position) {
-                                return position;
-                            }
-
-                            @Override
-                            public View getView(int position, View convertView, ViewGroup parent) {
-                                final View result = convertView != null ? convertView :
-                                        mInflater.inflate(R.layout.quickcontact_resolve_item,
-                                        parent, false);
-                                // Set action title based on summary value
-                                final Action action = (Action)getItem(position);
-
-                                TextView text1 = (TextView)result.findViewById(android.R.id.text1);
-                                TextView text2 = (TextView)result.findViewById(android.R.id.text2);
-
-                                text1.setText(action.getHeader());
-                                text2.setText(action.getBody());
-
-                                result.setTag(action);
-                                return result;
-                            }
-                        });
-
-                        animateExpand();
-                        // Make sure we resize to make room for ListView
-                        if (mDecor != null) {
-                            mDecor.forceLayout();
-                            mDecor.invalidate();
-                        }
+                    public int getCount() {
+                        return actionList.size();
                     }
-                };
-                if (mFooterDisambig.getVisibility() == View.VISIBLE) {
-                    // If the expansion list is currently opened, animate its collapse and then
-                    // execute the target app
-                    animateCollapse(configureListRunnable);
-                } else {
-                    // Defer the action to make the window properly repaint
-                    configureListRunnable.run();
+
+                    @Override
+                    public Object getItem(int position) {
+                        return actionList.get(position);
+                    }
+
+                    @Override
+                    public long getItemId(int position) {
+                        return position;
+                    }
+
+                    @Override
+                    public View getView(int position, View convertView, ViewGroup parent) {
+                        final View result = convertView != null ? convertView :
+                                mInflater.inflate(R.layout.quickcontact_resolve_item,
+                                parent, false);
+                        // Set action title based on summary value
+                        final Action listAction = actionList.get(position);
+
+                        TextView text1 = (TextView)result.findViewById(android.R.id.text1);
+                        TextView text2 = (TextView)result.findViewById(android.R.id.text2);
+
+                        text1.setText(listAction.getHeader());
+                        text2.setText(listAction.getBody());
+
+                        result.setTag(listAction);
+                        return result;
+                    }
+                });
+
+                animateExpand(false);
+                // Make sure we resize to make room for ListView
+                if (mDecor != null) {
+                    mDecor.forceLayout();
+                    mDecor.invalidate();
                 }
             }
+        };
+        if (mFooter.getVisibility() == View.VISIBLE) {
+            // If the expansion list is currently opened, animate its collapse and then
+            // execute the target app
+            animateCollapse(configureListRunnable);
+        } else {
+            // Defer the action to make the window properly repaint
+            configureListRunnable.run();
         }
     }
 
     @Override
-    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        mMakePrimary = isChecked;
-    }
-
-    @Override
     public void onBackPressed() {
         dismiss();
     }
diff --git a/src/com/android/contacts/views/ContactSaveService.java b/src/com/android/contacts/views/ContactSaveService.java
index 16daaed..280f399 100644
--- a/src/com/android/contacts/views/ContactSaveService.java
+++ b/src/com/android/contacts/views/ContactSaveService.java
@@ -63,6 +63,10 @@
     public static final String EXTRA_CONTACT_URI = "contactUri";
     public static final String EXTRA_STARRED_FLAG = "starred";
 
+    public static final String ACTION_SET_SUPER_PRIMARY = "setSuperPrimary";
+    public static final String ACTION_CLEAR_PRIMARY = "clearPrimary";
+    public static final String EXTRA_DATA_ID = "dataId";
+
     private static final HashSet<String> ALLOWED_DATA_COLUMNS = Sets.newHashSet(
         Data.MIMETYPE,
         Data.IS_PRIMARY,
@@ -101,6 +105,10 @@
             deleteGroup(intent);
         } else if (ACTION_SET_STARRED.equals(action)) {
             setStarred(intent);
+        } else if (ACTION_SET_SUPER_PRIMARY.equals(action)) {
+            setSuperPrimary(intent);
+        } else if (ACTION_CLEAR_PRIMARY.equals(action)) {
+            clearPrimary(intent);
         }
     }
 
@@ -288,4 +296,58 @@
         getContentResolver().update(contactUri, values, null, null);
 
     }
+
+    /**
+     * Creates an intent that sets the selected data item as super primary (default)
+     */
+    public static Intent createSetSuperPrimaryIntent(Context context, long dataId) {
+        Intent serviceIntent = new Intent(context, ContactSaveService.class);
+        serviceIntent.setAction(ContactSaveService.ACTION_SET_SUPER_PRIMARY);
+        serviceIntent.putExtra(ContactSaveService.EXTRA_DATA_ID, dataId);
+        return serviceIntent;
+    }
+
+    private void setSuperPrimary(Intent intent) {
+        long dataId = intent.getLongExtra(EXTRA_DATA_ID, -1);
+        if (dataId == -1) {
+            Log.e(TAG, "Invalid arguments for setSuperPrimary request");
+            return;
+        }
+
+        // Update the primary values in the data record.
+        ContentValues values = new ContentValues(1);
+        values.put(Data.IS_SUPER_PRIMARY, 1);
+        values.put(Data.IS_PRIMARY, 1);
+
+        getContentResolver().update(ContentUris.withAppendedId(Data.CONTENT_URI, dataId),
+                values, null, null);
+    }
+
+    /**
+     * Creates an intent that clears the primary flag of all data items that belong to the same
+     * raw_contact as the given data item. Will only clear, if the data item was primary before
+     * this call
+     */
+    public static Intent createClearPrimaryIntent(Context context, long dataId) {
+        Intent serviceIntent = new Intent(context, ContactSaveService.class);
+        serviceIntent.setAction(ContactSaveService.ACTION_CLEAR_PRIMARY);
+        serviceIntent.putExtra(ContactSaveService.EXTRA_DATA_ID, dataId);
+        return serviceIntent;
+    }
+
+    private void clearPrimary(Intent intent) {
+        long dataId = intent.getLongExtra(EXTRA_DATA_ID, -1);
+        if (dataId == -1) {
+            Log.e(TAG, "Invalid arguments for clearPrimary request");
+            return;
+        }
+
+        // Update the primary values in the data record.
+        ContentValues values = new ContentValues(1);
+        values.put(Data.IS_SUPER_PRIMARY, 0);
+        values.put(Data.IS_PRIMARY, 0);
+
+        getContentResolver().update(ContentUris.withAppendedId(Data.CONTENT_URI, dataId),
+                values, null, null);
+    }
 }
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index 1e9998f..3607923 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -33,6 +33,7 @@
 import com.android.contacts.util.DateUtils;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.contacts.views.ContactLoader;
+import com.android.contacts.views.ContactSaveService;
 import com.android.contacts.views.GroupMetaData;
 import com.android.contacts.views.editor.SelectAccountDialogFragment;
 import com.android.contacts.widget.TransitionAnimationView;
@@ -610,17 +611,6 @@
         }
     }
 
-    private static String buildActionString(DataKind kind, ContentValues values, Context context) {
-        if (kind.actionHeader == null) {
-            return null;
-        }
-        CharSequence actionHeader = kind.actionHeader.inflateUsing(context, values);
-        if (actionHeader == null) {
-            return null;
-        }
-        return actionHeader.toString();
-    }
-
     private static String buildDataString(DataKind kind, ContentValues values,
             Context context) {
         if (kind.actionBody == null) {
@@ -790,7 +780,6 @@
         public TextView footer;
         public ImageView actionIcon;
         public ImageView presenceIcon;
-        public ImageView primaryIcon;
         public ImageView secondaryActionButton;
         public View secondaryActionDivider;
     }
@@ -820,7 +809,6 @@
                 viewCache.data = (TextView) v.findViewById(R.id.data);
                 viewCache.footer = (TextView) v.findViewById(R.id.footer);
                 viewCache.actionIcon = (ImageView) v.findViewById(R.id.action_icon);
-                viewCache.primaryIcon = (ImageView) v.findViewById(R.id.primary_icon);
                 viewCache.presenceIcon = (ImageView) v.findViewById(R.id.presence_icon);
                 viewCache.secondaryActionButton = (ImageView) v.findViewById(
                         R.id.secondary_action_button);
@@ -870,9 +858,6 @@
                 views.footer.setVisibility(View.GONE);
             }
 
-            // Set the primary icon
-            views.primaryIcon.setVisibility(entry.isPrimary ? View.VISIBLE : View.GONE);
-
             // Set the action icon
             final ImageView action = views.actionIcon;
             if (entry.actionIcon != -1) {
@@ -1102,46 +1087,6 @@
     }
 
     @Override
-    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
-        AdapterView.AdapterContextMenuInfo info;
-        try {
-             info = (AdapterView.AdapterContextMenuInfo) menuInfo;
-        } catch (ClassCastException e) {
-            Log.e(TAG, "bad menuInfo", e);
-            return;
-        }
-
-        // This can be null sometimes, don't crash...
-        if (info == null) {
-            Log.e(TAG, "bad menuInfo");
-            return;
-        }
-
-        final ViewEntry entry = mAdapter.getEntry(info.position);
-        menu.setHeaderTitle(R.string.contactOptionsTitle);
-        if (entry.mimetype.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
-            if (mHasPhone) {
-                menu.add(0, 0, 0, R.string.menu_call).setIntent(entry.intent);
-            }
-            if (mHasSms) {
-                // If there is no Phone, SMS is the primary intent
-                final Intent intent = mHasPhone ? entry.secondaryIntent : entry.intent;
-                menu.add(0, 0, 0, R.string.menu_sendSMS).setIntent(intent);
-            }
-            if (!entry.isPrimary && mHasPhone) {
-                menu.add(0, R.id.menu_detail_makeDefault, 0, R.string.menu_makeDefaultNumber);
-            }
-        } else if (entry.mimetype.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
-            menu.add(0, 0, 0, R.string.menu_sendEmail).setIntent(entry.intent);
-            if (!entry.isPrimary) {
-                menu.add(0, R.id.menu_detail_makeDefault, 0, R.string.menu_makeDefaultEmail);
-            }
-        } else if (entry.mimetype.equals(CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)) {
-            menu.add(0, 0, 0, R.string.menu_viewAddress).setIntent(entry.intent);
-        }
-    }
-
-    @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         if (mListener == null) return;
         final ViewEntry entry = mAdapter.getEntry(position);
@@ -1151,47 +1096,6 @@
         mListener.onItemClicked(intent);
     }
 
-    @Override
-    public boolean onContextItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.menu_detail_makeDefault: {
-                if (makeItemDefault(item)) {
-                    return true;
-                }
-                break;
-            }
-        }
-
-        return false;
-    }
-
-    private boolean makeItemDefault(MenuItem item) {
-        ViewEntry entry = getViewEntryForMenuItem(item);
-        if (entry == null) {
-            return false;
-        }
-
-        // Update the primary values in the data record.
-        ContentValues values = new ContentValues(1);
-        values.put(Data.IS_SUPER_PRIMARY, 1);
-
-        mContext.getContentResolver().update(ContentUris.withAppendedId(Data.CONTENT_URI, entry.id),
-                values, null, null);
-        return true;
-    }
-
-    private ViewEntry getViewEntryForMenuItem(MenuItem item) {
-        AdapterView.AdapterContextMenuInfo info;
-        try {
-             info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
-        } catch (ClassCastException e) {
-            Log.e(TAG, "bad menuInfo", e);
-            return null;
-        }
-
-        return mAdapter.getEntry(info.position);
-    }
-
     public boolean handleKeyDown(int keyCode) {
         switch (keyCode) {
             case KeyEvent.KEYCODE_CALL: {