Merge "Fade QC contact photo more slowly" into lmp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0457681..06222c9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -46,7 +46,7 @@
 
     <application
         android:name="com.android.contacts.ContactsApplication"
-        android:label="@string/contactsList"
+        android:label="@string/applicationLabel"
         android:icon="@mipmap/ic_contacts_clr_48cv_44dp"
         android:taskAffinity="android.task.contacts"
         android:hardwareAccelerated="true"
@@ -55,7 +55,7 @@
 
         <!-- The main Contacts activity with the contact list, favorites, and groups. -->
         <activity android:name=".activities.PeopleActivity"
-            android:label="@string/people"
+            android:label="@string/launcherActivityLabel"
             android:theme="@style/PeopleTheme"
             android:clearTaskOnLaunch="true"
             android:launchMode="singleTop"
@@ -139,7 +139,7 @@
         </activity>
 
         <activity android:name=".activities.ContactSelectionActivity"
-            android:label="@string/contactsList"
+            android:label="@string/launcherActivityLabel"
             android:theme="@style/ContactPickerTheme"
             android:launchMode="singleTop"
             android:clearTaskOnLaunch="true"
@@ -387,6 +387,7 @@
 
         <!-- vCard related -->
         <activity android:name=".common.vcard.ImportVCardActivity"
+            android:label="@string/launcherActivityLabel"
             android:configChanges="orientation|screenSize|keyboardHidden"
             android:theme="@style/BackgroundOnlyTheme">
             <intent-filter>
@@ -399,6 +400,7 @@
         </activity>
 
         <activity android:name=".common.vcard.NfcImportVCardActivity"
+            android:label="@string/launcherActivityLabel"
             android:configChanges="orientation|screenSize|keyboardHidden"
             android:theme="@style/BackgroundOnlyTheme">
             <intent-filter>
@@ -410,17 +412,21 @@
         </activity>
 
         <activity android:name=".common.vcard.CancelActivity"
+            android:label="@string/launcherActivityLabel"
             android:theme="@style/BackgroundOnlyTheme" />
 
         <activity android:name=".common.vcard.SelectAccountActivity"
+            android:label="@string/launcherActivityLabel"
             android:theme="@style/BackgroundOnlyTheme" />
 
         <activity android:name=".common.vcard.ExportVCardActivity"
+            android:label="@string/launcherActivityLabel"
             android:theme="@style/BackgroundOnlyTheme" />
 
         <service
             android:name=".common.vcard.VCardService"
             android:exported="false" />
+        <!-- end vCard related -->
 
         <!-- Pinned header list demo -->
         <activity android:name=".widget.PinnedHeaderListDemoActivity">
@@ -438,6 +444,7 @@
         <activity
             android:name="com.android.contacts.NonPhoneActivity"
             android:theme="@style/NonPhoneActivityTheme"
+            android:label="@string/launcherActivityLabel"
             >
             <intent-filter android:priority="-1">
                 <action android:name="android.intent.action.MAIN"/>
diff --git a/res/layout-sw600dp/search_header.xml b/res/layout-sw600dp/search_header.xml
deleted file mode 100644
index 85f0169..0000000
--- a/res/layout-sw600dp/search_header.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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.
--->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:id="@+id/totalContactsText"
-    android:minHeight="@dimen/contact_filter_header_min_height"
-    android:paddingTop="24dip"
-    android:textAppearance="?android:attr/textAppearanceMedium"
-    android:textColor="?android:attr/textColorTertiary" />
diff --git a/res/layout-sw720dp/quickcontact_activity.xml b/res/layout-sw720dp/quickcontact_activity.xml
index e8fcf54..efbb4d1 100644
--- a/res/layout-sw720dp/quickcontact_activity.xml
+++ b/res/layout-sw720dp/quickcontact_activity.xml
@@ -33,7 +33,8 @@
             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:layout_weight="@integer/contact_list_space_layout_weight"
+            android:contentDescription="@string/quickcontact_transparent_view_description" />
 
         <LinearLayout
             android:layout_width="0dp"
@@ -62,7 +63,8 @@
             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:layout_weight="@integer/contact_list_space_layout_weight"
+            android:contentDescription="@string/quickcontact_transparent_view_description" />
 
     </LinearLayout>
 
diff --git a/res/layout/edit_kind_title.xml b/res/layout/edit_kind_title.xml
index b7de66f..acdcc07 100644
--- a/res/layout/edit_kind_title.xml
+++ b/res/layout/edit_kind_title.xml
@@ -21,16 +21,12 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
     android:paddingStart="8dip"
     android:paddingEnd="8dip"
     android:focusable="false">
     <TextView
         android:id="@+id/kind_title"
         style="@style/EditKindSeparatorTextViewStyle"
-        android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-        android:paddingStart="8dip"
+        android:paddingStart="0dip"
         android:paddingEnd="8dip" />
 </FrameLayout>
diff --git a/res/values-sw600dp-land/colors.xml b/res/values-sw600dp-land/colors.xml
index e36bfa6..c5f846e 100644
--- a/res/values-sw600dp-land/colors.xml
+++ b/res/values-sw600dp-land/colors.xml
@@ -14,5 +14,6 @@
      limitations under the License.
 -->
 <resources>
-    <color name="list_item_pinned_header_color">#FFFFFF</color>
+    <!-- This needs to match the color of the background card, when the center card is visible. -->
+    <color name="list_item_pinned_header_color">@color/contact_all_list_background_color</color>
 </resources>
diff --git a/res/values-sw720dp/colors.xml b/res/values-sw720dp/colors.xml
new file mode 100644
index 0000000..c5f846e
--- /dev/null
+++ b/res/values-sw720dp/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<resources>
+    <!-- This needs to match the color of the background card, when the center card is visible. -->
+    <color name="list_item_pinned_header_color">@color/contact_all_list_background_color</color>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6cd9c14..985a4e5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -53,5 +53,5 @@
     <color name="call_arrow_red">#ff2e58</color>
 
     <!-- Background color of pinned header items. -->
-    <color name="list_item_pinned_header_color">#f5f5f5</color>
+    <color name="list_item_pinned_header_color">@color/background_primary</color>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5497ee2..2d39407 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -15,9 +15,13 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <!-- Title for the activity that opens the Contacts app.  This is the name
+    <!-- Application name used in Settings/Apps. Default label for activities
+         that don't specify a label. -->
+    <string name="applicationLabel">Contacts</string>
+
+    <!-- Title for the activity that launches Contacts.  This is the name
          used in the Launcher icon. -->
-    <string name="people">Contacts</string>
+    <string name="launcherActivityLabel">Contacts</string>
 
     <!-- Directory partition name -->
     <string name="contactsList">Contacts</string>
@@ -317,7 +321,7 @@
     <!-- Shown as a toast when the user taps on a QuickContact icon, and no application
          was found that could perform the selected action. [CHAR LIMIT=NONE] -->
     <string name="quickcontact_missing_app">No app was found to handle this action.</string>
-    <!-- Content description for the transparent view above the visible section of QuickContacts.
+    <!-- Content description for the transparent views around the visible section of QuickContacts.
          Clicking this view causes Quick Contacts to close. [CHAR LIMIT=NONE] -->
     <string name="quickcontact_transparent_view_description">Click to return to previous screen</string>
 
@@ -702,6 +706,19 @@
     <!-- Content description for directions secondary button [CHAR LIMIT=NONE] -->
     <string name="content_description_directions">directions to location</string>
 
+    <!-- Content description for recent sms interaction [CHAR LIMIT=NONE] -->
+    <string name="content_description_recent_sms">recent sms. <xliff:g id="message_details">%s</xliff:g>. click to respond</string>
+
+    <!-- Header for the Relation entry [CHAR LIMIT=NONE] -->
+    <string name="content_description_recent_call_type_incoming">incoming</string>
+    <!-- Header for the Relation entry [CHAR LIMIT=NONE] -->
+    <string name="content_description_recent_call_type_outgoing">outgoing</string>
+    <!-- Header for the Relation entry [CHAR LIMIT=NONE] -->
+    <string name="content_description_recent_call_type_missed">missed</string>
+
+    <!-- Content description for recent sms interaction [CHAR LIMIT=NONE] -->
+    <string name="content_description_recent_call">recent call. <xliff:g id="call_details">%s</xliff:g>. click to call back</string>
+
     <!-- Prefix for messages that you sent [CHAR LIMIT=40] -->
     <string name="message_from_you_prefix">You: <xliff:g id="sms_body">%s</xliff:g></string>
 
diff --git a/src/com/android/contacts/interactions/CalendarInteraction.java b/src/com/android/contacts/interactions/CalendarInteraction.java
index b3862a2..12a968e 100644
--- a/src/com/android/contacts/interactions/CalendarInteraction.java
+++ b/src/com/android/contacts/interactions/CalendarInteraction.java
@@ -130,7 +130,7 @@
     }
 
     public Boolean getAllDay() {
-        return mValues.getAsBoolean(Attendees.ALL_DAY);
+        return mValues.getAsInteger(Attendees.ALL_DAY) == 1 ? true : false;
     }
 
     public Integer getAvailability() {
@@ -276,4 +276,10 @@
     public String getUid2445() {
         return mValues.getAsString(Attendees.UID_2445);
     }
+
+    @Override
+    public String getContentDescription(Context context) {
+        // The default TalkBack is good
+        return null;
+    }
 }
diff --git a/src/com/android/contacts/interactions/CallLogInteraction.java b/src/com/android/contacts/interactions/CallLogInteraction.java
index 28b9655..4e5a143 100644
--- a/src/com/android/contacts/interactions/CallLogInteraction.java
+++ b/src/com/android/contacts/interactions/CallLogInteraction.java
@@ -173,4 +173,33 @@
     public Integer getType() {
         return mValues.getAsInteger(Calls.TYPE);
     }
+
+    @Override
+    public String getContentDescription(Context context) {
+        String callDetails = getCallTypeString(context) + ". " + getViewFooter(context) + ". " +
+                getViewHeader(context) + ". " + getViewFooter(context);
+        return context.getResources().getString(R.string.content_description_recent_call,
+                callDetails);
+    }
+
+    private String getCallTypeString(Context context) {
+        String callType = "";
+        Resources res = context.getResources();
+        Integer type = getType();
+        if (type == null) {
+            return callType;
+        }
+        switch (type) {
+            case Calls.INCOMING_TYPE:
+                callType = res.getString(R.string.content_description_recent_call_type_incoming);
+                break;
+            case Calls.MISSED_TYPE:
+                callType = res.getString(R.string.content_description_recent_call_type_missed);
+                break;
+            case Calls.OUTGOING_TYPE:
+                callType = res.getString(R.string.content_description_recent_call_type_outgoing);
+                break;
+        }
+        return callType;
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/interactions/CallLogInteractionsLoader.java b/src/com/android/contacts/interactions/CallLogInteractionsLoader.java
index 9cbc0b4..ed6f2d5 100644
--- a/src/com/android/contacts/interactions/CallLogInteractionsLoader.java
+++ b/src/com/android/contacts/interactions/CallLogInteractionsLoader.java
@@ -23,6 +23,8 @@
 import android.database.DatabaseUtils;
 import android.net.Uri;
 import android.provider.CallLog.Calls;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -101,11 +103,17 @@
     }
 
     private List<ContactInteraction> getCallLogInteractions(String phoneNumber) {
-        final Uri uri = Uri.withAppendedPath(Calls.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
+        final String normalizedNumber = PhoneNumberUtils.normalizeNumber(phoneNumber);
+        // If the number contains only symbols, we can skip it
+        if (TextUtils.isEmpty(normalizedNumber)) {
+            return Collections.emptyList();
+        }
+        final Uri uri = Uri.withAppendedPath(Calls.CONTENT_FILTER_URI,
+                Uri.encode(normalizedNumber));
         // Append the LIMIT clause onto the ORDER BY clause. This won't cause crashes as long
         // as we don't also set the {@link android.provider.CallLog.Calls.LIMIT_PARAM_KEY} that
         // becomes available in KK.
-        String orderByAndLimit = Calls.DATE + " DESC LIMIT " + mMaxToRetrieve;
+        final String orderByAndLimit = Calls.DATE + " DESC LIMIT " + mMaxToRetrieve;
         final Cursor cursor = getContext().getContentResolver().query(uri, null, null, null,
                 orderByAndLimit);
         try {
diff --git a/src/com/android/contacts/interactions/ContactInteraction.java b/src/com/android/contacts/interactions/ContactInteraction.java
index 3f7a842..af19984 100644
--- a/src/com/android/contacts/interactions/ContactInteraction.java
+++ b/src/com/android/contacts/interactions/ContactInteraction.java
@@ -32,4 +32,5 @@
     Drawable getIcon(Context context);
     Drawable getBodyIcon(Context context);
     Drawable getFooterIcon(Context context);
+    String getContentDescription(Context context);
 }
diff --git a/src/com/android/contacts/interactions/SmsInteraction.java b/src/com/android/contacts/interactions/SmsInteraction.java
index 3f86eef..bc55572 100644
--- a/src/com/android/contacts/interactions/SmsInteraction.java
+++ b/src/com/android/contacts/interactions/SmsInteraction.java
@@ -152,4 +152,12 @@
     public Integer getType() {
         return mValues.getAsInteger(Sms.TYPE);
     }
+
+    @Override
+    public String getContentDescription(Context context) {
+        String messageDetails = getViewHeader(context) + ". " + getViewBody(context) + ". " +
+                getViewFooter(context);
+        return context.getResources().getString(R.string.content_description_recent_sms,
+                messageDetails);
+    }
 }
diff --git a/src/com/android/contacts/quickcontact/DirectoryContactUtil.java b/src/com/android/contacts/quickcontact/DirectoryContactUtil.java
index d483af3..1571b0a 100644
--- a/src/com/android/contacts/quickcontact/DirectoryContactUtil.java
+++ b/src/com/android/contacts/quickcontact/DirectoryContactUtil.java
@@ -35,41 +35,6 @@
         return contactData.getDirectoryExportSupport() != Directory.EXPORT_SUPPORT_NONE;
     }
 
-    public static void addToMyContacts(Contact contactData, Context context,
-            FragmentManager fragmentManager,
-            SelectAccountDialogFragmentListener selectAccountCallbacks) {
-        int exportSupport = contactData.getDirectoryExportSupport();
-        switch (exportSupport) {
-            case Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY: {
-                createCopy(contactData.getContentValues(),
-                        new AccountWithDataSet(contactData.getDirectoryAccountName(),
-                        contactData.getDirectoryAccountType(), null),
-                        context);
-                break;
-            }
-            case Directory.EXPORT_SUPPORT_ANY_ACCOUNT: {
-                final List<AccountWithDataSet> accounts =
-                        AccountTypeManager.getInstance(context).getAccounts(true);
-                if (accounts.isEmpty()) {
-                    createCopy(contactData.getContentValues(), null, context);
-                    return;  // Don't show a dialog.
-                }
-
-                // In the common case of a single writable account, auto-select
-                // it without showing a dialog.
-                if (accounts.size() == 1) {
-                    createCopy(contactData.getContentValues(), accounts.get(0), context);
-                    return;  // Don't show a dialog.
-                }
-
-                SelectAccountDialogFragment.show(fragmentManager,
-                        selectAccountCallbacks, R.string.dialog_new_contact_account,
-                        AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, null);
-                break;
-            }
-        }
-    }
-
     public static void createCopy(
             ArrayList<ContentValues> values, AccountWithDataSet account,
             Context context) {
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index b219988..db1f4a7 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -75,6 +75,7 @@
         private final Drawable mSubHeaderIcon;
         private final String mText;
         private final Drawable mTextIcon;
+        private final String mPrimaryContentDescription;
         private final Intent mIntent;
         private final Drawable mAlternateIcon;
         private final Intent mAlternateIntent;
@@ -87,17 +88,20 @@
         private final String mThirdContentDescription;
 
         public Entry(int id, Drawable icon, String header, String subHeader, String text,
-                Intent intent, Drawable alternateIcon, Intent alternateIntent,
-                String alternateContentDescription, boolean shouldApplyColor,
-                boolean isEditable, EntryContextMenuInfo entryContextMenuInfo,
-                Drawable thirdIcon, Intent thirdIntent, String thirdContentDescription) {
-            this(id, icon, header, subHeader, null, text, null, intent, alternateIcon,
+                String primaryContentDescription, Intent intent, Drawable alternateIcon,
+                Intent alternateIntent, String alternateContentDescription,
+                boolean shouldApplyColor, boolean isEditable,
+                EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
+                String thirdContentDescription) {
+            this(id, icon, header, subHeader, null, text, null, primaryContentDescription, intent,
+                    alternateIcon,
                     alternateIntent, alternateContentDescription, shouldApplyColor, isEditable,
                     entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
         }
 
         public Entry(int id, Drawable mainIcon, String header, String subHeader,
-                Drawable subHeaderIcon, String text, Drawable textIcon, Intent intent,
+                Drawable subHeaderIcon, String text, Drawable textIcon,
+                String primaryContentDescription, Intent intent,
                 Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
                 boolean shouldApplyColor, boolean isEditable,
                 EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
@@ -109,6 +113,7 @@
             mSubHeaderIcon = subHeaderIcon;
             mText = text;
             mTextIcon = textIcon;
+            mPrimaryContentDescription = primaryContentDescription;
             mIntent = intent;
             mAlternateIcon = alternateIcon;
             mAlternateIntent = alternateIntent;
@@ -145,6 +150,10 @@
             return mTextIcon;
         }
 
+        String getPrimaryContentDescription() {
+            return mPrimaryContentDescription;
+        }
+
         Intent getIntent() {
             return mIntent;
         }
@@ -582,6 +591,9 @@
                 R.layout.expanding_entry_card_item, this, false);
 
         view.setContextMenuInfo(entry.getEntryContextMenuInfo());
+        if (!TextUtils.isEmpty(entry.getPrimaryContentDescription())) {
+            view.setContentDescription(entry.getPrimaryContentDescription());
+        }
 
         final ImageView icon = (ImageView) view.findViewById(R.id.icon);
         icon.setVisibility(iconVisibility);
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index cedbea8..f70eb0d 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.quickcontact;
 
+import android.accounts.Account;
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.app.Activity;
@@ -30,6 +31,7 @@
 import android.content.Loader;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
@@ -61,8 +63,10 @@
 import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Directory;
 import android.provider.ContactsContract.DisplayNameSources;
 import android.provider.ContactsContract.DataUsageFeedback;
+import android.provider.ContactsContract.Intents;
 import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsContract.RawContacts;
 import android.support.v7.graphics.Palette;
@@ -79,7 +83,6 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnCreateContextMenuListener;
 import android.view.WindowManager;
-import android.widget.ImageView;
 import android.widget.Toast;
 import android.widget.Toolbar;
 
@@ -172,6 +175,7 @@
     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 REQUEST_CODE_CONTACT_SELECTION_ACTIVITY = 2;
     private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms";
 
     /** This is the Intent action to install a shortcut in the launcher. */
@@ -208,6 +212,7 @@
     private MultiShrinkScroller mScroller;
     private SelectAccountDialogFragmentListener mSelectAccountFragmentListener;
     private AsyncTask<Void, Void, Cp2DataCardModel> mEntriesAndActionsTask;
+    private AsyncTask<Void, Void, Void> mRecentDataTask;
     /**
      * The last copy of Cp2DataCardModel that was passed to {@link #populateContactAndAboutCard}.
      */
@@ -276,9 +281,9 @@
     private static final int MAX_PAST_CALENDAR_RETRIEVE = 3;
     private static final int MAX_FUTURE_CALENDAR_RETRIEVE = 3;
     private static final long PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR =
-            180L * 24L * 60L * 60L * 1000L /* 180 days */;
+            1L * 24L * 60L * 60L * 1000L /* 1 day */;
     private static final long FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR =
-            36L * 60L * 60L * 1000L /* 36 hours */;
+            7L * 24L * 60L * 60L * 1000L /* 7 days */;
 
     /** Id for the background Call Log Loader */
     private static final int LOADER_CALL_LOG_ID = 3;
@@ -679,6 +684,9 @@
                 resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) {
             // The contact that we were showing has been deleted.
             finish();
+        } else if (requestCode == REQUEST_CODE_CONTACT_SELECTION_ACTIVITY &&
+                resultCode != RESULT_CANCELED) {
+            processIntent(data);
         }
     }
 
@@ -935,6 +943,7 @@
                     getResources().getString(R.string.name_phonetic),
                     phoneticName,
                     /* text = */ null,
+                    /* primaryContentDescription = */ null,
                     /* intent = */ null,
                     /* alternateIcon = */ null,
                     /* alternateIntent = */ null,
@@ -992,7 +1001,8 @@
                 R.drawable.ic_phone_24dp).mutate();
         final Entry phonePromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT,
                 phoneIcon, getString(R.string.quickcontact_add_phone_number),
-                /* subHeader = */ null, /* text = */ null, getEditContactIntent(),
+                /* subHeader = */ null, /* text = */ null, /* primaryContentDescription = */ null,
+                getEditContactIntent(),
                 /* alternateIcon = */ null, /* alternateIntent = */ null,
                 /* alternateContentDescription = */ null, /* shouldApplyColor = */ true,
                 /* isEditable = */ false, /* EntryContextMenuInfo = */ null,
@@ -1003,7 +1013,8 @@
                 R.drawable.ic_email_24dp).mutate();
         final Entry emailPromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT,
                 emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null,
-                /* text = */ null, getEditContactIntent(), /* alternateIcon = */ null,
+                /* text = */ null, /* primaryContentDescription = */ null,
+                getEditContactIntent(), /* alternateIcon = */ null,
                 /* alternateIntent = */ null, /* alternateContentDescription = */ null,
                 /* shouldApplyColor = */ true, /* isEditable = */ false,
                 /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null,
@@ -1161,11 +1172,12 @@
         Drawable subHeaderIcon = null;
         String text = null;
         Drawable textIcon = null;
+        StringBuilder primaryContentDescription = new StringBuilder();
         Intent intent = null;
         boolean shouldApplyColor = true;
         Drawable alternateIcon = null;
         Intent alternateIntent = null;
-        String alternateContentDescription = null;
+        StringBuilder alternateContentDescription = new StringBuilder();
         final boolean isEditable = false;
         EntryContextMenuInfo entryContextMenuInfo = null;
         Drawable thirdIcon = null;
@@ -1173,6 +1185,7 @@
         String thirdContentDescription = null;
 
         context = context.getApplicationContext();
+        final Resources res = context.getResources();
         DataKind kind = dataItem.getDataKind();
 
         if (dataItem instanceof ImDataItem) {
@@ -1188,19 +1201,19 @@
             if (protocol == Im.PROTOCOL_CUSTOM) {
                 // If the protocol is custom, display the "IM" entry header as well to distinguish
                 // this entry from other ones
-                header = context.getResources().getString(R.string.header_im_entry);
-                subHeader = Im.getProtocolLabel(context.getResources(), protocol,
+                header = res.getString(R.string.header_im_entry);
+                subHeader = Im.getProtocolLabel(res, protocol,
                         im.getCustomProtocol()).toString();
                 text = im.getData();
             } else {
-                header = Im.getProtocolLabel(context.getResources(), protocol,
+                header = Im.getProtocolLabel(res, protocol,
                         im.getCustomProtocol()).toString();
                 subHeader = im.getData();
             }
             entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header);
         } else if (dataItem instanceof OrganizationDataItem) {
             final OrganizationDataItem organization = (OrganizationDataItem) dataItem;
-            header = context.getResources().getString(R.string.header_organization_entry);
+            header = res.getString(R.string.header_organization_entry);
             subHeader = organization.getCompany();
             entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
             text = organization.getTitle();
@@ -1215,18 +1228,18 @@
                 && contactData.getDisplayNameSource() == DisplayNameSources.NICKNAME;
 
             if (!duplicatesTitle) {
-                header = context.getResources().getString(R.string.header_nickname_entry);
+                header = res.getString(R.string.header_nickname_entry);
                 subHeader = nickname.getName();
                 entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
             }
         } else if (dataItem instanceof NoteDataItem) {
             final NoteDataItem note = (NoteDataItem) dataItem;
-            header = context.getResources().getString(R.string.header_note_entry);
+            header = res.getString(R.string.header_note_entry);
             subHeader = note.getNote();
             entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
         } else if (dataItem instanceof WebsiteDataItem) {
             final WebsiteDataItem website = (WebsiteDataItem) dataItem;
-            header = context.getResources().getString(R.string.header_website_entry);
+            header = res.getString(R.string.header_website_entry);
             subHeader = website.getUrl();
             entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
             try {
@@ -1248,9 +1261,9 @@
                 ContentUris.appendId(builder, nextAnniversary.getTime());
                 intent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
             }
-            header = context.getResources().getString(R.string.header_event_entry);
+            header = res.getString(R.string.header_event_entry);
             if (event.hasKindTypeColumn(kind)) {
-                subHeader = Event.getTypeLabel(context.getResources(), event.getKindTypeColumn(kind),
+                subHeader = Event.getTypeLabel(res, event.getKindTypeColumn(kind),
                         event.getLabel()).toString();
             }
             text = DateUtils.formatDate(context, dataString);
@@ -1263,99 +1276,114 @@
                 intent.putExtra(SearchManager.QUERY, dataString);
                 intent.setType(Contacts.CONTENT_TYPE);
             }
-            header = context.getResources().getString(R.string.header_relation_entry);
+            header = res.getString(R.string.header_relation_entry);
             subHeader = relation.getName();
             entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header);
             if (relation.hasKindTypeColumn(kind)) {
-                text = Relation.getTypeLabel(context.getResources(),
+                text = Relation.getTypeLabel(res,
                         relation.getKindTypeColumn(kind),
                         relation.getLabel()).toString();
             }
         } else if (dataItem instanceof PhoneDataItem) {
             final PhoneDataItem phone = (PhoneDataItem) dataItem;
             if (!TextUtils.isEmpty(phone.getNumber())) {
+                primaryContentDescription.append(res.getString(R.string.call_other)).append(" ");
                 header = phone.buildDataString(context, kind);
                 entryContextMenuInfo = new EntryContextMenuInfo(header,
-                        context.getResources().getString(R.string.phoneLabelsGroup));
+                        res.getString(R.string.phoneLabelsGroup));
                 if (phone.hasKindTypeColumn(kind)) {
-                    text = Phone.getTypeLabel(context.getResources(), phone.getKindTypeColumn(kind),
+                    text = Phone.getTypeLabel(res, phone.getKindTypeColumn(kind),
                             phone.getLabel()).toString();
+                    primaryContentDescription.append(text).append(" ");
                 }
-                icon = context.getResources().getDrawable(R.drawable.ic_phone_24dp);
+                primaryContentDescription.append(header);
+                icon = res.getDrawable(R.drawable.ic_phone_24dp);
                 if (PhoneCapabilityTester.isPhone(context)) {
                     intent = CallUtil.getCallIntent(phone.getNumber());
                 }
                 alternateIntent = new Intent(Intent.ACTION_SENDTO,
                         Uri.fromParts(CallUtil.SCHEME_SMSTO, phone.getNumber(), null));
 
-                alternateIcon = context.getResources().getDrawable(R.drawable.ic_message_24dp);
-                alternateContentDescription = context.getResources().getString(R.string.sms_other);
+                alternateIcon = res.getDrawable(R.drawable.ic_message_24dp);
+                alternateContentDescription.append(res.getString(R.string.sms_custom, header));
 
                 // Add video call button if supported
                 if (CallUtil.isVideoEnabled(context)) {
-                    thirdIcon = context.getResources().getDrawable(R.drawable.ic_videocam);
+                    thirdIcon = res.getDrawable(R.drawable.ic_videocam);
                     thirdIntent = CallUtil.getVideoCallIntent(phone.getNumber(),
                             CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY);
                     thirdContentDescription =
-                            context.getResources().getString(R.string.description_video_call);
+                            res.getString(R.string.description_video_call);
                 }
             }
         } else if (dataItem instanceof EmailDataItem) {
             final EmailDataItem email = (EmailDataItem) dataItem;
             final String address = email.getData();
             if (!TextUtils.isEmpty(address)) {
+                primaryContentDescription.append(res.getString(R.string.email_other)).append(" ");
                 final Uri mailUri = Uri.fromParts(CallUtil.SCHEME_MAILTO, address, null);
                 intent = new Intent(Intent.ACTION_SENDTO, mailUri);
                 header = email.getAddress();
                 entryContextMenuInfo = new EntryContextMenuInfo(header,
-                        context.getResources().getString(R.string.emailLabelsGroup));
+                        res.getString(R.string.emailLabelsGroup));
                 if (email.hasKindTypeColumn(kind)) {
-                    text = Email.getTypeLabel(context.getResources(), email.getKindTypeColumn(kind),
+                    text = Email.getTypeLabel(res, email.getKindTypeColumn(kind),
                             email.getLabel()).toString();
+                    primaryContentDescription.append(text).append(" ");
                 }
-                icon = context.getResources().getDrawable(R.drawable.ic_email_24dp);
+                primaryContentDescription.append(header);
+                icon = res.getDrawable(R.drawable.ic_email_24dp);
             }
         } else if (dataItem instanceof StructuredPostalDataItem) {
             StructuredPostalDataItem postal = (StructuredPostalDataItem) dataItem;
             final String postalAddress = postal.getFormattedAddress();
             if (!TextUtils.isEmpty(postalAddress)) {
+                primaryContentDescription.append(res.getString(R.string.map_other)).append(" ");
                 intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
                 header = postal.getFormattedAddress();
                 entryContextMenuInfo = new EntryContextMenuInfo(header,
-                        context.getResources().getString(R.string.postalLabelsGroup));
+                        res.getString(R.string.postalLabelsGroup));
                 if (postal.hasKindTypeColumn(kind)) {
-                    text = StructuredPostal.getTypeLabel(context.getResources(),
+                    text = StructuredPostal.getTypeLabel(res,
                             postal.getKindTypeColumn(kind), postal.getLabel()).toString();
+                    primaryContentDescription.append(text).append(" ");
                 }
+                primaryContentDescription.append(header);
                 alternateIntent =
                         StructuredPostalUtils.getViewPostalAddressDirectionsIntent(postalAddress);
-                alternateIcon = context.getResources().getDrawable(R.drawable.ic_directions_24dp);
-                icon = context.getResources().getDrawable(R.drawable.ic_place_24dp);
+                alternateIcon = res.getDrawable(R.drawable.ic_directions_24dp);
+                alternateContentDescription.append(res.getString(
+                        R.string.content_description_directions)).append(" ").append(header);
+                icon = res.getDrawable(R.drawable.ic_place_24dp);
             }
         } else if (dataItem instanceof SipAddressDataItem) {
             if (PhoneCapabilityTester.isSipPhone(context)) {
                 final SipAddressDataItem sip = (SipAddressDataItem) dataItem;
                 final String address = sip.getSipAddress();
                 if (!TextUtils.isEmpty(address)) {
+                    primaryContentDescription.append(res.getString(R.string.call_other)).append(
+                            " ");
                     final Uri callUri = Uri.fromParts(CallUtil.SCHEME_SIP, address, null);
                     intent = CallUtil.getCallIntent(callUri);
                     header = address;
                     entryContextMenuInfo = new EntryContextMenuInfo(header,
-                            context.getResources().getString(R.string.phoneLabelsGroup));
+                            res.getString(R.string.phoneLabelsGroup));
                     if (sip.hasKindTypeColumn(kind)) {
-                        text = SipAddress.getTypeLabel(context.getResources(),
+                        text = SipAddress.getTypeLabel(res,
                                 sip.getKindTypeColumn(kind), sip.getLabel()).toString();
+                        primaryContentDescription.append(text).append(" ");
                     }
-                    icon = context.getResources().getDrawable(R.drawable.ic_dialer_sip_black_24dp);
+                    primaryContentDescription.append(header);
+                    icon = res.getDrawable(R.drawable.ic_dialer_sip_black_24dp);
                 }
             }
         } else if (dataItem instanceof StructuredNameDataItem) {
             final String givenName = ((StructuredNameDataItem) dataItem).getGivenName();
             if (!TextUtils.isEmpty(givenName)) {
-                aboutCardName.value = context.getResources().getString(R.string.about_card_title) +
+                aboutCardName.value = res.getString(R.string.about_card_title) +
                         " " + givenName;
             } else {
-                aboutCardName.value = context.getResources().getString(R.string.about_card_title);
+                aboutCardName.value = res.getString(R.string.about_card_title);
             }
         } else {
             // Custom DataItem
@@ -1373,17 +1401,17 @@
                     case MIMETYPE_GPLUS_PROFILE:
                         if (INTENT_DATA_GPLUS_PROFILE_ADD_TO_CIRCLE.equals(
                                 intent.getDataString())) {
-                            icon = context.getResources().getDrawable(
+                            icon = res.getDrawable(
                                     R.drawable.ic_add_to_circles_black_24);
                         } else {
-                            icon = context.getResources().getDrawable(R.drawable.ic_google_plus_24dp);
+                            icon = res.getDrawable(R.drawable.ic_google_plus_24dp);
                         }
                         break;
                     case MIMETYPE_HANGOUTS:
                         if (INTENT_DATA_HANGOUTS_VIDEO.equals(intent.getDataString())) {
-                            icon = context.getResources().getDrawable(R.drawable.ic_hangout_video_24dp);
+                            icon = res.getDrawable(R.drawable.ic_hangout_video_24dp);
                         } else {
-                            icon = context.getResources().getDrawable(R.drawable.ic_hangout_24dp);
+                            icon = res.getDrawable(R.drawable.ic_hangout_24dp);
                         }
                         break;
                     default:
@@ -1410,11 +1438,9 @@
             // Do not set the alternate intent is there are no resolves
             if (!PhoneCapabilityTester.isIntentRegistered(context, alternateIntent)) {
                 alternateIntent = null;
-            }
-
-            // Attempt to use package manager to find a suitable content description if needed
-            if (TextUtils.isEmpty(alternateContentDescription)) {
-                alternateContentDescription = getIntentResolveLabel(alternateIntent, context);
+            } else if (TextUtils.isEmpty(alternateContentDescription)) {
+                // Attempt to use package manager to find a suitable content description if needed
+                alternateContentDescription.append(getIntentResolveLabel(alternateIntent, context));
             }
         }
 
@@ -1428,9 +1454,10 @@
         final int dataId = dataItem.getId() > Integer.MAX_VALUE ?
                 -1 : (int) dataItem.getId();
 
-        return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, intent,
-                alternateIcon, alternateIntent, alternateContentDescription, shouldApplyColor,
-                isEditable, entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
+        return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon,
+                primaryContentDescription.toString(), intent, alternateIcon, alternateIntent,
+                alternateContentDescription.toString(), shouldApplyColor, isEditable,
+                entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription);
     }
 
     private List<Entry> dataItemsToEntries(List<DataItem> dataItems,
@@ -1603,6 +1630,7 @@
                     interaction.getBodyIcon(this),
                     interaction.getViewFooter(this),
                     interaction.getFooterIcon(this),
+                    interaction.getContentDescription(this),
                     interaction.getIntent(),
                     /* alternateIcon = */ null,
                     /* alternateIntent = */ null,
@@ -1746,41 +1774,66 @@
 
     private void bindRecentData() {
         final List<ContactInteraction> allInteractions = new ArrayList<>();
-        for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) {
-            allInteractions.addAll(loaderInteractions);
-        }
+        final List<List<Entry>> interactionsWrapper = new ArrayList<>();
 
-        // Sort the interactions by most recent
-        Collections.sort(allInteractions, new Comparator<ContactInteraction>() {
+        mRecentDataTask = new AsyncTask<Void, Void, Void>() {
             @Override
-            public int compare(ContactInteraction a, ContactInteraction b) {
-                return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1;
-            }
-        });
+            protected Void doInBackground(Void... params) {
+                Trace.beginSection("sort recent loader results");
 
-        // Wrap each interaction in its own list so that an icon is displayed for each entry
-        List<List<Entry>> interactionsWrapper = new ArrayList<>();
-        for (Entry contactInteraction : contactInteractionsToEntries(allInteractions)) {
-            List<Entry> entryListWrapper = new ArrayList<>(1);
-            entryListWrapper.add(contactInteraction);
-            interactionsWrapper.add(entryListWrapper);
-        }
-        if (allInteractions.size() > 0) {
-            mRecentCard.initialize(interactionsWrapper,
+                for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) {
+                    allInteractions.addAll(loaderInteractions);
+                }
+
+                // Sort the interactions by most recent
+                Collections.sort(allInteractions, new Comparator<ContactInteraction>() {
+                    @Override
+                    public int compare(ContactInteraction a, ContactInteraction b) {
+                        return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1;
+                    }
+                });
+
+                Trace.endSection();
+                Trace.beginSection("contactInteractionsToEntries");
+
+                // Wrap each interaction in its own list so that an icon is displayed for each entry
+                for (Entry contactInteraction : contactInteractionsToEntries(allInteractions)) {
+                    List<Entry> entryListWrapper = new ArrayList<>(1);
+                    entryListWrapper.add(contactInteraction);
+                    interactionsWrapper.add(entryListWrapper);
+                }
+
+                Trace.endSection();
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Void aVoid) {
+                super.onPostExecute(aVoid);
+                Trace.beginSection("initialize recents card");
+
+                if (allInteractions.size() > 0) {
+                    mRecentCard.initialize(interactionsWrapper,
                     /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN,
                     /* isExpanded = */ mRecentCard.isExpanded(), /* isAlwaysExpanded = */ false,
-                    mExpandingEntryCardViewListener, mScroller);
-            mRecentCard.setVisibility(View.VISIBLE);
-        }
+                            mExpandingEntryCardViewListener, mScroller);
+                    mRecentCard.setVisibility(View.VISIBLE);
+                }
 
-        // About card is initialized along with the contact card, but since it appears after
-        // the recent card in the UI, we hold off until making it visible until the recent card
-        // is also ready to avoid stuttering.
-        if (mAboutCard.shouldShow()) {
-            mAboutCard.setVisibility(View.VISIBLE);
-        } else {
-            mAboutCard.setVisibility(View.GONE);
-        }
+                Trace.endSection();
+
+                // About card is initialized along with the contact card, but since it appears after
+                // the recent card in the UI, we hold off until making it visible until the recent
+                // card is also ready to avoid stuttering.
+                if (mAboutCard.shouldShow()) {
+                    mAboutCard.setVisibility(View.VISIBLE);
+                } else {
+                    mAboutCard.setVisibility(View.GONE);
+                }
+                mRecentDataTask = null;
+            }
+        };
+        mRecentDataTask.execute();
     }
 
     @Override
@@ -1794,6 +1847,9 @@
             // the entire process will be killed.
             mEntriesAndActionsTask.cancel(/* mayInterruptIfRunning = */ false);
         }
+        if (mRecentDataTask != null) {
+            mRecentDataTask.cancel(/* mayInterruptIfRunning = */ false);
+        }
     }
 
     /**
@@ -1812,13 +1868,13 @@
 
     private Intent getEditContactIntent() {
         final Intent intent = new Intent(Intent.ACTION_EDIT, mContactData.getLookupUri());
-        mContactLoader.cacheResult();
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
         return intent;
     }
 
     private void editContact() {
         mHasIntentLaunched = true;
+        mContactLoader.cacheResult();
         startActivityForResult(getEditContactIntent(), REQUEST_CODE_CONTACT_EDITOR_ACTIVITY);
     }
 
@@ -1964,8 +2020,42 @@
                 return true;
             case R.id.menu_edit:
                 if (DirectoryContactUtil.isDirectoryContact(mContactData)) {
-                    DirectoryContactUtil.addToMyContacts(mContactData, this, getFragmentManager(),
-                            mSelectAccountFragmentListener);
+                    // This action is used to launch the contact selector, with the option of
+                    // creating a new contact. Creating a new contact is an INSERT, while selecting
+                    // an exisiting one is an edit. The fields in the edit screen will be
+                    // prepopulated with data.
+
+                    final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+                    intent.setType(Contacts.CONTENT_ITEM_TYPE);
+
+                    // Only pre-fill the name field if the provided display name is an organization
+                    // name or better (e.g. structured name, nickname)
+                    if (mContactData.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) {
+                        intent.putExtra(Intents.Insert.NAME, mContactData.getDisplayName());
+                    }
+                    ArrayList<ContentValues> values = mContactData.getContentValues();
+                    // Last time used and times used are aggregated values from the usage stat
+                    // table. They need to be removed from data values so the SQL table can insert
+                    // properly
+                    for (ContentValues value : values) {
+                        value.remove(Data.LAST_TIME_USED);
+                        value.remove(Data.TIMES_USED);
+                    }
+                    intent.putExtra(Intents.Insert.DATA, values);
+
+                    // If the contact can only export to the same account, add it to the intent.
+                    // Otherwise the ContactEditorFragment will show a dialog for selecting an
+                    // account.
+                    if (mContactData.getDirectoryExportSupport() ==
+                            Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY) {
+                        intent.putExtra(Intents.Insert.ACCOUNT,
+                                new Account(mContactData.getDirectoryAccountName(),
+                                        mContactData.getDirectoryAccountType()));
+                        intent.putExtra(Intents.Insert.DATA_SET,
+                                mContactData.getRawContacts().get(0).getDataSet());
+                    }
+
+                    startActivityForResult(intent, REQUEST_CODE_CONTACT_SELECTION_ACTIVITY);
                 } else if (InvisibleContactUtil.isInvisibleAndAddable(mContactData, this)) {
                     InvisibleContactUtil.addToDefaultGroup(mContactData, this);
                 } else if (isContactEditable()) {
diff --git a/src/com/android/contacts/widget/MultiShrinkScroller.java b/src/com/android/contacts/widget/MultiShrinkScroller.java
index 7965e85..c5492d2 100644
--- a/src/com/android/contacts/widget/MultiShrinkScroller.java
+++ b/src/com/android/contacts/widget/MultiShrinkScroller.java
@@ -315,13 +315,14 @@
             public void run() {
                 if (!mIsTwoPanel) {
                     // We never want the height of the photo view to exceed its width.
-                    mMaximumHeaderHeight = getWidth();
+                    mMaximumHeaderHeight = mPhotoViewContainer.getWidth();
                     mIntermediateHeaderHeight = (int) (mMaximumHeaderHeight
                             * INTERMEDIATE_HEADER_HEIGHT_RATIO);
                 }
                 final boolean isLandscape = getResources().getConfiguration().orientation
                         == Configuration.ORIENTATION_LANDSCAPE;
-                mMaximumPortraitHeaderHeight = isLandscape ? getHeight() : getWidth();
+                mMaximumPortraitHeaderHeight = isLandscape ? getHeight()
+                        : mPhotoViewContainer.getWidth();
                 setHeaderHeight(getMaximumScrollableHeaderHeight());
                 mMaximumHeaderTextSize = mLargeTextView.getHeight();
                 if (mIsTwoPanel) {