Merge "Import translations. DO NOT MERGE" into lmp-dev
diff --git a/res/layout-sw720dp/quickcontact_activity.xml b/res/layout-sw720dp/quickcontact_activity.xml
index efbb4d1..5a7d90a 100644
--- a/res/layout-sw720dp/quickcontact_activity.xml
+++ b/res/layout-sw720dp/quickcontact_activity.xml
@@ -27,45 +27,52 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="horizontal">
+        android:orientation="vertical" >
 
         <View
-            android:id="@+id/empty_start_column"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="@integer/contact_list_space_layout_weight"
-            android:contentDescription="@string/quickcontact_transparent_view_description" />
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/quickcontact_starting_empty_height"
+            android:contentDescription="@string/quickcontact_transparent_view_description"
+            android:id="@+id/transparent_view" />
 
         <LinearLayout
-            android:layout_width="0dp"
-            android:layout_weight="@integer/contact_list_card_layout_weight"
+            android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:orientation="vertical">
+            android:orientation="horizontal">
 
             <View
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/quickcontact_starting_empty_height"
-                android:contentDescription="@string/quickcontact_transparent_view_description"
-                android:id="@+id/transparent_view" />
-
-            <FrameLayout
-                android:layout_width="match_parent"
+                android:id="@+id/empty_start_column"
+                android:layout_width="0dp"
                 android:layout_height="match_parent"
-                android:id="@+id/toolbar_parent">
-                <include layout="@layout/quickcontact_header" />
-            </FrameLayout>
+                android:layout_weight="@integer/contact_list_space_layout_weight"
+                android:background="@color/background_primary"
+                android:focusable="false" />
 
-            <include layout="@layout/quickcontact_content" />
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="@integer/contact_list_card_layout_weight"
+                android:orientation="vertical"
+                android:elevation="@dimen/contact_list_card_elevation"
+                android:outlineProvider="bounds" >
+                <FrameLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:id="@+id/toolbar_parent">
+                    <include layout="@layout/quickcontact_header" />
+                </FrameLayout>
 
+                <include layout="@layout/quickcontact_content" />
+            </LinearLayout>
+
+            <View
+                android:id="@+id/empty_end_column"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="@integer/contact_list_space_layout_weight"
+                android:background="@color/background_primary"
+                android:focusable="false" />
         </LinearLayout>
-
-        <View
-            android:id="@+id/empty_end_column"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="@integer/contact_list_space_layout_weight"
-            android:contentDescription="@string/quickcontact_transparent_view_description" />
-
     </LinearLayout>
 
     <!-- This title's maximum height must be less than the minimum size of its
diff --git a/res/layout/contact_picker_content.xml b/res/layout/contact_picker_content.xml
index c71314e..36734c5 100644
--- a/res/layout/contact_picker_content.xml
+++ b/res/layout/contact_picker_content.xml
@@ -29,6 +29,8 @@
         android:layout_marginRight="?attr/contact_browser_list_padding_right"
         android:layout_marginStart="?attr/contact_browser_list_padding_left"
         android:layout_marginEnd="?attr/contact_browser_list_padding_right"
+        android:paddingTop="@dimen/contact_browser_list_item_padding_top_or_bottom"
+        android:clipToPadding="false"
         android:fastScrollEnabled="true"/>
 
     <TextView android:id="@android:id/empty"
diff --git a/res/layout/pinned_header_list_demo.xml b/res/layout/pinned_header_list_demo.xml
index 3fc2b79..c717b35 100644
--- a/res/layout/pinned_header_list_demo.xml
+++ b/res/layout/pinned_header_list_demo.xml
@@ -27,6 +27,8 @@
         android:id="@android:id/list"
         android:layout_width="match_parent"
         android:layout_height="0dip"
+        android:paddingTop="@dimen/contact_browser_list_item_padding_top_or_bottom"
+        android:clipToPadding="false"
         android:fastScrollEnabled="true"
         android:layout_weight="1"
     />
diff --git a/res/layout/user_profile_header.xml b/res/layout/user_profile_header.xml
index 5a07313..828f08c 100644
--- a/res/layout/user_profile_header.xml
+++ b/res/layout/user_profile_header.xml
@@ -40,12 +40,8 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="?android:attr/listPreferredItemHeight"
-        android:layout_marginLeft="?attr/list_item_padding_left"
-        android:layout_marginRight="?attr/list_item_padding_right"
-        android:layout_marginStart="?attr/list_item_padding_left"
-        android:layout_marginEnd="?attr/list_item_padding_right"
-        android:paddingLeft="?attr/list_item_gap_between_image_and_text"
-        android:paddingStart="?attr/list_item_gap_between_image_and_text"
+        android:paddingStart="?attr/list_item_padding_left"
+        android:paddingEnd="?attr/list_item_padding_right"
         android:background="?android:attr/selectableItemBackground"
         android:singleLine="true"
         android:text="@string/profile_display_name"
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index a001a63..2c542ba 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -28,7 +28,7 @@
     <dimen name="contact_tile_list_padding_top">18dip</dimen>
     <dimen name="contact_browser_list_item_text_size">18sp</dimen>
     <dimen name="contact_browser_list_item_photo_size">50dp</dimen>
-    <dimen name="contact_browser_list_item_gap_between_image_and_text">15dp</dimen>
+    <dimen name="contact_browser_list_item_gap_between_image_and_text">25dp</dimen>
     <dimen name="contact_browser_list_top_margin">18dp</dimen>
     <!-- Contact list (vertical scroll bar comes left) -->
     <dimen name="list_visible_scrollbar_padding">32dip</dimen>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 1ce9a6f..67b2514 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -28,4 +28,7 @@
     <dimen name="quickcontact_maximum_title_size">64dp</dimen>
     <!-- Right margin of the floating action button -->
     <dimen name="floating_action_button_margin_right">100dp</dimen>
+
+    <dimen name="expanding_entry_card_marginStartEnd">10dp</dimen>
+
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c44d899..865704f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -132,8 +132,7 @@
 
 
     <!-- Margins for ExpandingEntryCardView -->
-    <dimen name="expanding_entry_card_marginStart">8dp</dimen>
-    <dimen name="expanding_entry_card_marginEnd">8dp</dimen>
+    <dimen name="expanding_entry_card_marginStartEnd">8dp</dimen>
     <dimen name="expanding_entry_card_marginBottom">12dp</dimen>
     <!-- Width of the grey border surrounding the expanding entry cards. If we ever add
          a rounded corner to the expanding entry cards, than we will need to increase this value -->
@@ -198,4 +197,10 @@
 
     <!-- Width of the box around a tab when the tab has focus -->
     <dimen name="tab_focused_stroke_width">1dp</dimen>
+
+    <!-- This value should be kept at (?android:attr/listPreferredItemHeight -
+      @dimen/contact_browser_list_item_photo_size) / 2 or greater. Otherwise, this padding
+      will never take affect inside list items. As a result, the padding at the very top
+      of ListView's will not match the padding inside list items -->
+    <dimen name="contact_browser_list_item_padding_top_or_bottom">12dp</dimen>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 73329b3..074ff52 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -72,9 +72,13 @@
         <item name="activated_background">@drawable/list_item_activated_background</item>
         <item name="section_header_background">@drawable/list_title_holo</item>
         <item name="list_section_header_height">24dip</item>
-        <item name="list_item_padding_top">8dip</item>
+        <item name="list_item_padding_top">
+            @dimen/contact_browser_list_item_padding_top_or_bottom
+        </item>
         <item name="list_item_padding_right">32dp</item>
-        <item name="list_item_padding_bottom">8dip</item>
+        <item name="list_item_padding_bottom">
+            @dimen/contact_browser_list_item_padding_top_or_bottom
+        </item>
         <item name="list_item_padding_left">16dip</item>
         <item name="list_item_gap_between_image_and_text">
             @dimen/contact_browser_list_item_gap_between_image_and_text
@@ -271,8 +275,8 @@
         <item name="android:elevation">@dimen/expanding_entry_card_elevation</item>
         <item name="android:background">@color/expanding_entry_card_background_color</item>
         <item name="android:layout_marginBottom">@dimen/expanding_entry_card_marginBottom</item>
-        <item name="android:layout_marginEnd">@dimen/expanding_entry_card_marginEnd</item>
-        <item name="android:layout_marginStart">@dimen/expanding_entry_card_marginStart</item>
+        <item name="android:layout_marginEnd">@dimen/expanding_entry_card_marginStartEnd</item>
+        <item name="android:layout_marginStart">@dimen/expanding_entry_card_marginStartEnd</item>
         <item name="android:orientation">vertical</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
diff --git a/src/com/android/contacts/interactions/CalendarInteraction.java b/src/com/android/contacts/interactions/CalendarInteraction.java
index 12a968e..efd724a 100644
--- a/src/com/android/contacts/interactions/CalendarInteraction.java
+++ b/src/com/android/contacts/interactions/CalendarInteraction.java
@@ -282,4 +282,9 @@
         // The default TalkBack is good
         return null;
     }
+
+    @Override
+    public int getIconResourceId() {
+        return CALENDAR_ICON_RES;
+    }
 }
diff --git a/src/com/android/contacts/interactions/CallLogInteraction.java b/src/com/android/contacts/interactions/CallLogInteraction.java
index 4e5a143..702c23b 100644
--- a/src/com/android/contacts/interactions/CallLogInteraction.java
+++ b/src/com/android/contacts/interactions/CallLogInteraction.java
@@ -202,4 +202,9 @@
         }
         return callType;
     }
+
+    @Override
+    public int getIconResourceId() {
+        return CALL_LOG_ICON_RES;
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/interactions/ContactInteraction.java b/src/com/android/contacts/interactions/ContactInteraction.java
index af19984..11bbb49 100644
--- a/src/com/android/contacts/interactions/ContactInteraction.java
+++ b/src/com/android/contacts/interactions/ContactInteraction.java
@@ -33,4 +33,6 @@
     Drawable getBodyIcon(Context context);
     Drawable getFooterIcon(Context context);
     String getContentDescription(Context context);
+    /** The resource id for the icon, if available. May be 0 if one is not available. */
+    int getIconResourceId();
 }
diff --git a/src/com/android/contacts/interactions/SmsInteraction.java b/src/com/android/contacts/interactions/SmsInteraction.java
index bc55572..34adfc1 100644
--- a/src/com/android/contacts/interactions/SmsInteraction.java
+++ b/src/com/android/contacts/interactions/SmsInteraction.java
@@ -160,4 +160,9 @@
         return context.getResources().getString(R.string.content_description_recent_sms,
                 messageDetails);
     }
+
+    @Override
+    public int getIconResourceId() {
+        return SMS_ICON_RES;
+    }
 }
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index db1f4a7..1313e24 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -86,17 +86,19 @@
         private final Drawable mThirdIcon;
         private final Intent mThirdIntent;
         private final String mThirdContentDescription;
+        private final int mIconResourceId;
 
         public Entry(int id, Drawable icon, String header, String subHeader, String text,
                 String primaryContentDescription, Intent intent, Drawable alternateIcon,
                 Intent alternateIntent, String alternateContentDescription,
                 boolean shouldApplyColor, boolean isEditable,
                 EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
-                String thirdContentDescription) {
+                String thirdContentDescription, int iconResourceId) {
             this(id, icon, header, subHeader, null, text, null, primaryContentDescription, intent,
                     alternateIcon,
                     alternateIntent, alternateContentDescription, shouldApplyColor, isEditable,
-                    entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
+                    entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription,
+                    iconResourceId);
         }
 
         public Entry(int id, Drawable mainIcon, String header, String subHeader,
@@ -105,7 +107,7 @@
                 Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
                 boolean shouldApplyColor, boolean isEditable,
                 EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
-                String thirdContentDescription) {
+                String thirdContentDescription, int iconResourceId) {
             mId = id;
             mIcon = mainIcon;
             mHeader = header;
@@ -124,6 +126,7 @@
             mThirdIcon = thirdIcon;
             mThirdIntent = thirdIntent;
             mThirdContentDescription = thirdContentDescription;
+            mIconResourceId = iconResourceId;
         }
 
         Drawable getIcon() {
@@ -197,6 +200,10 @@
         String getThirdContentDescription() {
             return mThirdContentDescription;
         }
+
+        int getIconResourceId() {
+            return mIconResourceId;
+        }
     }
 
     public interface ExpandingEntryCardViewListener {
@@ -231,6 +238,7 @@
     private ViewGroup mAnimationViewGroup;
     private LinearLayout mBadgeContainer;
     private final List<ImageView> mBadges;
+    private final List<Integer> mBadgeIds;
     /**
      * List to hold the separators. This saves us from reconstructing every expand/collapse and
      * provides a smoother animation.
@@ -270,6 +278,7 @@
         mBadgeContainer = (LinearLayout) mExpandCollapseButton.findViewById(R.id.badge_container);
 
         mBadges = new ArrayList<ImageView>();
+        mBadgeIds = new ArrayList<Integer>();
     }
 
     /**
@@ -719,11 +728,17 @@
     private void updateBadges() {
         if (mIsExpanded) {
             mBadgeContainer.removeAllViews();
+            mBadgeIds.clear();
         } else {
             // Inflate badges if not yet created
             if (mBadges.size() < mEntries.size() - mCollapsedEntriesCount) {
                 for (int i = mCollapsedEntriesCount; i < mEntries.size(); i++) {
                     Drawable badgeDrawable = mEntries.get(i).get(0).getIcon();
+                    int badgeResourceId = mEntries.get(i).get(0).getIconResourceId();
+                    // Do not add the same badge twice
+                    if (badgeResourceId != 0 && mBadgeIds.contains(badgeResourceId)) {
+                        continue;
+                    }
                     if (badgeDrawable != null) {
                         ImageView badgeView = new ImageView(getContext());
                         LinearLayout.LayoutParams badgeViewParams = new LinearLayout.LayoutParams(
@@ -736,6 +751,7 @@
                         badgeView.setLayoutParams(badgeViewParams);
                         badgeView.setImageDrawable(badgeDrawable);
                         mBadges.add(badgeView);
+                        mBadgeIds.add(badgeResourceId);
                     }
                 }
             }
@@ -758,6 +774,8 @@
         transitionSet.addTransition(boundsTransition);
         transitionSet.addTransition(fadeIn);
 
+        transitionSet.excludeTarget(R.id.text, /* exclude = */ true);
+
         final ViewGroup transitionViewContainer = mAnimationViewGroup == null ?
                 this : mAnimationViewGroup;
 
@@ -916,10 +934,17 @@
     public static final class EntryContextMenuInfo implements ContextMenuInfo {
         private final String mCopyText;
         private final String mCopyLabel;
+        private final String mMimeType;
+        private final long mId;
+        private final boolean mIsSuperPrimary;
 
-        public EntryContextMenuInfo(String copyText, String copyLabel) {
+        public EntryContextMenuInfo(String copyText, String copyLabel, String mimeType, long id,
+                boolean isSuperPrimary) {
             mCopyText = copyText;
             mCopyLabel = copyLabel;
+            mMimeType = mimeType;
+            mId = id;
+            mIsSuperPrimary = isSuperPrimary;
         }
 
         public String getCopyText() {
@@ -929,6 +954,18 @@
         public String getCopyLabel() {
             return mCopyLabel;
         }
+
+        public String getMimeType() {
+            return mMimeType;
+        }
+
+        public long getId() {
+            return mId;
+        }
+
+        public boolean isSuperPrimary() {
+            return mIsSuperPrimary;
+        }
     }
 
     static final class EntryTag {
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 293fae6..360ffb7 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -175,7 +175,8 @@
 
     private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150;
     private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1;
-    private static final int SCRIM_COLOR = Color.argb(0xC8, 0, 0, 0);
+    private static final int DEFAULT_SCRIM_ALPHA = 0xC8;
+    private static final int SCRIM_COLOR = Color.argb(DEFAULT_SCRIM_ALPHA, 0, 0, 0);
     private static final int REQUEST_CODE_CONTACT_SELECTION_ACTIVITY = 2;
     private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms";
 
@@ -204,6 +205,8 @@
     private int mExtraMode;
     private int mStatusBarColor;
     private boolean mHasAlreadyBeenOpened;
+    private boolean mOnlyOnePhoneNumber;
+    private boolean mOnlyOneEmail;
 
     private QuickContactImageView mPhotoView;
     private ExpandingEntryCardView mContactCard;
@@ -355,6 +358,16 @@
                 }
             }
 
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Force the window dim amount to the scrim value for app transition animations
+            // The scrim may be removed before the window transitions to the new activity, which
+            // can cause a flicker in the status and navigation bar. Set dim alone does not work
+            // well because the request is passed through IPC which makes it slow to animate.
+            getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
+                    WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+            getWindow().setDimAmount(mWindowScrim.getAlpha() / DEFAULT_SCRIM_ALPHA);
+
             mHasIntentLaunched = true;
             startActivity(intent);
         }
@@ -373,6 +386,12 @@
         }
     };
 
+    private interface ContextMenuIds {
+        static final int COPY_TEXT = 0;
+        static final int CLEAR_DEFAULT = 1;
+        static final int SET_DEFAULT = 2;
+    }
+
     private final OnCreateContextMenuListener mEntryContextMenuListener =
             new OnCreateContextMenuListener() {
         @Override
@@ -380,9 +399,36 @@
             if (menuInfo == null) {
                 return;
             }
-            EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo;
+            final EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo;
             menu.setHeaderTitle(info.getCopyText());
-            menu.add(R.string.copy_text);
+            menu.add(ContextMenu.NONE, ContextMenuIds.COPY_TEXT,
+                    ContextMenu.NONE, getString(R.string.copy_text));
+
+            // Don't allow setting or clearing of defaults for non-editable contacts
+            if (!isContactEditable()) {
+                return;
+            }
+
+            final String selectedMimeType = info.getMimeType();
+
+            // Defaults to true will only enable the detail to be copied to the clipboard.
+            boolean onlyOneOfMimeType = true;
+
+            // Only allow primary support for Phone and Email content types
+            if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
+                onlyOneOfMimeType = mOnlyOnePhoneNumber;
+            } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
+                onlyOneOfMimeType = mOnlyOneEmail;
+            }
+
+            // Checking for previously set default
+            if (info.isSuperPrimary()) {
+                menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT,
+                        ContextMenu.NONE, getString(R.string.clear_default));
+            } else if (!onlyOneOfMimeType) {
+                menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT,
+                        ContextMenu.NONE, getString(R.string.set_default));
+            }
         }
     };
 
@@ -396,8 +442,24 @@
             return false;
         }
 
-        ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(), true);
-        return true;
+        switch (item.getItemId()) {
+            case ContextMenuIds.COPY_TEXT:
+                ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(),
+                        true);
+                return true;
+            case ContextMenuIds.SET_DEFAULT:
+                final Intent setIntent = ContactSaveService.createSetSuperPrimaryIntent(this,
+                        menuInfo.getId());
+                this.startService(setIntent);
+                return true;
+            case ContextMenuIds.CLEAR_DEFAULT:
+                final Intent clearIntent = ContactSaveService.createClearPrimaryIntent(this,
+                        menuInfo.getId());
+                this.startService(clearIntent);
+                return true;
+            default:
+                throw new IllegalArgumentException("Unknown menu option " + item.getItemId());
+        }
     }
 
     /**
@@ -827,6 +889,9 @@
     private void startInteractionLoaders(Cp2DataCardModel cp2DataCardModel) {
         final Map<String, List<DataItem>> dataItemsMap = cp2DataCardModel.dataItemsMap;
         final List<DataItem> phoneDataItems = dataItemsMap.get(Phone.CONTENT_ITEM_TYPE);
+        if (phoneDataItems != null && phoneDataItems.size() == 1) {
+            mOnlyOnePhoneNumber = true;
+        }
         String[] phoneNumbers = null;
         if (phoneDataItems != null) {
             phoneNumbers = new String[phoneDataItems.size()];
@@ -854,6 +919,9 @@
 
         Trace.beginSection("start calendar loader");
         final List<DataItem> emailDataItems = dataItemsMap.get(Email.CONTENT_ITEM_TYPE);
+        if (emailDataItems != null && emailDataItems.size() == 1) {
+            mOnlyOneEmail = true;
+        }
         String[] emailAddresses = null;
         if (emailDataItems != null) {
             emailAddresses = new String[emailDataItems.size()];
@@ -952,10 +1020,12 @@
                     /* shouldApplyColor = */ false,
                     /* isEditable = */ false,
                     /* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName,
-                            getResources().getString(R.string.name_phonetic)),
+                            getResources().getString(R.string.name_phonetic),
+                            /* mimeType = */ null, /* id = */ -1, /* isPrimary = */ false),
                     /* thirdIcon = */ null,
                     /* thirdIntent = */ null,
-                    /* thirdContentDescription = */ null);
+                    /* thirdContentDescription = */ null,
+                    /* iconResourceId = */ 0);
             List<Entry> phoneticList = new ArrayList<>();
             phoneticList.add(phoneticEntry);
             // Phonetic name comes after nickname. Check to see if the first entry type is nickname
@@ -1008,7 +1078,7 @@
                 /* alternateContentDescription = */ null, /* shouldApplyColor = */ true,
                 /* isEditable = */ false, /* EntryContextMenuInfo = */ null,
                 /* thirdIcon = */ null, /* thirdIntent = */ null,
-                /* thirdContentDescription = */ null);
+                /* thirdContentDescription = */ null, R.drawable.ic_phone_24dp);
 
         final Drawable emailIcon = getResources().getDrawable(
                 R.drawable.ic_email_24dp).mutate();
@@ -1019,7 +1089,8 @@
                 /* alternateIntent = */ null, /* alternateContentDescription = */ null,
                 /* shouldApplyColor = */ true, /* isEditable = */ false,
                 /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null,
-                /* thirdIntent = */ null, /* thirdContentDescription = */ null);
+                /* thirdIntent = */ null, /* thirdContentDescription = */ null,
+                R.drawable.ic_email_24dp);
 
         final List<List<Entry>> promptEntries = new ArrayList<>();
         promptEntries.add(new ArrayList<Entry>(1));
@@ -1184,6 +1255,7 @@
         Drawable thirdIcon = null;
         Intent thirdIntent = null;
         String thirdContentDescription = null;
+        int iconResourceId = 0;
 
         context = context.getApplicationContext();
         final Resources res = context.getResources();
@@ -1211,12 +1283,14 @@
                         im.getCustomProtocol()).toString();
                 subHeader = im.getData();
             }
-            entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header);
+            entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header,
+                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
         } else if (dataItem instanceof OrganizationDataItem) {
             final OrganizationDataItem organization = (OrganizationDataItem) dataItem;
             header = res.getString(R.string.header_organization_entry);
             subHeader = organization.getCompany();
-            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
+            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
+                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
             text = organization.getTitle();
         } else if (dataItem instanceof NicknameDataItem) {
             final NicknameDataItem nickname = (NicknameDataItem) dataItem;
@@ -1231,18 +1305,21 @@
             if (!duplicatesTitle) {
                 header = res.getString(R.string.header_nickname_entry);
                 subHeader = nickname.getName();
-                entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
+                entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
+                        dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
             }
         } else if (dataItem instanceof NoteDataItem) {
             final NoteDataItem note = (NoteDataItem) dataItem;
             header = res.getString(R.string.header_note_entry);
             subHeader = note.getNote();
-            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
+            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
+                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
         } else if (dataItem instanceof WebsiteDataItem) {
             final WebsiteDataItem website = (WebsiteDataItem) dataItem;
             header = res.getString(R.string.header_website_entry);
             subHeader = website.getUrl();
-            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
+            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
+                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
             try {
                 final WebAddress webAddress = new WebAddress(website.buildDataString(context,
                         kind));
@@ -1268,7 +1345,8 @@
                         event.getLabel()).toString();
             }
             text = DateUtils.formatDate(context, dataString);
-            entryContextMenuInfo = new EntryContextMenuInfo(text, header);
+            entryContextMenuInfo = new EntryContextMenuInfo(text, header,
+                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
         } else if (dataItem instanceof RelationDataItem) {
             final RelationDataItem relation = (RelationDataItem) dataItem;
             final String dataString = relation.buildDataString(context, kind);
@@ -1279,7 +1357,8 @@
             }
             header = res.getString(R.string.header_relation_entry);
             subHeader = relation.getName();
-            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
+            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
+                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
             if (relation.hasKindTypeColumn(kind)) {
                 text = Relation.getTypeLabel(res,
                         relation.getKindTypeColumn(kind),
@@ -1291,7 +1370,8 @@
                 primaryContentDescription.append(res.getString(R.string.call_other)).append(" ");
                 header = phone.buildDataString(context, kind);
                 entryContextMenuInfo = new EntryContextMenuInfo(header,
-                        res.getString(R.string.phoneLabelsGroup));
+                        res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(),
+                        dataItem.getId(), dataItem.isSuperPrimary());
                 if (phone.hasKindTypeColumn(kind)) {
                     text = Phone.getTypeLabel(res, phone.getKindTypeColumn(kind),
                             phone.getLabel()).toString();
@@ -1299,6 +1379,7 @@
                 }
                 primaryContentDescription.append(header);
                 icon = res.getDrawable(R.drawable.ic_phone_24dp);
+                iconResourceId = R.drawable.ic_phone_24dp;
                 if (PhoneCapabilityTester.isPhone(context)) {
                     intent = CallUtil.getCallIntent(phone.getNumber());
                 }
@@ -1326,7 +1407,8 @@
                 intent = new Intent(Intent.ACTION_SENDTO, mailUri);
                 header = email.getAddress();
                 entryContextMenuInfo = new EntryContextMenuInfo(header,
-                        res.getString(R.string.emailLabelsGroup));
+                        res.getString(R.string.emailLabelsGroup), dataItem.getMimeType(),
+                        dataItem.getId(), dataItem.isSuperPrimary());
                 if (email.hasKindTypeColumn(kind)) {
                     text = Email.getTypeLabel(res, email.getKindTypeColumn(kind),
                             email.getLabel()).toString();
@@ -1334,6 +1416,7 @@
                 }
                 primaryContentDescription.append(header);
                 icon = res.getDrawable(R.drawable.ic_email_24dp);
+                iconResourceId = R.drawable.ic_email_24dp;
             }
         } else if (dataItem instanceof StructuredPostalDataItem) {
             StructuredPostalDataItem postal = (StructuredPostalDataItem) dataItem;
@@ -1343,7 +1426,8 @@
                 intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
                 header = postal.getFormattedAddress();
                 entryContextMenuInfo = new EntryContextMenuInfo(header,
-                        res.getString(R.string.postalLabelsGroup));
+                        res.getString(R.string.postalLabelsGroup), dataItem.getMimeType(),
+                        dataItem.getId(), dataItem.isSuperPrimary());
                 if (postal.hasKindTypeColumn(kind)) {
                     text = StructuredPostal.getTypeLabel(res,
                             postal.getKindTypeColumn(kind), postal.getLabel()).toString();
@@ -1356,6 +1440,7 @@
                 alternateContentDescription.append(res.getString(
                         R.string.content_description_directions)).append(" ").append(header);
                 icon = res.getDrawable(R.drawable.ic_place_24dp);
+                iconResourceId = R.drawable.ic_place_24dp;
             }
         } else if (dataItem instanceof SipAddressDataItem) {
             if (PhoneCapabilityTester.isSipPhone(context)) {
@@ -1368,7 +1453,8 @@
                     intent = CallUtil.getCallIntent(callUri);
                     header = address;
                     entryContextMenuInfo = new EntryContextMenuInfo(header,
-                            res.getString(R.string.phoneLabelsGroup));
+                            res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(),
+                            dataItem.getId(), dataItem.isSuperPrimary());
                     if (sip.hasKindTypeColumn(kind)) {
                         text = SipAddress.getTypeLabel(res,
                                 sip.getKindTypeColumn(kind), sip.getLabel()).toString();
@@ -1376,6 +1462,7 @@
                     }
                     primaryContentDescription.append(header);
                     icon = res.getDrawable(R.drawable.ic_dialer_sip_black_24dp);
+                    iconResourceId = R.drawable.ic_dialer_sip_black_24dp;
                 }
             }
         } else if (dataItem instanceof StructuredNameDataItem) {
@@ -1404,19 +1491,25 @@
                                 intent.getDataString())) {
                             icon = res.getDrawable(
                                     R.drawable.ic_add_to_circles_black_24);
+                            iconResourceId = R.drawable.ic_add_to_circles_black_24;
                         } else {
                             icon = res.getDrawable(R.drawable.ic_google_plus_24dp);
+                            iconResourceId = R.drawable.ic_google_plus_24dp;
                         }
                         break;
                     case MIMETYPE_HANGOUTS:
                         if (INTENT_DATA_HANGOUTS_VIDEO.equals(intent.getDataString())) {
                             icon = res.getDrawable(R.drawable.ic_hangout_video_24dp);
+                            iconResourceId = R.drawable.ic_hangout_video_24dp;
                         } else {
                             icon = res.getDrawable(R.drawable.ic_hangout_24dp);
+                            iconResourceId = R.drawable.ic_hangout_24dp;
                         }
                         break;
                     default:
-                        entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype);
+                        entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype,
+                                dataItem.getMimeType(), dataItem.getId(),
+                                dataItem.isSuperPrimary());
                         icon = ResolveCache.getInstance(context).getIcon(
                                 dataItem.getMimeType(), intent);
                         // Call mutate to create a new Drawable.ConstantState for color filtering
@@ -1458,7 +1551,8 @@
         return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon,
                 primaryContentDescription.toString(), intent, alternateIcon, alternateIntent,
                 alternateContentDescription.toString(), shouldApplyColor, isEditable,
-                entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
+                entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription,
+                iconResourceId);
     }
 
     private List<Entry> dataItemsToEntries(List<DataItem> dataItems,
@@ -1641,7 +1735,8 @@
                     /* EntryContextMenuInfo = */ null,
                     /* thirdIcon = */ null,
                     /* thirdIntent = */ null,
-                    /* thirdContentDescription = */ null));
+                    /* thirdContentDescription = */ null,
+                    interaction.getIconResourceId()));
         }
         return entries;
     }
@@ -1976,6 +2071,14 @@
         builder.createContactShortcutIntent(mContactData.getLookupUri());
     }
 
+    private boolean isShortcutCreatable() {
+        final Intent createShortcutIntent = new Intent();
+        createShortcutIntent.setAction(ACTION_INSTALL_SHORTCUT);
+        final List<ResolveInfo> receivers = getPackageManager()
+                .queryBroadcastReceivers(createShortcutIntent, 0);
+        return receivers != null && receivers.size() > 0;
+    }
+
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         final MenuInflater inflater = getMenuInflater();
@@ -2008,6 +2111,9 @@
             final MenuItem shareMenuItem = menu.findItem(R.id.menu_share);
             shareMenuItem.setVisible(isContactShareable());
 
+            final MenuItem shortcutMenuItem = menu.findItem(R.id.menu_create_contact_shortcut);
+            shortcutMenuItem.setVisible(isShortcutCreatable());
+
             return true;
         }
         return false;
diff --git a/src/com/android/contacts/widget/MultiShrinkScroller.java b/src/com/android/contacts/widget/MultiShrinkScroller.java
index 47b6d6f..15dca5c 100644
--- a/src/com/android/contacts/widget/MultiShrinkScroller.java
+++ b/src/com/android/contacts/widget/MultiShrinkScroller.java
@@ -275,21 +275,7 @@
         mLargeTextView = (TextView) findViewById(R.id.large_title);
         mInvisiblePlaceholderTextView = (TextView) findViewById(R.id.placeholder_textview);
         mStartColumn = findViewById(R.id.empty_start_column);
-        // Touching the empty space should close the card
-        if (mStartColumn != null) {
-            mStartColumn.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    scrollOffBottom();
-                }
-            });
-            findViewById(R.id.empty_end_column).setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    scrollOffBottom();
-                }
-            });
-        }
+
         mListener = listener;
         mIsOpenContactSquare = isOpenContactSquare;
 
@@ -895,10 +881,17 @@
     /**
      * Returns the minimum size that we want to compress the header to, given that we don't want to
      * allow the the ScrollView to scroll unless there is new content off of the edge of ScrollView.
+     * This value is never smaller than the current header height.
      */
     private int getFullyCompressedHeaderHeight() {
-        return Math.min(Math.max(mToolbar.getLayoutParams().height - getOverflowingChildViewSize(),
-                        mMinimumHeaderHeight), getMaximumScrollableHeaderHeight());
+        final int minimumScrollableHeaderHeight =
+                Math.min(Math.max(mToolbar.getLayoutParams().height - getOverflowingChildViewSize(),
+                mMinimumHeaderHeight), getMaximumScrollableHeaderHeight());
+        // It is possible that the current header height is smaller than the minimum height
+        // that can be obtained by scrolling since tapping on the contact photo collapses it.
+        // In this case, just return the current height or the minimum height.
+        return Math.max(Math.min(minimumScrollableHeaderHeight, mToolbar.getLayoutParams().height),
+                mMinimumHeaderHeight);
     }
 
     /**