merge in nakasi-factoryrom-release history after reset to jb-dev
diff --git a/res/layout/people_navigation_item.xml b/res/layout/people_navigation_item.xml
new file mode 100644
index 0000000..b7d86d2
--- /dev/null
+++ b/res/layout/people_navigation_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<!-- This is the text view layout that is shown in the spinner for the navigation drop down menu on
+     tablet devices.  The text appearance is governed via two styles:
+     PeopleNavigationDropDownHeaderTextAppearance - text appearance of the item in the header part
+         of navigation drop down list of the action bar.
+     PeopleNavigationDropDownTextAppearance - text appearance of the item in the drop down part of
+         the navigation drop down list of the action bar. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:paddingLeft="18dip"
+    android:paddingRight="18dip"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+/>
diff --git a/res/values-sw580dp-w940dp/styles.xml b/res/values-sw580dp-w940dp/styles.xml
new file mode 100644
index 0000000..07ef912
--- /dev/null
+++ b/res/values-sw580dp-w940dp/styles.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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>
+    <style name="PeopleTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
+        <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
+        <item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
+        <item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
+        <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+        <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
+        <item name="android:textColorPrimary">@color/primary_text_color</item>
+        <item name="android:textColorSecondary">@color/secondary_text_color</item>
+        <item name="android:listViewStyle">@style/ListViewStyle</item>
+        <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
+        <item name="activated_background">@drawable/list_item_activated_background</item>
+        <item name="section_header_background">@drawable/list_title_holo</item>
+        <item name="list_item_divider">?android:attr/listDivider</item>
+        <item name="list_item_padding_top">0dip</item>
+        <item name="list_item_padding_right">24dip</item>
+        <item name="list_item_padding_bottom">0dip</item>
+        <item name="list_item_padding_left">0dip</item>
+        <item name="list_item_gap_between_image_and_text">8dip</item>
+        <item name="list_item_gap_between_label_and_data">5dip</item>
+        <item name="list_item_vertical_divider_margin">5dip</item>
+        <item name="list_item_presence_icon_margin">4dip</item>
+        <item name="list_item_photo_size">64dip</item>
+        <item name="list_item_profile_photo_size">80dip</item>
+        <item name="list_item_prefix_highlight_color">@color/people_app_theme_color</item>
+        <item name="list_item_header_text_indent">8dip</item>
+        <item name="list_item_header_text_size">14sp</item>
+        <item name="list_item_header_text_color">@color/people_app_theme_color</item>
+        <item name="list_item_header_height">32dip</item>
+        <item name="list_item_header_underline_height">1dip</item>
+        <item name="list_item_header_underline_color">@color/people_app_theme_color</item>
+        <item name="list_item_data_width_weight">5</item>
+        <item name="list_item_label_width_weight">3</item>
+        <item name="list_item_contacts_count_text_color">@color/contact_count_text_color</item>
+        <item name="list_item_contacts_count_text_size">12sp</item>
+        <item name="contact_browser_list_padding_left">0dip</item>
+        <item name="contact_browser_list_padding_right">0dip</item>
+        <item name="contact_browser_background">@android:color/transparent</item>
+        <item name="list_item_text_indent">@dimen/contact_browser_list_item_text_indent</item>
+        <!-- Favorites -->
+        <item name="favorites_padding_bottom">0dip</item>
+    </style>
+
+</resources>
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index c387435..7a247ae 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -19,6 +19,7 @@
         <item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
         <item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
         <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+        <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
         <item name="android:listViewStyle">@style/ListViewStyle</item>
@@ -27,7 +28,7 @@
         <item name="section_header_background">@drawable/list_title_holo</item>
         <item name="list_item_divider">?android:attr/listDivider</item>
         <item name="list_item_padding_top">0dip</item>
-        <item name="list_item_padding_right">24dip</item>
+        <item name="list_item_padding_right">12dip</item>
         <item name="list_item_padding_bottom">0dip</item>
         <item name="list_item_padding_left">0dip</item>
         <item name="list_item_gap_between_image_and_text">8dip</item>
diff --git a/res/values-sw680dp/styles.xml b/res/values-sw680dp/styles.xml
index 31de81b..3db3867 100644
--- a/res/values-sw680dp/styles.xml
+++ b/res/values-sw680dp/styles.xml
@@ -19,6 +19,7 @@
         <item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
         <item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
         <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+        <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
         <item name="android:listViewStyle">@style/ListViewStyle</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c375e8..93c130f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -363,7 +363,7 @@
          This is especially valuable for views without textual representation like ImageView.
 
          [CHAR LIMIT=NONE] -->
-    <string name="contactsAllLabel">All</string>
+    <string name="contactsAllLabel">All contacts</string>
 
     <!-- The content description text for the groups tab.
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3be1222..1702585 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -130,6 +130,7 @@
         <item name="android:actionBarItemBackground">@drawable/action_bar_item_background</item>
         <item name="android:actionBarWidgetTheme">@style/ContactsActionBarTheme</item>
         <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
+        <item name="android:actionDropDownStyle">@style/ContactsActionBarDropDownStyle</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
         <item name="android:listViewStyle">@style/ListViewStyle</item>
@@ -174,6 +175,9 @@
         <item name="android:displayOptions"></item>
     </style>
 
+    <style name="ContactsActionBarDropDownStyle" parent="@android:style/Widget.Holo.Light.Spinner">
+    </style>
+
     <style name="ContactsActionBarTheme" parent="@android:style/Theme.Holo">
         <item name="android:textColorHint">#CCCCCC</item>
         <item name="android:textColor">@android:color/black</item>
@@ -343,4 +347,18 @@
         <item name="android:singleLine">true</item>
         <item name="android:textAllCaps">true</item>
     </style>
+
+    <style name="PeopleNavigationDropDownTextAppearance">
+        <item name="android:textColor">#333333</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textAllCaps">false</item>
+    </style>
+
+    <style name="PeopleNavigationDropDownHeaderTextAppearance">
+        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textAllCaps">true</item>
+    </style>
 </resources>
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index 5d188fb..ab2ac41 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -226,10 +226,11 @@
             mIsUserProfile = isUserProfile;
         }
 
-        private Result(Result from) {
+        private Result(Uri requestedUri, Result from) {
+            mRequestedUri = requestedUri;
+
             mStatus = from.mStatus;
             mException = from.mException;
-            mRequestedUri = from.mRequestedUri;
             mLookupUri = from.mLookupUri;
             mUri = from.mUri;
             mDirectoryId = from.mDirectoryId;
@@ -520,6 +521,12 @@
         public boolean isUserProfile() {
             return mIsUserProfile;
         }
+
+        @Override
+        public String toString() {
+            return "{requested=" + mRequestedUri + ",lookupkey=" + mLookupKey +
+                    ",uri=" + mUri + ",status=" + mStatus + "}";
+        }
     }
 
     /**
@@ -730,13 +737,13 @@
                     UriUtils.areEqual(cachedResult.getLookupUri(), mLookupUri)) {
                 // We are using a cached result from earlier. Below, we should make sure
                 // we are not doing any more network or disc accesses
-                result = cachedResult;
+                result = new Result(mRequestedUri, cachedResult);
                 resultIsCached = true;
             } else {
                 result = loadContactEntity(resolver, uriCurrentFormat);
                 resultIsCached = false;
             }
-            if (!result.isNotFound()) {
+            if (result.isLoaded()) {
                 if (result.isDirectoryEntry()) {
                     if (!resultIsCached) {
                         loadDirectoryMetaData(result);
@@ -1345,10 +1352,10 @@
      * contact. If the next load is for a different contact, the cached result will be dropped
      */
     public void cacheResult() {
-        if (mContact == null) {
+        if (mContact == null || !mContact.isLoaded()) {
             sCachedResult = null;
         } else {
-            sCachedResult = new Result(mContact);
+            sCachedResult = mContact;
         }
     }
 }
diff --git a/src/com/android/contacts/ContactsApplication.java b/src/com/android/contacts/ContactsApplication.java
index b23dde1..956ce65 100644
--- a/src/com/android/contacts/ContactsApplication.java
+++ b/src/com/android/contacts/ContactsApplication.java
@@ -26,10 +26,13 @@
 import android.app.FragmentManager;
 import android.app.LoaderManager;
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.os.AsyncTask;
 import android.os.StrictMode;
 import android.preference.PreferenceManager;
+import android.provider.ContactsContract.Contacts;
 import android.util.Log;
 
 public final class ContactsApplication extends Application {
@@ -120,10 +123,6 @@
             Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate start");
         }
 
-        // Priming caches to placate the StrictMode police
-        Context context = getApplicationContext();
-        PreferenceManager.getDefaultSharedPreferences(context);
-        AccountTypeManager.getInstance(context);
         if (ENABLE_FRAGMENT_LOG) FragmentManager.enableDebugLogging(true);
         if (ENABLE_LOADER_LOG) LoaderManager.enableDebugLogging(true);
 
@@ -132,8 +131,30 @@
                     new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
         }
 
+        // Perform the initialization that doesn't have to finish immediately.
+        // We use an async task here just to avoid creating a new thread.
+        (new DelayedInitializer()).execute();
+
         if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
             Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate finish");
         }
     }
+
+    private class DelayedInitializer extends AsyncTask<Void, Void, Void> {
+        @Override
+        protected Void doInBackground(Void... params) {
+            final Context context = ContactsApplication.this;
+
+            // Warm up the preferences, the account type manager and the contacts provider.
+            PreferenceManager.getDefaultSharedPreferences(context);
+            AccountTypeManager.getInstance(context);
+            getContentResolver().getType(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1));
+            return null;
+        }
+
+        public void execute() {
+            executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
+                    (Void[]) null);
+        }
+    }
 }
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index fd06d60..4fc9866 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -26,15 +26,19 @@
 import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.ArrayAdapter;
 import android.widget.SearchView;
 import android.widget.SearchView.OnCloseListener;
 import android.widget.SearchView.OnQueryTextListener;
+import android.widget.TextView;
 
 /**
  * Adapter for the action bar at the top of the Contacts activity.
@@ -74,7 +78,9 @@
     private Listener mListener;
 
     private final ActionBar mActionBar;
-    private final MyTabListener mTabListener = new MyTabListener();
+    private final int mActionBarNavigationMode;
+    private final MyTabListener mTabListener;
+    private final MyNavigationListener mNavigationListener;
 
     private boolean mShowHomeIcon;
     private boolean mShowTabsAsText;
@@ -90,6 +96,34 @@
 
     private int mCurrentTab = TabState.DEFAULT;
 
+    /**
+     * Extension of ArrayAdapter to be used for the action bar navigation drop list.  It is not
+     * possible to change the text appearance of a text item that is in the spinner header or
+     * in the drop down list using a selector xml file.  The only way to differentiate the two
+     * is if the view is gotten via {@link #getView(int, View, ViewGroup)} or
+     * {@link #getDropDownView(int, View, ViewGroup)}.
+     */
+    private class CustomArrayAdapter extends ArrayAdapter<String> {
+
+        public CustomArrayAdapter(Context context, int textResId) {
+            super(context, textResId);
+        }
+
+        public View getView (int position, View convertView, ViewGroup parent) {
+            TextView textView = (TextView) super.getView(position, convertView, parent);
+            textView.setTextAppearance(mContext,
+                    R.style.PeopleNavigationDropDownHeaderTextAppearance);
+            return textView;
+        }
+
+        public View getDropDownView (int position, View convertView, ViewGroup parent) {
+            TextView textView = (TextView) super.getDropDownView(position, convertView, parent);
+            textView.setTextAppearance(mContext,
+                    R.style.PeopleNavigationDropDownTextAppearance);
+            return textView;
+        }
+    }
+
     public ActionBarAdapter(Context context, Listener listener, ActionBar actionBar,
             boolean isUsingTwoPanes) {
         mContext = context;
@@ -101,6 +135,15 @@
 
         // On wide screens, show the tabs as text (instead of icons)
         mShowTabsAsText = isUsingTwoPanes;
+        if (isUsingTwoPanes) {
+            mActionBarNavigationMode = ActionBar.NAVIGATION_MODE_LIST;
+            mTabListener = null;
+            mNavigationListener = new MyNavigationListener();
+        } else {
+            mActionBarNavigationMode = ActionBar.NAVIGATION_MODE_TABS;
+            mTabListener = new MyTabListener();
+            mNavigationListener = null;
+        }
 
         // Set up search view.
         View customSearchView = LayoutInflater.from(mActionBar.getThemedContext()).inflate(
@@ -124,12 +167,67 @@
         mSearchView.setQuery(mQueryString, false);
         mActionBar.setCustomView(customSearchView, layoutParams);
 
-        // Set up tabs
+        // Set up tabs or navigation list
+        switch(mActionBarNavigationMode) {
+            case ActionBar.NAVIGATION_MODE_TABS:
+                setupTabs();
+                break;
+            case ActionBar.NAVIGATION_MODE_LIST:
+                setupNavigationList();
+                break;
+        }
+    }
+
+    private void setupTabs() {
         addTab(TabState.GROUPS, R.drawable.ic_tab_groups, R.string.contactsGroupsLabel);
         addTab(TabState.ALL, R.drawable.ic_tab_all, R.string.contactsAllLabel);
         addTab(TabState.FAVORITES, R.drawable.ic_tab_starred, R.string.contactsFavoritesLabel);
     }
 
+    private void setupNavigationList() {
+        ArrayAdapter<String> navAdapter = new CustomArrayAdapter(mContext,
+                R.layout.people_navigation_item);
+        navAdapter.add(mContext.getString(R.string.contactsAllLabel));
+        navAdapter.add(mContext.getString(R.string.contactsFavoritesLabel));
+        navAdapter.add(mContext.getString(R.string.contactsGroupsLabel));
+        mActionBar.setListNavigationCallbacks(navAdapter, mNavigationListener);
+    }
+
+    /**
+     * Because the navigation list items are in a different order than tab items, this returns
+     * the appropriate tab from the navigation item position.
+     */
+    private int getTabPositionFromNavigationItemPosition(int navItemPos) {
+        switch(navItemPos) {
+            case 0:
+                return TabState.ALL;
+            case 1:
+                return TabState.FAVORITES;
+            case 2:
+                return TabState.GROUPS;
+        }
+        throw new IllegalArgumentException(
+                "Parameter must be between 0 and " + Integer.toString(TabState.COUNT-1)
+                + " inclusive.");
+    }
+
+    /**
+     * This is the inverse of {@link getTabPositionFromNavigationItemPosition}.
+     */
+    private int getNavigationItemPositionFromTabPosition(int tabPos) {
+        switch(tabPos) {
+            case TabState.ALL:
+                return 0;
+            case TabState.FAVORITES:
+                return 1;
+            case TabState.GROUPS:
+                return 2;
+        }
+        throw new IllegalArgumentException(
+                "Parameter must be between 0 and " + Integer.toString(TabState.COUNT-1)
+                + " inclusive.");
+    }
+
     public void initialize(Bundle savedState, ContactsRequest request) {
         if (savedState == null) {
             mSearchMode = request.isSearchMode();
@@ -189,6 +287,17 @@
         }
     }
 
+    private class MyNavigationListener implements ActionBar.OnNavigationListener {
+        public boolean mIgnoreNavigationItemSelected;
+
+        public boolean onNavigationItemSelected(int itemPosition, long itemId) {
+            if (!mIgnoreNavigationItemSelected) {
+                setCurrentTab(getTabPositionFromNavigationItemPosition(itemPosition));
+            }
+            return true;
+        }
+    }
+
     /**
      * Change the current tab, and notify the listener.
      */
@@ -205,9 +314,20 @@
         }
         mCurrentTab = tab;
 
-        if ((mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS)
-                && (mCurrentTab != mActionBar.getSelectedNavigationIndex())) {
-            mActionBar.setSelectedNavigationItem(mCurrentTab);
+        final int actionBarSelectedNavIndex = mActionBar.getSelectedNavigationIndex();
+        switch(mActionBar.getNavigationMode()) {
+            case ActionBar.NAVIGATION_MODE_TABS:
+                if (mCurrentTab != actionBarSelectedNavIndex) {
+                    mActionBar.setSelectedNavigationItem(mCurrentTab);
+                }
+                break;
+            case ActionBar.NAVIGATION_MODE_LIST:
+                if (mCurrentTab != getTabPositionFromNavigationItemPosition(
+                        actionBarSelectedNavIndex)) {
+                    mActionBar.setSelectedNavigationItem(
+                            getNavigationItemPositionFromTabPosition(mCurrentTab));
+                }
+                break;
         }
 
         if (notifyListener && mListener != null) mListener.onSelectedTabChanged();
@@ -306,7 +426,9 @@
                 mListener.onAction(Action.START_SEARCH_MODE);
             }
         } else {
-            if (mActionBar.getNavigationMode() != ActionBar.NAVIGATION_MODE_TABS) {
+            final int currentNavigationMode = mActionBar.getNavigationMode();
+            if (mActionBarNavigationMode == ActionBar.NAVIGATION_MODE_TABS
+                    && currentNavigationMode != ActionBar.NAVIGATION_MODE_TABS) {
                 // setNavigationMode will trigger onTabSelected() with the tab which was previously
                 // selected.
                 // The issue is that when we're first switching to the tab navigation mode after
@@ -319,6 +441,13 @@
                 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
                 mActionBar.setSelectedNavigationItem(mCurrentTab);
                 mTabListener.mIgnoreTabSelected = false;
+            } else if (mActionBarNavigationMode == ActionBar.NAVIGATION_MODE_LIST
+                    && currentNavigationMode != ActionBar.NAVIGATION_MODE_LIST) {
+                mNavigationListener.mIgnoreNavigationItemSelected = true;
+                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+                mActionBar.setSelectedNavigationItem(
+                        getNavigationItemPositionFromTabPosition(mCurrentTab));
+                mNavigationListener.mIgnoreNavigationItemSelected = false;
             }
             mActionBar.setTitle(null);
             // Since we have the {@link SearchView} in a custom action bar, we must manually handle
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 942f0be..5a26ea2 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -83,8 +83,8 @@
             mTempPhotoFile = ContactPhotoUtils.generateTempPhotoFile(this);
             mTempPhotoUri = Uri.fromFile(mTempPhotoFile);
 
-            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
-            intent.setType(Contacts.CONTENT_ITEM_TYPE);
+            Intent intent = new Intent(Intent.ACTION_PICK);
+            intent.setType(Contacts.CONTENT_TYPE);
             startActivityForResult(intent, REQUEST_PICK_CONTACT);
         }
 
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index d8fa158..25c60d6 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -191,6 +191,7 @@
         @Override
         public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
             if (!mLookupUri.equals(data.getRequestedUri())) {
+                Log.e(TAG, "Different URI: requested=" + mLookupUri + "  actual=" + data);
                 return;
             }
 
diff --git a/src/com/android/contacts/list/ShortcutIntentBuilder.java b/src/com/android/contacts/list/ShortcutIntentBuilder.java
index 753ba02..d71a0f5 100644
--- a/src/com/android/contacts/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/list/ShortcutIntentBuilder.java
@@ -137,6 +137,7 @@
      */
     private abstract class LoadingAsyncTask extends AsyncTask<Void, Void, Void> {
         protected Uri mUri;
+        protected String mContentType;
         protected String mDisplayName;
         protected byte[] mBitmapData;
         protected long mPhotoId;
@@ -147,6 +148,7 @@
 
         @Override
         protected Void doInBackground(Void... params) {
+            mContentType = mContext.getContentResolver().getType(mUri);
             loadData();
             loadPhoto();
             return null;
@@ -196,7 +198,7 @@
         }
         @Override
         protected void onPostExecute(Void result) {
-            createContactShortcutIntent(mUri, mDisplayName, mBitmapData);
+            createContactShortcutIntent(mUri, mContentType, mDisplayName, mBitmapData);
         }
     }
 
@@ -248,7 +250,7 @@
         return bitmap;
     }
 
-    private void createContactShortcutIntent(Uri contactUri, String displayName,
+    private void createContactShortcutIntent(Uri contactUri, String contentType, String displayName,
             byte[] bitmapData) {
         Bitmap bitmap = getPhotoBitmap(bitmapData);
 
@@ -263,7 +265,7 @@
         // Tell the launcher to not do its animation, because we are doing our own
         shortcutIntent.putExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true);
 
-        shortcutIntent.setData(contactUri);
+        shortcutIntent.setDataAndType(contactUri, contentType);
         shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_MODE,
                 ContactsContract.QuickContact.MODE_LARGE);
         shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_EXCLUDE_MIMES,
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 5fe34e0..eb5fb23 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -21,6 +21,7 @@
 import com.android.contacts.R;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.DataKind;
+import com.android.contacts.util.Constants;
 import com.android.contacts.util.DataStatus;
 import com.android.contacts.util.ImageViewDrawableSetter;
 import com.android.contacts.util.SchedulingUtils;
@@ -494,6 +495,9 @@
             bindData(data);
 
             if (TRACE_LAUNCH) android.os.Debug.stopMethodTracing();
+            if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
+                Log.d(Constants.PERFORMANCE_TAG, "QuickContact shown");
+            }
 
             // Data bound and ready, pull curtain to show. Put this on the Handler to ensure
             // that the layout passes are completed