Merge "Fix issues with photo selection on Prime."
diff --git a/src/com/android/contacts/ContactPhotoManager.java b/src/com/android/contacts/ContactPhotoManager.java
index 7c54e80..f53766d 100644
--- a/src/com/android/contacts/ContactPhotoManager.java
+++ b/src/com/android/contacts/ContactPhotoManager.java
@@ -177,6 +177,14 @@
     public abstract void refreshCache();
 
     /**
+     * Stores the given bitmap directly in the LRU bitmap cache.
+     * @param photoUri The URI of the photo (for future requests).
+     * @param bitmap The bitmap.
+     * @param photoBytes The bytes that were parsed to create the bitmap.
+     */
+    public abstract void cacheBitmap(Uri photoUri, Bitmap bitmap, byte[] photoBytes);
+
+    /**
      * Initiates a background process that over time will fill up cache with
      * preload photos.
      */
@@ -649,6 +657,14 @@
         mBitmapHolderCache.put(key, holder);
     }
 
+    @Override
+    public void cacheBitmap(Uri photoUri, Bitmap bitmap, byte[] photoBytes) {
+        Request request = Request.createFromUri(photoUri, true, false, DEFAULT_AVATER);
+        BitmapHolder holder = new BitmapHolder(photoBytes);
+        mBitmapHolderCache.put(request.getKey(), holder);
+        mBitmapCache.put(request, bitmap);
+    }
+
     /**
      * Populates an array of photo IDs that need to be loaded.
      */
diff --git a/src/com/android/contacts/activities/PhotoSelectionActivity.java b/src/com/android/contacts/activities/PhotoSelectionActivity.java
index 73a85eb..de129cb 100644
--- a/src/com/android/contacts/activities/PhotoSelectionActivity.java
+++ b/src/com/android/contacts/activities/PhotoSelectionActivity.java
@@ -15,6 +15,7 @@
  */
 package com.android.contacts.activities;
 
+import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.R;
 import com.android.contacts.detail.PhotoSelectionHandler;
@@ -30,6 +31,7 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.view.View;
@@ -58,8 +60,8 @@
 
     private static final String KEY_SUB_ACTIVITY_IN_PROGRESS = "subinprogress";
 
-    /** Intent extra to get the photo bitmap. */
-    public static final String PHOTO_BITMAP = "photo_bitmap";
+    /** Intent extra to get the photo URI. */
+    public static final String PHOTO_URI = "photo_uri";
 
     /** Intent extra to get the entity delta list. */
     public static final String ENTITY_DELTA_LIST = "entity_delta_list";
@@ -80,8 +82,10 @@
     /** Source bounds of the image that was clicked on. */
     private Rect mSourceBounds;
 
-    /** The photo bitmap. */
-    private Bitmap mPhotoBitmap;
+    /**
+     * The photo URI. May be null, in which case the default avatar will be used.
+     */
+    private Uri mPhotoUri;
 
     /** Entity delta list of the contact. */
     private EntityDeltaList mState;
@@ -149,7 +153,7 @@
 
         // Pull data out of the intent.
         final Intent intent = getIntent();
-        mPhotoBitmap = intent.getParcelableExtra(PHOTO_BITMAP);
+        mPhotoUri = intent.getParcelableExtra(PHOTO_URI);
         mState = (EntityDeltaList) intent.getParcelableExtra(ENTITY_DELTA_LIST);
         mIsProfile = intent.getBooleanExtra(IS_PROFILE, false);
         mIsDirectoryContact = intent.getBooleanExtra(IS_DIRECTORY_CONTACT, false);
@@ -193,7 +197,12 @@
     /**
      * Builds a well-formed intent for invoking this activity.
      * @param context The context.
-     * @param photoBitmap The bitmap of the current photo.
+     * @param photoUri The URI of the current photo (may be null, in which case the default
+     *     avatar image will be displayed).
+     * @param photoBitmap The bitmap of the current photo (may be null, in which case the default
+     *     avatar image will be displayed).
+     * @param photoBytes The bytes for the current photo (may be null, in which case the default
+     *     avatar image will be displayed).
      * @param photoBounds The pixel bounds of the current photo.
      * @param delta The entity delta list for the contact.
      * @param isProfile Whether the contact is the user's profile.
@@ -202,11 +211,13 @@
      *     this should be true for phones, and false for tablets).
      * @return An intent that can be used to invoke the photo selection activity.
      */
-    public static Intent buildIntent(Context context, Bitmap photoBitmap, Rect photoBounds,
-            EntityDeltaList delta, boolean isProfile, boolean isDirectoryContact,
-            boolean expandPhotoOnClick) {
+    public static Intent buildIntent(Context context, Uri photoUri, Bitmap photoBitmap,
+            byte[] photoBytes, Rect photoBounds, EntityDeltaList delta, boolean isProfile,
+            boolean isDirectoryContact, boolean expandPhotoOnClick) {
         Intent intent = new Intent(context, PhotoSelectionActivity.class);
-        intent.putExtra(PHOTO_BITMAP, photoBitmap);
+        if (photoUri != null && photoBitmap != null && photoBytes != null) {
+            intent.putExtra(PHOTO_URI, photoUri);
+        }
         intent.setSourceBounds(photoBounds);
         intent.putExtra(ENTITY_DELTA_LIST, (Parcelable) delta);
         intent.putExtra(IS_PROFILE, isProfile);
@@ -233,48 +244,55 @@
     }
 
     private void displayPhoto() {
-        if (mPhotoBitmap != null) {
-            final int[] pos = new int[2];
-            mBackdrop.getLocationOnScreen(pos);
-            LayoutParams layoutParams = new LayoutParams(mSourceBounds.width(),
-                    mSourceBounds.height());
-            mOriginalPos.left = mSourceBounds.left - pos[0];
-            mOriginalPos.top = mSourceBounds.top - pos[1];
-            mOriginalPos.right = mOriginalPos.left + mSourceBounds.width();
-            mOriginalPos.bottom = mOriginalPos.top + mSourceBounds.height();
-            layoutParams.setMargins(mOriginalPos.left, mOriginalPos.top, mOriginalPos.right,
-                    mOriginalPos.bottom);
-            mPhotoStartParams = layoutParams;
-            mPhotoView.setLayoutParams(layoutParams);
-            mPhotoView.requestLayout();
-
-            mPhotoView.setImageBitmap(mPhotoBitmap);
-            mPhotoView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-                @Override
-                public void onLayoutChange(View v, int left, int top, int right, int bottom,
-                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                    if (mAnimationPending) {
-                        mAnimationPending = false;
-                        PropertyValuesHolder pvhLeft =
-                                PropertyValuesHolder.ofInt("left", mOriginalPos.left, left);
-                        PropertyValuesHolder pvhTop =
-                                PropertyValuesHolder.ofInt("top", mOriginalPos.top, top);
-                        PropertyValuesHolder pvhRight =
-                                PropertyValuesHolder.ofInt("right", mOriginalPos.right, right);
-                        PropertyValuesHolder pvhBottom =
-                                PropertyValuesHolder.ofInt("bottom", mOriginalPos.bottom, bottom);
-                        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(mPhotoView,
-                                pvhLeft, pvhTop, pvhRight, pvhBottom).setDuration(
-                                PHOTO_EXPAND_DURATION);
-                        if (mAnimationListener != null) {
-                            anim.addListener(mAnimationListener);
-                        }
-                        anim.start();
-                    }
-                }
-            });
-            attachPhotoHandler();
+        // Load the photo.
+        if (mPhotoUri != null) {
+            // If we have a URI, the bitmap should be cached directly.
+            ContactPhotoManager.getInstance(this).loadPhoto(mPhotoView, mPhotoUri, true, false);
+        } else {
+            // Fall back to avatar image.
+            mPhotoView.setImageResource(ContactPhotoManager.getDefaultAvatarResId(true, false));
         }
+
+        // Animate the photo view into its end location.
+        final int[] pos = new int[2];
+        mBackdrop.getLocationOnScreen(pos);
+        LayoutParams layoutParams = new LayoutParams(mSourceBounds.width(),
+                mSourceBounds.height());
+        mOriginalPos.left = mSourceBounds.left - pos[0];
+        mOriginalPos.top = mSourceBounds.top - pos[1];
+        mOriginalPos.right = mOriginalPos.left + mSourceBounds.width();
+        mOriginalPos.bottom = mOriginalPos.top + mSourceBounds.height();
+        layoutParams.setMargins(mOriginalPos.left, mOriginalPos.top, mOriginalPos.right,
+                mOriginalPos.bottom);
+        mPhotoStartParams = layoutParams;
+        mPhotoView.setLayoutParams(layoutParams);
+        mPhotoView.requestLayout();
+
+        mPhotoView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                if (mAnimationPending) {
+                    mAnimationPending = false;
+                    PropertyValuesHolder pvhLeft =
+                            PropertyValuesHolder.ofInt("left", mOriginalPos.left, left);
+                    PropertyValuesHolder pvhTop =
+                            PropertyValuesHolder.ofInt("top", mOriginalPos.top, top);
+                    PropertyValuesHolder pvhRight =
+                            PropertyValuesHolder.ofInt("right", mOriginalPos.right, right);
+                    PropertyValuesHolder pvhBottom =
+                            PropertyValuesHolder.ofInt("bottom", mOriginalPos.bottom, bottom);
+                    ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(mPhotoView,
+                            pvhLeft, pvhTop, pvhRight, pvhBottom).setDuration(
+                            PHOTO_EXPAND_DURATION);
+                    if (mAnimationListener != null) {
+                        anim.addListener(mAnimationListener);
+                    }
+                    anim.start();
+                }
+            }
+        });
+        attachPhotoHandler();
     }
 
     private LayoutParams getPhotoEndParams() {
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index 588e6ff..912d7fb 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -29,7 +29,6 @@
 import com.android.contacts.util.StreamItemPhotoEntry;
 import com.google.common.annotations.VisibleForTesting;
 
-import android.app.Activity;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
@@ -45,7 +44,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.Parcelable;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.Data;
@@ -228,7 +226,7 @@
 
         // Set up the photo to display a full-screen photo selection activity when clicked.
         OnClickListener clickListener = new PhotoClickListener(context, contactData, bitmap,
-                expandPhotoOnClick);
+                photo, expandPhotoOnClick);
         photoView.setOnClickListener(clickListener);
         return clickListener;
     }
@@ -238,12 +236,14 @@
         private final Context mContext;
         private final Result mContactData;
         private final Bitmap mPhotoBitmap;
+        private final byte[] mPhotoBytes;
         private final boolean mExpandPhotoOnClick;
         public PhotoClickListener(Context context, Result contactData, Bitmap photoBitmap,
-                boolean expandPhotoOnClick) {
+                byte[] photoBytes, boolean expandPhotoOnClick) {
             mContext = context;
             mContactData = contactData;
             mPhotoBitmap = photoBitmap;
+            mPhotoBytes = photoBytes;
             mExpandPhotoOnClick = expandPhotoOnClick;
         }
 
@@ -266,9 +266,16 @@
             rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
             rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
 
+            Uri photoUri = null;
+            if (mContactData.getPhotoUri() != null) {
+                photoUri = Uri.parse(mContactData.getPhotoUri());
+            }
             Intent photoSelectionIntent = PhotoSelectionActivity.buildIntent(mContext,
-                    mPhotoBitmap, rect, delta, mContactData.isUserProfile(),
+                    photoUri, mPhotoBitmap, mPhotoBytes, rect, delta, mContactData.isUserProfile(),
                     mContactData.isDirectoryEntry(), mExpandPhotoOnClick);
+            // Cache the bitmap directly, so the activity can pull it from the photo manager.
+            ContactPhotoManager.getInstance(mContext).cacheBitmap(photoUri, mPhotoBitmap,
+                    mPhotoBytes);
             mContext.startActivity(photoSelectionIntent);
         }
     }
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index f3d7451..a5bea92 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -454,7 +454,7 @@
                 mStaticPhotoContainer.setVisibility(View.VISIBLE);
                 ImageView photoView = (ImageView) mStaticPhotoContainer.findViewById(R.id.photo);
                 OnClickListener listener = ContactDetailDisplayUtils.setPhoto(mContext,
-                        mContactData, photoView, !PhoneCapabilityTester.isUsingTwoPanes(mContext));
+                        mContactData, photoView, false);
                 if (mPhotoTouchOverlay != null) {
                     mPhotoTouchOverlay.setVisibility(View.VISIBLE);
                     mPhotoTouchOverlay.setOnClickListener(listener);
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
index 51c665f..67b7c0c 100644
--- a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
+++ b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
@@ -18,6 +18,7 @@
 
 import com.android.contacts.ContactPhotoManager;
 
+import android.graphics.Bitmap;
 import android.net.Uri;
 import android.widget.ImageView;
 
@@ -56,6 +57,10 @@
     }
 
     @Override
+    public void cacheBitmap(Uri photoUri, Bitmap bitmap, byte[] photoBytes) {
+    }
+
+    @Override
     public void preloadPhotosInBackground() {
     }
 }