Launch viewStreamItemPhotoActivity when photo is tapped...

on stream item list, if the account type supports it.

If the account type doesn't support it, tap of photos launches
viewStreamItemActivity as before.

Bug 5185880

Change-Id: I0b43da3e966ee7737937b2dde7a97e4c440d00dc
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index cbdf148..18a4750 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -20,13 +20,13 @@
 import com.android.contacts.ContactLoader.Result;
 import com.android.contacts.ContactPhotoManager;
 import com.android.contacts.R;
-import com.android.contacts.format.FormatUtils;
 import com.android.contacts.preference.ContactsPreferences;
 import com.android.contacts.util.ContactBadgeUtil;
 import com.android.contacts.util.StreamItemEntry;
 import com.android.contacts.util.StreamItemPhotoEntry;
 import com.google.common.annotations.VisibleForTesting;
 
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Entity;
@@ -37,16 +37,15 @@
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.StreamItems;
 import android.text.Html;
 import android.text.Html.ImageGetter;
-import android.text.Spanned;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -71,6 +70,27 @@
 
     private static final int PHOTO_FADE_IN_ANIMATION_DURATION_MILLIS = 100;
 
+    /**
+     * Tag object used for stream item photos.
+     */
+    public static class StreamPhotoTag {
+        public final StreamItemEntry streamItem;
+        public final StreamItemPhotoEntry streamItemPhoto;
+
+        public StreamPhotoTag(StreamItemEntry streamItem, StreamItemPhotoEntry streamItemPhoto) {
+            this.streamItem = streamItem;
+            this.streamItemPhoto = streamItemPhoto;
+        }
+
+        public Uri getStreamItemPhotoUri() {
+            final Uri.Builder builder = StreamItems.CONTENT_URI.buildUpon();
+            ContentUris.appendId(builder, streamItem.getId());
+            builder.appendPath(StreamItems.StreamItemPhotos.CONTENT_DIRECTORY);
+            ContentUris.appendId(builder, streamItemPhoto.getId());
+            return builder.build();
+        }
+    }
+
     private ContactDetailDisplayUtils() {
         // Disallow explicit creation of this class.
     }
@@ -244,7 +264,8 @@
 
     /** Creates the view that represents a stream item. */
     public static View createStreamItemView(LayoutInflater inflater, Context context,
-            StreamItemEntry streamItem, LinearLayout parent) {
+            StreamItemEntry streamItem, LinearLayout parent,
+            View.OnClickListener photoClickListener) {
         View container = inflater.inflate(R.layout.stream_item_container, parent, false);
         ViewGroup contentTable = (ViewGroup) container.findViewById(R.id.stream_item_content);
 
@@ -261,17 +282,17 @@
 
                 View photoContainer = inflater.inflate(R.layout.stream_item_row_two_images,
                         contentTable, false);
-                loadPhoto(contactPhotoManager, firstPhoto, photoContainer,
-                        R.id.stream_item_first_image);
-                loadPhoto(contactPhotoManager, secondPhoto, photoContainer,
-                        R.id.stream_item_second_image);
+                loadPhoto(contactPhotoManager, streamItem, firstPhoto, photoContainer,
+                        R.id.stream_item_first_image, photoClickListener);
+                loadPhoto(contactPhotoManager, streamItem, secondPhoto, photoContainer,
+                        R.id.stream_item_second_image, photoClickListener);
                 contentTable.addView(photoContainer);
             } else {
                 // Put in a single photo with text on the side.
                 View photoContainer = inflater.inflate(
                         R.layout.stream_item_row_image_and_text, contentTable, false);
-                loadPhoto(contactPhotoManager, firstPhoto, photoContainer,
-                        R.id.stream_item_first_image);
+                loadPhoto(contactPhotoManager, streamItem, firstPhoto, photoContainer,
+                        R.id.stream_item_first_image, photoClickListener);
                 addStreamItemText(context, streamItem,
                         photoContainer.findViewById(R.id.stream_item_second_text));
                 contentTable.addView(photoContainer);
@@ -294,11 +315,22 @@
         return container;
     }
 
-    /** Loads a photo into an image view. The image view is identifiedc by the given id. */
+    /** Loads a photo into an image view. The image view is identified by the given id. */
     private static void loadPhoto(ContactPhotoManager contactPhotoManager,
-            final StreamItemPhotoEntry firstPhoto, View photoContainer, int imageViewId) {
-        ImageView firstImageView = (ImageView) photoContainer.findViewById(imageViewId);
-        contactPhotoManager.loadPhoto(firstImageView, Uri.parse(firstPhoto.getPhotoUri()));
+            final StreamItemEntry streamItem, final StreamItemPhotoEntry streamItemPhoto,
+            View photoContainer, int imageViewId, View.OnClickListener photoClickListener) {
+        ImageView imageView = (ImageView) photoContainer.findViewById(imageViewId);
+        if (photoClickListener != null) {
+            imageView.setOnClickListener(photoClickListener);
+            imageView.setTag(new StreamPhotoTag(streamItem, streamItemPhoto));
+            imageView.setFocusable(true);
+        } else {
+            imageView.setOnClickListener(null);
+            imageView.setTag(null);
+            imageView.setFocusable(false);
+            imageView.setClickable(false); // setOnClickListener makes it clickable, so overwrite it
+        }
+        contactPhotoManager.loadPhoto(imageView, Uri.parse(streamItemPhoto.getPhotoUri()));
     }
 
     @VisibleForTesting
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index 846a957..99766f2 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -19,9 +19,11 @@
 import com.android.contacts.ContactLoader;
 import com.android.contacts.R;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
+import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag;
 import com.android.contacts.model.AccountType;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.util.StreamItemEntry;
+import com.android.contacts.util.StreamItemPhotoEntry;
 
 import android.app.ListFragment;
 import android.content.ContentUris;
@@ -67,7 +69,7 @@
      * <p>
      * It assumes the view has a tag of type {@link StreamItemEntry} associated with it.
      */
-    private View.OnClickListener mStreamItemClickListener = new View.OnClickListener() {
+    private final View.OnClickListener mStreamItemClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             StreamItemEntry streamItemEntry = (StreamItemEntry) view.getTag();
@@ -75,9 +77,7 @@
                 // Ignore if this item does not have a stream item associated with it.
                 return;
             }
-            final AccountTypeManager manager = AccountTypeManager.getInstance(getActivity());
-            final AccountType accountType = manager.getAccountType(
-                    streamItemEntry.getAccountType(), streamItemEntry.getDataSet());
+            final AccountType accountType = getAccountTypeForStreamItemEntry(streamItemEntry);
 
             final Uri uri = ContentUris.withAppendedId(StreamItems.CONTENT_URI,
                     streamItemEntry.getId());
@@ -88,6 +88,28 @@
         }
     };
 
+    private final View.OnClickListener mStreamItemPhotoItemClickListener
+            = new View.OnClickListener() {
+        @Override
+        public void onClick(View view) {
+            StreamPhotoTag tag = (StreamPhotoTag) view.getTag();
+            if (tag == null) {
+                return;
+            }
+            final AccountType accountType = getAccountTypeForStreamItemEntry(tag.streamItem);
+
+            final Intent intent = new Intent(Intent.ACTION_VIEW, tag.getStreamItemPhotoUri());
+            intent.setClassName(accountType.resPackageName,
+                    accountType.getViewStreamItemPhotoActivity());
+            startActivity(intent);
+        }
+    };
+
+    private AccountType getAccountTypeForStreamItemEntry(StreamItemEntry streamItemEntry) {
+        return AccountTypeManager.getInstance(getActivity()).getAccountType(
+                streamItemEntry.getAccountType(), streamItemEntry.getDataSet());
+    }
+
     public ContactDetailUpdatesFragment() {
         // Explicit constructor for inflation
     }
@@ -108,7 +130,8 @@
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        mStreamItemAdapter = new StreamItemAdapter(getActivity(), mStreamItemClickListener);
+        mStreamItemAdapter = new StreamItemAdapter(getActivity(), mStreamItemClickListener,
+                mStreamItemPhotoItemClickListener);
         setListAdapter(mStreamItemAdapter);
         getListView().setOnScrollListener(mVerticalScrollListener);
 
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
index 5128787..9094c5c 100644
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -42,14 +42,17 @@
     private static final int ITEM_VIEW_TYPE_STREAM_ITEM = 2;
 
     private final Context mContext;
-    private final View.OnClickListener mListener;
+    private final View.OnClickListener mItemClickListener;
+    private final View.OnClickListener mPhotoClickListener;
     private final LayoutInflater mInflater;
 
     private List<StreamItemEntry> mStreamItems;
 
-    public StreamItemAdapter(Context context, View.OnClickListener listener) {
+    public StreamItemAdapter(Context context, View.OnClickListener itemClickListener,
+            View.OnClickListener photoClickListener) {
         mContext = context;
-        mListener = listener;
+        mItemClickListener = itemClickListener;
+        mPhotoClickListener = photoClickListener;
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         mStreamItems = Lists.newArrayList();
     }
@@ -83,20 +86,23 @@
         if (position == 1) {
             return mInflater.inflate(R.layout.updates_title, null);
         }
-        StreamItemEntry streamItem = (StreamItemEntry) getItem(position);
-        View view = ContactDetailDisplayUtils.createStreamItemView(
-                mInflater, mContext, streamItem, null);
+        final StreamItemEntry streamItem = (StreamItemEntry) getItem(position);
         final AccountTypeManager manager = AccountTypeManager.getInstance(mContext);
         final AccountType accountType =
                 manager.getAccountType(streamItem.getAccountType(), streamItem.getDataSet());
+        final View view = ContactDetailDisplayUtils.createStreamItemView(
+                mInflater, mContext, streamItem, null,
+                (accountType.getViewStreamItemPhotoActivity() == null) ? null : mPhotoClickListener
+                );
         if (accountType.getViewStreamItemActivity() != null) {
             view.setTag(streamItem);
             view.setFocusable(true);
-            view.setOnClickListener(mListener);
+            view.setOnClickListener(mItemClickListener);
         } else {
             view.setTag(null);
             view.setFocusable(false);
             view.setOnClickListener(null);
+            view.setClickable(false); // setOnClickListener makes it clickable, so overwrite it
         }
         return view;
     }
diff --git a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
index d862d6e..1fee9b6 100644
--- a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
+++ b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
@@ -28,19 +28,22 @@
 // TODO: We should have tests for action, but that requires a mock sync-adapter that specifies
 // an action or doesn't
 
+// TODO Add test for photo click
+
 /**
  * Unit tests for {@link StreamItemAdapter}.
  */
 public class StreamItemAdapterTest extends AndroidTestCase {
     private StreamItemAdapter mAdapter;
     private FakeOnClickListener mListener;
+    private FakeOnClickListener mPhotoListener;
     private View mView;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mListener = new FakeOnClickListener();
-        mAdapter = new StreamItemAdapter(getContext(), mListener);
+        mAdapter = new StreamItemAdapter(getContext(), mListener, mPhotoListener);
     }
 
     @Override