Merge "Make tests more resiliant to changes."
diff --git a/res/layout/contact_tile_frequent.xml b/res/layout/contact_tile_frequent.xml
index 14cb04e..2e79ba6 100644
--- a/res/layout/contact_tile_frequent.xml
+++ b/res/layout/contact_tile_frequent.xml
@@ -17,7 +17,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     class="com.android.contacts.list.ContactTileView"
     android:focusable="true"
-    android:background="@drawable/list_selector"
+    android:background="@null"
     android:paddingRight="16dip"
     android:paddingLeft="16dip" >
 
@@ -32,32 +32,46 @@
             android:scaleType="centerCrop"
             android:layout_alignParentRight="true" />
 
-        <TextView
-            android:id="@+id/contact_tile_name"
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:layout_toLeftOf="@id/contact_tile_quick" />
+            android:layout_height="64dip"
+            android:orientation="vertical"
+            android:layout_alignParentBottom="true"
+            android:gravity="center_vertical"
+            android:paddingRight="80dip"
+            android:paddingLeft="8dip">
 
-        <ImageView
-            android:id="@+id/contact_tile_presence"
-            android:layout_width="16dip"
-            android:layout_height="16dip"
-            android:layout_below="@id/contact_tile_name"
-            android:layout_alignParentLeft="true" />
+            <TextView
+                android:id="@+id/contact_tile_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="@color/primary_text_color"
+                android:textSize="18sp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:fadingEdgeLength="3dip"
+                android:ellipsize="marquee" />
 
-        <TextView
-            android:id="@+id/contact_tile_status"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textSize="14sp"
-            android:ellipsize="end"
-            android:singleLine="true"
-            android:textColor="#cccccc"
-            android:layout_toRightOf="@id/contact_tile_presence"
-            android:layout_below="@id/contact_tile_name" />
+            <TextView
+                android:id="@+id/contact_tile_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textColor="?android:attr/textColorSecondary"
+                android:singleLine="true"
+                android:drawablePadding="4dip"
+                android:fadingEdge="horizontal"
+                android:fadingEdgeLength="3dip"
+                android:ellipsize="marquee" />
+
+        </LinearLayout>
+
+        <View
+            android:id="@+id/contact_tile_horizontal_divider"
+            android:layout_width="match_parent"
+            android:layout_height="1px"
+            android:background="?android:attr/listDivider"
+            android:layout_below="@id/contact_tile_quick" />
 
     </RelativeLayout>
 
diff --git a/res/layout/contact_tile_frequent_phone.xml b/res/layout/contact_tile_frequent_phone.xml
index 50c1fc2..563dea0 100644
--- a/res/layout/contact_tile_frequent_phone.xml
+++ b/res/layout/contact_tile_frequent_phone.xml
@@ -17,7 +17,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     class="com.android.contacts.list.ContactTileView"
     android:focusable="true"
-    android:background="@drawable/list_selector"
+    android:background="@null"
     android:paddingRight="16dip"
     android:paddingLeft="16dip" >
 
@@ -36,22 +36,24 @@
             android:id="@+id/contact_tile_name"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:singleLine="true"
-            android:ellipsize="end"
             android:layout_marginLeft="8dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:layout_marginTop="8dip"
-            android:layout_toRightOf="@id/contact_tile_quick" />
+            android:layout_toRightOf="@id/contact_tile_quick"
+            android:singleLine="true"
+            android:fadingEdge="horizontal"
+            android:fadingEdgeLength="3dip"
+            android:ellipsize="marquee" />
 
         <TextView
             android:id="@+id/contact_tile_phone_number"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textSize="14sp"
-            android:ellipsize="end"
-            android:singleLine="true"
             android:textColor="@color/dialtacts_secondary_text_color"
             android:layout_marginLeft="8dip"
+            android:singleLine="true"
+            android:maxLength="18"
             android:layout_toRightOf="@id/contact_tile_quick"
             android:layout_below="@id/contact_tile_name" />
 
@@ -65,23 +67,16 @@
             android:textAllCaps="true"
             android:textColor="@color/dialtacts_secondary_text_color"
             android:layout_marginLeft="12dip"
+            android:maxLength="8"
             android:layout_alignParentRight="true"
             android:layout_alignTop="@id/contact_tile_phone_number" />
 
         <View
             android:id="@+id/contact_tile_horizontal_divider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
+            android:layout_height="1px"
             android:background="?android:attr/listDivider"
-            android:layout_alignParentBottom="true" />
-
-        <View
-            android:id="@+id/contact_tile_horizontal_picture_divider"
-            android:layout_width="64dip"
-            android:layout_height="1dip"
-            android:background="@android:color/black"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentLeft="true" />
+            android:layout_below="@id/contact_tile_quick" />
 
     </RelativeLayout>
 
diff --git a/res/layout/contact_tile_starred.xml b/res/layout/contact_tile_starred.xml
index 3b74946..5fdfe65 100644
--- a/res/layout/contact_tile_starred.xml
+++ b/res/layout/contact_tile_starred.xml
@@ -15,10 +15,13 @@
 -->
 <view
     xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.contacts.list.ContactTileStarredView"
-    style="@style/ContactTileStarred" >
+    android:background="@null"
+    android:paddingBottom="1dip"
+    android:paddingRight="1dip"
+    class="com.android.contacts.list.ContactTileStarredView" >
 
     <RelativeLayout
+        android:id="@+id/contact_tile_layout"
         android:layout_width="match_parent"
         android:layout_height="match_parent" >
 
@@ -28,40 +31,42 @@
             android:layout_height="match_parent"
             android:scaleType="centerCrop" />
 
-        <View
-            android:id="@+id/contact_tile_background"
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="@dimen/contact_tile_shadowbox_height"
+            android:orientation="vertical"
+            android:background="@color/contact_tile_shadow_box_color"
             android:layout_alignParentBottom="true"
-            style="@style/ContactTileStarredShadowBox" />
+            android:gravity="center_vertical"
+            android:paddingRight="8dip"
+            android:paddingLeft="8dip">
 
-        <ImageView
-            android:id="@+id/contact_tile_presence"
-            android:layout_width="16dip"
-            android:layout_height="16dip"
-            android:layout_alignParentBottom="true"
-            android:layout_marginLeft="8dip"
-            android:layout_marginBottom="10dip" />
+            <TextView
+                android:id="@+id/contact_tile_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="@android:color/white"
+                android:textSize="16sp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:fadingEdgeLength="3dip"
+                android:ellipsize="marquee" />
 
-        <TextView
-            android:id="@+id/contact_tile_name"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignLeft="@id/contact_tile_presence"
-            android:layout_above="@id/contact_tile_presence"
-            android:textColor="@android:color/white"
-            stlye="@style/ContactTileStarredName" />
+            <TextView
+                android:id="@+id/contact_tile_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textColor="@color/people_contact_tile_status_color"
+                android:singleLine="true"
+                android:drawablePadding="4dip"
+                android:fadingEdge="horizontal"
+                android:fadingEdgeLength="3dip"
+                android:ellipsize="marquee" />
 
-        <TextView
-            android:id="@+id/contact_tile_status"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/contact_tile_presence"
-            android:layout_below="@id/contact_tile_name"
-            android:layout_marginLeft="4dip"
-            style="@style/ContactTileStatusText" />
+        </LinearLayout>
 
-       <ImageButton
+       <View
             android:id="@+id/contact_tile_push_state"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
diff --git a/res/layout/contact_tile_starred_quick_contact.xml b/res/layout/contact_tile_starred_quick_contact.xml
index 0fb580e..9bb4abe 100644
--- a/res/layout/contact_tile_starred_quick_contact.xml
+++ b/res/layout/contact_tile_starred_quick_contact.xml
@@ -15,51 +15,61 @@
 -->
 <view
     xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.contacts.list.ContactTileStarredView"
-    style="@style/ContactTileStarred" >
+    android:paddingBottom="1dip"
+    android:paddingRight="1dip"
+    android:background="@null"
+    class="com.android.contacts.list.ContactTileStarredView" >
 
     <RelativeLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent" >
 
-        <QuickContactBadge
-            android:id="@+id/contact_tile_quick"
+        <ImageView
+            android:id="@+id/contact_tile_image"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:scaleType="centerCrop" />
 
-        <View
-            android:id="@+id/contact_tile_background"
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="@dimen/contact_tile_shadowbox_height"
+            android:orientation="vertical"
+            android:background="@color/contact_tile_shadow_box_color"
             android:layout_alignParentBottom="true"
-            style="@style/ContactTileStarredShadowBox" />
+            android:gravity="center_vertical"
+            android:paddingRight="8dip"
+            android:paddingLeft="8dip">
 
-        <ImageView
-            android:id="@+id/contact_tile_presence"
-            android:layout_width="16dip"
-            android:layout_height="16dip"
-            android:layout_alignParentBottom="true"
-            android:layout_marginLeft="8dip"
-            android:layout_marginBottom="10dip" />
+            <TextView
+                android:id="@+id/contact_tile_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="@android:color/white"
+                android:textSize="16sp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:fadingEdgeLength="3dip"
+                android:ellipsize="marquee" />
 
-        <TextView
-            android:id="@+id/contact_tile_name"
+            <TextView
+                android:id="@+id/contact_tile_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textColor="@color/people_contact_tile_status_color"
+                android:singleLine="true"
+                android:drawablePadding="4dip"
+                android:fadingEdge="horizontal"
+                android:fadingEdgeLength="3dip"
+                android:ellipsize="marquee" />
+
+        </LinearLayout>
+
+        <QuickContactBadge
+            android:id="@+id/contact_tile_quick"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignLeft="@id/contact_tile_presence"
-            android:layout_above="@id/contact_tile_presence"
-            android:textColor="@android:color/white"
-            stlye="@style/ContactTileStarredName" />
-
-        <TextView
-            android:id="@+id/contact_tile_status"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/contact_tile_presence"
-            android:layout_below="@id/contact_tile_name"
-            android:layout_marginLeft="4dip"
-            style="@style/ContactTileStatusText" />
+            android:layout_height="match_parent"
+            android:background="@null" />
 
     </RelativeLayout>
 
diff --git a/res/layout/contact_tile_starred_secondary_target.xml b/res/layout/contact_tile_starred_secondary_target.xml
index 3558166..e72575e 100644
--- a/res/layout/contact_tile_starred_secondary_target.xml
+++ b/res/layout/contact_tile_starred_secondary_target.xml
@@ -15,8 +15,10 @@
 -->
 <view
     xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.contacts.list.ContactTileSecondaryTargetView"
-    style="@style/ContactTileStarred" >
+    android:background="@null"
+    android:paddingBottom="1dip"
+    android:paddingRight="1dip"
+    class="com.android.contacts.list.ContactTileSecondaryTargetView" >
 
     <RelativeLayout
         android:layout_width="match_parent"
@@ -28,49 +30,24 @@
             android:layout_height="match_parent"
             android:scaleType="centerCrop" />
 
-        <View
-            android:id="@+id/contact_tile_background"
+        <TextView
+            android:id="@+id/contact_tile_name"
             android:layout_width="match_parent"
             android:layout_height="@dimen/contact_tile_shadowbox_height"
+            android:background="@color/contact_tile_shadow_box_color"
+            android:gravity="center_vertical"
+            android:textColor="@android:color/white"
+            android:singleLine="true"
+            android:textSize="16sp"
+            android:fadingEdge="horizontal"
+            android:fadingEdgeLength="3dip"
+            android:ellipsize="marquee"
             android:layout_alignParentBottom="true"
-            android:layout_alignParentLeft="true"
-            style="@style/ContactTileStarredShadowBox" />
-
-        <FrameLayout
-            android:id="@+id/contact_tile_info_layout"
-            android:layout_height="@dimen/contact_tile_shadowbox_height"
-            android:layout_width="wrap_content"
-            android:orientation="horizontal"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentLeft="true"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="45dip">
-
-            <TextView
-                android:id="@+id/contact_tile_name"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:textColor="@android:color/white"
-                android:singleLine="true"
-                android:textSize="16sp"
-                android:fadingEdge="horizontal"
-                android:fadingEdgeLength="3dip"
-                android:ellipsize="marquee" />
-
-        </FrameLayout>
+            android:paddingLeft="8dip"
+            android:paddingRight="47dip"
+            android:drawableRight="@drawable/ic_divider_dashed_holo_dark" />
 
         <View
-            android:id="@+id/secondary_vertical_divider"
-            android:layout_width="1dip"
-            android:layout_height="32dip"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentRight="true"
-            android:layout_marginRight="44dip"
-            android:layout_marginBottom="8dip"
-            android:background="@drawable/ic_divider_dashed_holo_dark" />
-
-        <ImageButton
             android:id="@+id/contact_tile_push_state"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -82,25 +59,11 @@
             android:background="?android:attr/selectableItemBackground"
             android:layout_height="@dimen/contact_tile_shadowbox_height"
             android:layout_width="48dip"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentRight="true"
             android:paddingRight="8dip"
-            android:paddingLeft="8dip" />
-
-        <View
-            android:id="@+id/contact_tile_vertical_divider"
-            android:layout_height="match_parent"
-            android:layout_width="2dip"
-            android:background="@color/phone_contact_tile_divider_color"
+            android:paddingLeft="8dip"
+            android:layout_alignParentBottom="true"
             android:layout_alignParentRight="true" />
 
-        <View
-            android:id="@+id/contact_tile_horizontal_divider"
-            android:layout_width="match_parent"
-            android:layout_height="2dip"
-            android:background="@color/phone_contact_tile_divider_color"
-            android:layout_alignParentBottom="true" />
-
     </RelativeLayout>
 
 </view>
diff --git a/res/layout/list_separator.xml b/res/layout/list_separator.xml
index 7d57ef7..39de1da 100644
--- a/res/layout/list_separator.xml
+++ b/res/layout/list_separator.xml
@@ -23,22 +23,22 @@
     android:paddingLeft="16dip"
     android:paddingRight="16dip">
 
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingTop="8dip"
-            android:paddingLeft="8dip"
-            android:textStyle="bold"
-            android:textAllCaps="true"
-            android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="@color/people_app_theme_color"
-            android:gravity="left|center_vertical"
-            android:id="@+id/header_text" />
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingTop="8dip"
+        android:paddingLeft="8dip"
+        android:textStyle="bold"
+        android:textAllCaps="true"
+        android:singleLine="true"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textColor="@color/people_app_theme_color"
+        android:gravity="left|center_vertical"
+        android:id="@+id/header_text" />
 
-        <View
-            android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:background="@color/people_app_theme_color" />
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dip"
+        android:background="@color/people_app_theme_color" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 1e47948..64d7dfb 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -95,7 +95,10 @@
     <!-- Color of the text for buttons in the action bar  -->
     <color name="action_bar_button_text_color">#FFFFFF</color>
 
-    <!-- Color of the vertical and horizontal dividers for starred contacts in the Phone app -->
-    <color name="phone_contact_tile_divider_color">#D8000000</color>
+    <!--  Color of the status message for starred contacts in the People app -->
+    <color name="people_contact_tile_status_color">#CCCCCC</color>
+
+    <!--  Color of the semi-transparent shadow box on contact tiles -->
+    <color name="contact_tile_shadow_box_color">#7F000000</color>
 
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 81b962f..2f74c32 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -255,4 +255,7 @@
     <!-- Height for directory headers in contact lists -->
     <dimen name="directory_header_height">24dip</dimen>
 
+    <!--  Vertical and horizontal padding in between contact tiles -->
+    <dimen name="contact_tile_divider_padding">2dip</dimen>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 84c3d15..677ac10 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -270,25 +270,14 @@
         <item name="android:soundEffectsEnabled">false</item>
     </style>
 
-    <style name="ContactTileStarred">
-        <item name="android:focusable">true</item>
+    <style name="FavoritesFragmentStyle">
+        <item name="android:layout_width">0dip</item>
+        <item name="android:layout_weight">1</item>
     </style>
 
-    <style name="ContactTileStarredName">
-        <item name="android:singleLine">true</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:textSize">16sp</item>
-    </style>
-
-    <style name="ContactTileStatusText">
-        <item name="android:singleLine">true</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
-        <item name="android:textColor">#777777</item>
-    </style>
-
-    <style name="ContactTileStarredShadowBox">
-        <item name="android:background">#7F000000</item>
+    <style name="FrequentFragmentStyle">
+        <item name="android:layout_width">0dip</item>
+        <item name="android:layout_weight">1</item>
     </style>
 
     <style name="DialtactsActionBarStyle" parent="android:Widget.Holo.ActionBar">
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index ceaa246..b49a357 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -1117,7 +1117,7 @@
             final ContentValues entityValues = entity.getEntityValues();
             final String type = entityValues.getAsString(RawContacts.ACCOUNT_TYPE);
             final String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
-            final AccountType accountType = AccountTypeManager.getInstance(context ).getAccountType(
+            final AccountType accountType = AccountTypeManager.getInstance(context).getAccountType(
                     type, dataSet);
             final String serviceName = accountType.getViewContactNotifyServiceClassName();
             final String resPackageName = accountType.resPackageName;
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 3bb330f..78c4b18 100644
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -53,8 +53,8 @@
 
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * A service responsible for saving changes to the content provider.
@@ -133,7 +133,8 @@
         public void onServiceCompleted(Intent callbackIntent);
     }
 
-    private static final LinkedList<Listener> sListeners = new LinkedList<Listener>();
+    private static final CopyOnWriteArrayList<Listener> sListeners =
+            new CopyOnWriteArrayList<Listener>();
 
     private Handler mMainHandler;
 
@@ -148,15 +149,11 @@
             throw new ClassCastException("Only activities can be registered to"
                     + " receive callback from " + ContactSaveService.class.getName());
         }
-        synchronized (sListeners) {
-            sListeners.addFirst(listener);
-        }
+        sListeners.add(0, listener);
     }
 
     public static void unregisterListener(Listener listener) {
-        synchronized (sListeners) {
-            sListeners.remove(listener);
-        }
+        sListeners.remove(listener);
     }
 
     @Override
@@ -975,13 +972,11 @@
         // TODO: this assumes that if there are multiple instances of the same
         // activity registered, the last one registered is the one waiting for
         // the callback. Validity of this assumption needs to be verified.
-        synchronized (sListeners) {
-            for (Listener listener : sListeners) {
-                if (callbackIntent.getComponent().equals(
-                        ((Activity) listener).getIntent().getComponent())) {
-                    listener.onServiceCompleted(callbackIntent);
-                    return;
-                }
+        for (Listener listener : sListeners) {
+            if (callbackIntent.getComponent().equals(
+                    ((Activity) listener).getIntent().getComponent())) {
+                listener.onServiceCompleted(callbackIntent);
+                return;
             }
         }
     }
diff --git a/src/com/android/contacts/GroupListLoader.java b/src/com/android/contacts/GroupListLoader.java
index b567ba8..2589c9b 100644
--- a/src/com/android/contacts/GroupListLoader.java
+++ b/src/com/android/contacts/GroupListLoader.java
@@ -34,8 +34,6 @@
         Groups.DATA_SET,
         Groups._ID,
         Groups.TITLE,
-        Groups.ACTION,
-        Groups.ACTION_URI,
         Groups.SUMMARY_COUNT,
     };
 
@@ -44,9 +42,7 @@
     public final static int DATA_SET = 2;
     public final static int GROUP_ID = 3;
     public final static int TITLE = 4;
-    public final static int ACTION = 5;
-    public final static int ACTION_URI = 6;
-    public final static int MEMBER_COUNT = 7;
+    public final static int MEMBER_COUNT = 5;
 
     private static final Uri GROUP_LIST_URI = Groups.CONTENT_SUMMARY_URI;
 
diff --git a/src/com/android/contacts/GroupMetaDataLoader.java b/src/com/android/contacts/GroupMetaDataLoader.java
index 2f3468b..8344041 100644
--- a/src/com/android/contacts/GroupMetaDataLoader.java
+++ b/src/com/android/contacts/GroupMetaDataLoader.java
@@ -36,8 +36,6 @@
         Groups.FAVORITES,
         Groups.GROUP_IS_READ_ONLY,
         Groups.DELETED,
-        Groups.ACTION,
-        Groups.ACTION_URI,
     };
 
     public final static int ACCOUNT_NAME = 0;
@@ -49,8 +47,6 @@
     public final static int FAVORITES = 6;
     public final static int IS_READ_ONLY = 7;
     public final static int DELETED = 8;
-    public final static int ACTION = 9;
-    public final static int ACTION_URI = 10;
 
     public GroupMetaDataLoader(Context context, Uri groupUri) {
         super(context, ensureIsGroupUri(groupUri), COLUMNS, Groups.ACCOUNT_TYPE + " NOT NULL AND "
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index e970fcc..e79bdce 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -107,7 +107,8 @@
             mPhoneNumberHelper.getDisplayNumber(details.number, details.formattedNumber);
         if (TextUtils.isEmpty(details.name)) {
             nameText = displayNumber;
-            if (TextUtils.isEmpty(details.geocode)) {
+            if (TextUtils.isEmpty(details.geocode)
+                    || mPhoneNumberHelper.isVoicemailNumber(details.number)) {
                 numberText = mResources.getString(R.string.call_log_empty_gecode);
             } else {
                 numberText = details.geocode;
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 13ce317..cfca831 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -552,6 +552,7 @@
                 Log.e(TAG, "DialpadFragment isn't ready yet when the tab is already selected.");
             }
         }
+        invalidateOptionsMenu();
     }
 
     /** Returns true if the given intent contains a phone number to populate the dialer with */
@@ -753,7 +754,7 @@
 
     private void hideInputMethod(View view) {
         InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
-        if (imm != null) {
+        if (imm != null && view != null) {
             imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
         }
     }
diff --git a/src/com/android/contacts/activities/GroupDetailActivity.java b/src/com/android/contacts/activities/GroupDetailActivity.java
index b66d8b8..47e02a7 100644
--- a/src/com/android/contacts/activities/GroupDetailActivity.java
+++ b/src/com/android/contacts/activities/GroupDetailActivity.java
@@ -20,11 +20,15 @@
 import com.android.contacts.R;
 import com.android.contacts.group.GroupDetailDisplayUtils;
 import com.android.contacts.group.GroupDetailFragment;
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountTypeManager;
 
 import android.app.ActionBar;
+import android.content.ContentUris;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.ContactsContract.Groups;
 import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -40,8 +44,8 @@
 
     private String mAccountTypeString;
     private String mDataSet;
-    private String mGroupSourceAction;
-    private String mGroupSourceUri;
+
+    private GroupDetailFragment mFragment;
 
     @Override
     public void onCreate(Bundle savedState) {
@@ -55,12 +59,12 @@
         mShowGroupSourceInActionBar = getResources().getBoolean(
                 R.bool.config_show_group_action_in_action_bar);
 
-        GroupDetailFragment fragment = (GroupDetailFragment) getFragmentManager().findFragmentById(
+        mFragment = (GroupDetailFragment) getFragmentManager().findFragmentById(
                 R.id.group_detail_fragment);
-        fragment.setListener(mFragmentListener);
-        fragment.setShowGroupSourceInActionBar(mShowGroupSourceInActionBar);
-        fragment.loadGroup(getIntent().getData());
-        fragment.closeActivityAfterDelete(true);
+        mFragment.setListener(mFragmentListener);
+        mFragment.setShowGroupSourceInActionBar(mShowGroupSourceInActionBar);
+        mFragment.loadGroup(getIntent().getData());
+        mFragment.closeActivityAfterDelete(true);
 
         // We want the UP affordance but no app icon.
         ActionBar actionBar = getActionBar();
@@ -85,12 +89,9 @@
         }
 
         @Override
-        public void onGroupSourceUpdated(String accountTypeString, String dataSet,
-                String groupSourceAction, String groupSourceActionUri) {
+        public void onAccountTypeUpdated(String accountTypeString, String dataSet) {
             mAccountTypeString = accountTypeString;
             mDataSet = dataSet;
-            mGroupSourceAction = groupSourceAction;
-            mGroupSourceUri = groupSourceActionUri;
             invalidateOptionsMenu();
         }
 
@@ -128,8 +129,11 @@
         if (groupSourceMenuItem == null) {
             return false;
         }
-        if (TextUtils.isEmpty(mAccountTypeString) || TextUtils.isEmpty(mGroupSourceAction) ||
-                TextUtils.isEmpty(mGroupSourceUri)) {
+        final AccountTypeManager manager = AccountTypeManager.getInstance(this);
+        final AccountType accountType =
+                manager.getAccountType(mAccountTypeString, mDataSet);
+        if (TextUtils.isEmpty(mAccountTypeString)
+                || TextUtils.isEmpty(accountType.getViewGroupActivity())) {
             groupSourceMenuItem.setVisible(false);
             return false;
         }
@@ -139,7 +143,11 @@
         groupSourceView.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                startActivity(new Intent(mGroupSourceAction, Uri.parse(mGroupSourceUri)));
+                final Uri uri = ContentUris.withAppendedId(Groups.CONTENT_URI,
+                        mFragment.getGroupId());
+                final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+                intent.setClassName(accountType.resPackageName, accountType.getViewGroupActivity());
+                startActivity(intent);
             }
         });
         groupSourceMenuItem.setActionView(groupSourceView);
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index cab8afd..1da1c97 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -23,7 +23,6 @@
 import com.android.contacts.activities.ActionBarAdapter.TabState;
 import com.android.contacts.detail.ContactDetailFragment;
 import com.android.contacts.detail.ContactDetailLayoutController;
-import com.android.contacts.detail.ContactDetailTabCarousel;
 import com.android.contacts.detail.ContactDetailUpdatesFragment;
 import com.android.contacts.detail.ContactLoaderFragment;
 import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
@@ -39,6 +38,7 @@
 import com.android.contacts.list.ContactListFilter;
 import com.android.contacts.list.ContactListFilterController;
 import com.android.contacts.list.ContactTileAdapter.DisplayType;
+import com.android.contacts.list.ContactTileListFragment;
 import com.android.contacts.list.ContactsIntentResolver;
 import com.android.contacts.list.ContactsRequest;
 import com.android.contacts.list.ContactsUnavailableFragment;
@@ -48,7 +48,6 @@
 import com.android.contacts.list.OnContactsUnavailableActionListener;
 import com.android.contacts.list.ProviderStatusLoader;
 import com.android.contacts.list.ProviderStatusLoader.ProviderStatusListener;
-import com.android.contacts.list.ContactTileListFragment;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferenceActivity;
@@ -1160,8 +1159,7 @@
         }
 
         @Override
-        public void onGroupSourceUpdated(String accountTypeString, String dataSet,
-                String groupSourceAction, String groupSourceUri) {
+        public void onAccountTypeUpdated(String accountTypeString, String dataSet) {
             // Nothing needs to be done here because the group source will be displayed in the
             // detail fragment
         }
diff --git a/src/com/android/contacts/calllog/CallLogNotificationsService.java b/src/com/android/contacts/calllog/CallLogNotificationsService.java
index 6dd24aa..be540ad 100644
--- a/src/com/android/contacts/calllog/CallLogNotificationsService.java
+++ b/src/com/android/contacts/calllog/CallLogNotificationsService.java
@@ -26,8 +26,8 @@
  * <p>
  * It handles the following actions:
  * <ul>
- * <li>{@link #ACTION_MARK_NEW_CALLS_AS_OLD}: marks all the new items in the call log as old; this
- * is called when a notification is dismissed.</li>
+ * <li>{@link #ACTION_MARK_NEW_VOICEMAILS_AS_OLD}: marks all the new voicemails in the call log as
+ * old; this is called when a notification is dismissed.</li>
  * <li>{@link #ACTION_UPDATE_NOTIFICATIONS}: updates the content of the new items notification; it
  * may include an optional extra {@link #EXTRA_NEW_VOICEMAIL_URI}, containing the URI of the new
  * voicemail that has triggered this update (if any).</li>
@@ -36,11 +36,9 @@
 public class CallLogNotificationsService extends IntentService {
     private static final String TAG = "CallLogNotificationsService";
 
-    /**
-     * Action to mark all the new calls as old.
-     */
-    public static final String ACTION_MARK_NEW_CALLS_AS_OLD =
-            "com.android.contacts.calllog.MARK_NEW_CALLS_AS_OLD";
+    /** Action to mark all the new voicemails as old. */
+    public static final String ACTION_MARK_NEW_VOICEMAILS_AS_OLD =
+            "com.android.contacts.calllog.ACTION_MARK_NEW_VOICEMAILS_AS_OLD";
 
     /**
      * Action to update the notifications.
@@ -72,8 +70,8 @@
 
     @Override
     protected void onHandleIntent(Intent intent) {
-        if (ACTION_MARK_NEW_CALLS_AS_OLD.equals(intent.getAction())) {
-            mCallLogQueryHandler.markNewCallsAsOld();
+        if (ACTION_MARK_NEW_VOICEMAILS_AS_OLD.equals(intent.getAction())) {
+            mCallLogQueryHandler.markNewVoicemailsAsOld();
         } else if (ACTION_UPDATE_NOTIFICATIONS.equals(intent.getAction())) {
             Uri voicemailUri = (Uri) intent.getParcelableExtra(EXTRA_NEW_VOICEMAIL_URI);
             DefaultVoicemailNotifier.getInstance(this).updateNotification(voicemailUri);
diff --git a/src/com/android/contacts/calllog/CallLogQueryHandler.java b/src/com/android/contacts/calllog/CallLogQueryHandler.java
index b87a850..25beba5 100644
--- a/src/com/android/contacts/calllog/CallLogQueryHandler.java
+++ b/src/com/android/contacts/calllog/CallLogQueryHandler.java
@@ -50,12 +50,13 @@
     private static final int QUERY_OLD_CALLS_TOKEN = 54;
     /** The token for the query to mark all missed calls as old after seeing the call log. */
     private static final int UPDATE_MARK_AS_OLD_TOKEN = 55;
+    /** The token for the query to mark all new voicemails as old. */
+    private static final int UPDATE_MARK_VOICEMAILS_AS_OLD_TOKEN = 56;
     /** The token for the query to mark all missed calls as read after seeing the call log. */
-    private static final int UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN = 56;
+    private static final int UPDATE_MARK_MISSED_CALL_AS_READ_TOKEN = 57;
 
     /** The token for the query to fetch voicemail status messages. */
-    private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 57;
-
+    private static final int QUERY_VOICEMAIL_STATUS_TOKEN = 58;
 
     private final WeakReference<Listener> mListener;
 
@@ -191,6 +192,22 @@
                 values, where.toString(), null);
     }
 
+    /** Updates all new voicemails to mark them as old. */
+    public void markNewVoicemailsAsOld() {
+        // Mark all "new" voicemails as not new anymore.
+        StringBuilder where = new StringBuilder();
+        where.append(Calls.NEW);
+        where.append(" = 1 AND ");
+        where.append(Calls.TYPE);
+        where.append(" = ?");
+
+        ContentValues values = new ContentValues(1);
+        values.put(Calls.NEW, "0");
+
+        startUpdate(UPDATE_MARK_VOICEMAILS_AS_OLD_TOKEN, null, Calls.CONTENT_URI_WITH_VOICEMAIL,
+                values, where.toString(), new String[]{ Integer.toString(Calls.VOICEMAIL_TYPE) });
+    }
+
     /** Updates all missed calls to mark them as read. */
     public void markMissedCallsAsRead() {
         // Mark all "new" calls as not new anymore.
diff --git a/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java b/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
index 1cf67c1..f795a9c 100644
--- a/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
+++ b/src/com/android/contacts/calllog/DefaultVoicemailNotifier.java
@@ -153,7 +153,7 @@
                 .setContentTitle(title)
                 .setContentText(callers)
                 .setDefaults(callToNotify != null ? Notification.DEFAULT_ALL : 0)
-                .setDeleteIntent(createMarkNewCallsAsOld())
+                .setDeleteIntent(createMarkNewVoicemailsAsOldIntent())
                 .setAutoCancel(true)
                 .getNotification();
 
@@ -182,10 +182,10 @@
         mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification);
     }
 
-    /** Creates a pending intent that marks all new calls as old. */
-    private PendingIntent createMarkNewCallsAsOld() {
+    /** Creates a pending intent that marks all new voicemails as old. */
+    private PendingIntent createMarkNewVoicemailsAsOldIntent() {
         Intent intent = new Intent(mContext, CallLogNotificationsService.class);
-        intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_CALLS_AS_OLD);
+        intent.setAction(CallLogNotificationsService.ACTION_MARK_NEW_VOICEMAILS_AS_OLD);
         return PendingIntent.getService(mContext, 0, intent, 0);
     }
 
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index b2a203b..ba86f9f 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -19,12 +19,16 @@
 import com.android.contacts.ContactLoader;
 import com.android.contacts.R;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.util.StreamItemEntry;
 
 import android.app.ListFragment;
+import android.content.ContentUris;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.ContactsContract.StreamItems;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -69,27 +73,16 @@
                 // Ignore if this item does not have a stream item associated with it.
                 return;
             }
-            String actionUri = streamItemEntry.getActionUri();
-            if (actionUri == null) {
-                // Ignore if this item does not have a URI.
-                return;
-            }
-            // Parse the URI.
-            Uri uri;
-            try {
-                uri = Uri.parse(actionUri);
-            } catch (Throwable throwable) {
-                // This may fail if the URI is invalid: instead of failing, just ignore it.
-                Log.e(TAG, "invalid URI for stream item #" + streamItemEntry.getId() + ": "
-                        + actionUri);
-                return;
-            }
-            String action = streamItemEntry.getAction();
-            if (action == null) {
-                // Ignore if this item does not have an action.
-                return;
-            }
-            startActivity(new Intent(action, uri));
+            final AccountTypeManager manager = AccountTypeManager.getInstance(getActivity());
+            final AccountType accountType = manager.getAccountType(
+                    streamItemEntry.getAccountType(), streamItemEntry.getDataSet());
+
+            final Uri uri = ContentUris.withAppendedId(StreamItems.CONTENT_URI,
+                    streamItemEntry.getId());
+            final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+            intent.setClassName(accountType.resPackageName,
+                    accountType.getViewStreamItemActivity());
+            startActivity(intent);
         }
     };
 
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
index 09aa20b..5128787 100644
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ b/src/com/android/contacts/detail/StreamItemAdapter.java
@@ -17,6 +17,8 @@
 package com.android.contacts.detail;
 
 import com.android.contacts.R;
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.util.StreamItemEntry;
 import com.google.android.collect.Lists;
 
@@ -84,7 +86,10 @@
         StreamItemEntry streamItem = (StreamItemEntry) getItem(position);
         View view = ContactDetailDisplayUtils.createStreamItemView(
                 mInflater, mContext, streamItem, null);
-        if (streamItem.getAction() != null && streamItem.getActionUri() != null) {
+        final AccountTypeManager manager = AccountTypeManager.getInstance(mContext);
+        final AccountType accountType =
+                manager.getAccountType(streamItem.getAccountType(), streamItem.getDataSet());
+        if (accountType.getViewStreamItemActivity() != null) {
             view.setTag(streamItem);
             view.setFocusable(true);
             view.setOnClickListener(mListener);
diff --git a/src/com/android/contacts/format/FormatUtils.java b/src/com/android/contacts/format/FormatUtils.java
index 771656b..cb4dc2d 100644
--- a/src/com/android/contacts/format/FormatUtils.java
+++ b/src/com/android/contacts/format/FormatUtils.java
@@ -15,6 +15,7 @@
  */
 package com.android.contacts.format;
 
+import com.android.contacts.test.NeededForTesting;
 import com.google.common.annotations.VisibleForTesting;
 
 import android.database.CharArrayBuffer;
@@ -45,6 +46,7 @@
      * Finds the earliest point in string1 at which the first part of string2 matches.  For example,
      * overlapPoint("abcd", "cdef") == 2.
      */
+    @NeededForTesting  // App itself doesn't use this right now, but we don't want to remove it.
     public static int overlapPoint(String string1, String string2) {
         if (string1 == null || string2 == null) {
             return -1;
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
index 1205c31..1f47510 100644
--- a/src/com/android/contacts/group/GroupDetailFragment.java
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -30,6 +30,7 @@
 import android.app.Fragment;
 import android.app.LoaderManager;
 import android.app.LoaderManager.LoaderCallbacks;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.CursorLoader;
 import android.content.Intent;
@@ -38,6 +39,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.ContactsContract.Groups;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -68,10 +70,9 @@
         public void onGroupSizeUpdated(String size);
 
         /**
-         * The group source (intent action and action URI) has been determined.
+         * The account type and dataset have been determined.
          */
-        public void onGroupSourceUpdated(String accountTypeString, String dataSet,
-                String groupSourceAction, String groupSourceUri);
+        public void onAccountTypeUpdated(String accountTypeString, String dataSet);
 
         /**
          * User decided to go to Edit-Mode
@@ -277,9 +278,7 @@
 
             final String accountTypeString = cursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
             final String dataSet = cursor.getString(GroupMetaDataLoader.DATA_SET);
-            final String groupSourceAction = cursor.getString(GroupMetaDataLoader.ACTION);
-            final String groupSourceUri = cursor.getString(GroupMetaDataLoader.ACTION_URI);
-            updateGroupSource(accountTypeString, dataSet, groupSourceAction, groupSourceUri);
+            updateAccountType(accountTypeString, dataSet);
         }
     }
 
@@ -322,21 +321,23 @@
      * a button in a static header on the page, or as a header that scrolls with the
      * {@link ListView}.
      */
-    private void updateGroupSource(final String accountTypeString, final String dataSet,
-            final String groupSourceAction, final String groupSourceUri) {
+    private void updateAccountType(final String accountTypeString, final String dataSet) {
 
         // If the group action should be shown in the action bar, then pass the data to the
         // listener who will take care of setting up the view and click listener. There is nothing
         // else to be done by this {@link Fragment}.
         if (mShowGroupActionInActionBar) {
-            mListener.onGroupSourceUpdated(accountTypeString, dataSet, groupSourceAction,
-                    groupSourceUri);
+            mListener.onAccountTypeUpdated(accountTypeString, dataSet);
             return;
         }
 
+        final AccountTypeManager manager = AccountTypeManager.getInstance(getActivity());
+        final AccountType accountType =
+                manager.getAccountType(accountTypeString, dataSet);
+
         // Otherwise, if the {@link Fragment} needs to create and setup the button, then first
         // verify that there is a valid action.
-        if (!TextUtils.isEmpty(groupSourceAction) && !TextUtils.isEmpty(groupSourceUri)) {
+        if (!TextUtils.isEmpty(accountType.getViewGroupActivity())) {
             if (mGroupSourceView == null) {
                 mGroupSourceView = GroupDetailDisplayUtils.getNewGroupSourceView(mContext);
                 // Figure out how to add the view to the fragment.
@@ -358,7 +359,11 @@
             mGroupSourceView.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    startActivity(new Intent(groupSourceAction, Uri.parse(groupSourceUri)));
+                    final Uri uri = ContentUris.withAppendedId(Groups.CONTENT_URI, mGroupId);
+                    final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+                    intent.setClassName(accountType.resPackageName,
+                            accountType.getViewGroupActivity());
+                    startActivity(intent);
                 }
             });
         } else if (mGroupSourceView != null) {
@@ -431,4 +436,8 @@
     public void closeActivityAfterDelete(boolean closeActivity) {
         mCloseActivityAfterDelete = closeActivity;
     }
+
+    public long getGroupId() {
+        return mGroupId;
+    }
 }
diff --git a/src/com/android/contacts/interactions/PhoneNumberInteraction.java b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
index 9442f5e..0448bd5 100644
--- a/src/com/android/contacts/interactions/PhoneNumberInteraction.java
+++ b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
@@ -89,6 +89,18 @@
         long type;
         String label;
 
+        public PhoneItem() {
+        }
+
+        private PhoneItem(Parcel in) {
+            this.id          = in.readLong();
+            this.phoneNumber = in.readString();
+            this.accountType = in.readString();
+            this.dataSet     = in.readString();
+            this.type        = in.readLong();
+            this.label       = in.readString();
+        }
+
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeLong(id);
             dest.writeString(phoneNumber);
@@ -129,6 +141,17 @@
         public String toString() {
             return phoneNumber;
         }
+
+        public static final Parcelable.Creator<PhoneItem> CREATOR
+                = new Parcelable.Creator<PhoneItem>() {
+            public PhoneItem createFromParcel(Parcel in) {
+                return new PhoneItem(in);
+            }
+
+            public PhoneItem[] newArray(int size) {
+                return new PhoneItem[size];
+            }
+        };
     }
 
     /**
diff --git a/src/com/android/contacts/list/ContactTileAdapter.java b/src/com/android/contacts/list/ContactTileAdapter.java
index 7a293b3..37ccded 100644
--- a/src/com/android/contacts/list/ContactTileAdapter.java
+++ b/src/com/android/contacts/list/ContactTileAdapter.java
@@ -73,6 +73,7 @@
     private int mPhoneNumberLabelIndex;
 
     private boolean mIsQuickContactEnabled = false;
+    private final int mPaddingInPixels;
 
     /**
      * Configures the adapter to filter and display contacts using different view types.
@@ -116,6 +117,10 @@
         mColumnCount = (displayType == DisplayType.FREQUENT_ONLY ? 1 : numCols);
         mDisplayType = displayType;
 
+        // Converting padding in dips to padding in pixels
+        mPaddingInPixels = mContext.getResources()
+                .getDimensionPixelOffset(R.dimen.contact_tile_divider_padding);
+
         bindColumnIndices();
     }
 
@@ -406,7 +411,7 @@
     }
     @Override
     public int getViewTypeCount() {
-        return ViewTypes.MAX_VIEW_COUNT;
+        return ViewTypes.COUNT;
     }
 
     @Override
@@ -498,10 +503,21 @@
             contactTile.setClickable(entry != null);
             contactTile.loadFromContact(entry);
 
-            contactTile.setVerticalDividerVisibility(
-                    childIndex >= mColumnCount - 1 ? View.GONE : View.VISIBLE);
-            contactTile.setHorizontalDividerVisibility(
-                    isLastRow ? View.GONE : View.VISIBLE);
+            switch (mItemViewType) {
+                case ViewTypes.STARRED_WITH_SECONDARY_ACTION:
+                case ViewTypes.STARRED:
+                    // Setting divider visibilities
+                    contactTile.setPadding(0, 0,
+                            childIndex >= mColumnCount - 1 ? 0 : mPaddingInPixels,
+                            isLastRow ? 0 : mPaddingInPixels);
+                    break;
+                case ViewTypes.FREQUENT:
+                    contactTile.setHorizontalDividerVisibility(
+                            isLastRow ? View.GONE : View.VISIBLE);
+                    break;
+                default:
+                    break;
+            }
         }
     }
 
@@ -519,7 +535,7 @@
     }
 
     private static class ViewTypes {
-        public static final int MAX_VIEW_COUNT = 4;
+        public static final int COUNT = 4;
         public static final int STARRED = 0;
         public static final int DIVIDER = 1;
         public static final int FREQUENT = 2;
diff --git a/src/com/android/contacts/list/ContactTileView.java b/src/com/android/contacts/list/ContactTileView.java
index ef9c2fb..25edd7f 100644
--- a/src/com/android/contacts/list/ContactTileView.java
+++ b/src/com/android/contacts/list/ContactTileView.java
@@ -27,7 +27,6 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.FrameLayout;
-import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.QuickContactBadge;
 import android.widget.TextView;
@@ -40,17 +39,15 @@
 
     private Uri mLookupUri;
     private ImageView mPhoto;
-    private ImageView mPresence;
     private QuickContactBadge mQuickContact;
     private TextView mName;
     private TextView mStatus;
     private TextView mPhoneLabel;
     private TextView mPhoneNumber;
     private ContactPhotoManager mPhotoManager = null;
-    private ImageButton mPushState;
-    private Listener mListener;
-    private View mVerticalDivider;
+    private View mPushState;
     private View mHorizontalDivider;
+    private Listener mListener;
 
     public ContactTileView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -63,12 +60,10 @@
 
         mQuickContact = (QuickContactBadge) findViewById(R.id.contact_tile_quick);
         mPhoto = (ImageView) findViewById(R.id.contact_tile_image);
-        mPresence = (ImageView) findViewById(R.id.contact_tile_presence);
         mStatus = (TextView) findViewById(R.id.contact_tile_status);
         mPhoneLabel = (TextView) findViewById(R.id.contact_tile_phone_type);
         mPhoneNumber = (TextView) findViewById(R.id.contact_tile_phone_number);
-        mPushState = (ImageButton) findViewById(R.id.contact_tile_push_state);
-        mVerticalDivider = findViewById(R.id.contact_tile_vertical_divider);
+        mPushState = findViewById(R.id.contact_tile_push_state);
         mHorizontalDivider = findViewById(R.id.contact_tile_horizontal_divider);
 
         OnClickListener listener = new OnClickListener() {
@@ -100,23 +95,25 @@
             mName.setText(entry.name);
             mLookupUri = entry.lookupKey;
 
-            int presenceDrawableResId = (entry.presence == null ? 0 :
-                    StatusUpdates.getPresenceIconResourceId(entry.presence));
-
-            if (mPresence != null) {
-                mPresence.setBackgroundResource(presenceDrawableResId);
-            }
-
             if (mStatus != null) {
                 String statusText;
                 if (entry.presence == null) {
-                    statusText = null;
+                    mStatus.setVisibility(View.GONE);
                 } else {
                     statusText =
                           (entry.status != null ? entry.status :
                           ContactStatusUtil.getStatusString(mContext, entry.presence));
+                    mStatus.setText(statusText);
+                    int presenceDrawableResId = (entry.presence == null ? 0 :
+                            StatusUpdates.getPresenceIconResourceId(entry.presence));
+                    if (presenceDrawableResId != 0) {
+                        Log.i(TAG, "iconId = " + presenceDrawableResId);
+                        mStatus.setCompoundDrawablesWithIntrinsicBounds(
+                                getResources().getDrawable(presenceDrawableResId),
+                                null, null, null);
+                    }
+                    mStatus.setVisibility(View.VISIBLE);
                 }
-                mStatus.setText(statusText);
             }
 
             if (mPhoneLabel != null) {
@@ -128,21 +125,19 @@
                 mPhoneNumber.setText(entry.phoneNumber);
             }
 
-            if (mQuickContact != null) {
-                mQuickContact.assignContactUri(mLookupUri);
-                mQuickContact.setImageBitmap(null);
-            } else {
-                mPhoto.setImageBitmap(null);
-            }
-
             setVisibility(View.VISIBLE);
 
             if (mPhotoManager != null) {
-                if (mQuickContact != null){
-                    mPhotoManager.loadPhoto(mQuickContact, entry.photoUri);
-                } else {
+                if (mPhoto != null) {
                     mPhotoManager.loadPhoto(mPhoto, entry.photoUri);
-                }
+
+                    if (mQuickContact != null) {
+                        mQuickContact.assignContactUri(mLookupUri);
+                    }
+                } else if (mQuickContact != null) {
+                        mQuickContact.assignContactUri(mLookupUri);
+                        mPhotoManager.loadPhoto(mQuickContact, entry.photoUri);
+                    }
 
             } else {
                 Log.w(TAG, "contactPhotoManager not set");
@@ -152,18 +147,14 @@
         }
     }
 
-    public void setVerticalDividerVisibility(int visibility) {
-        if (mVerticalDivider != null) mVerticalDivider.setVisibility(visibility);
+    public void setListener(Listener listener) {
+        mListener = listener;
     }
 
     public void setHorizontalDividerVisibility(int visibility) {
         if (mHorizontalDivider != null) mHorizontalDivider.setVisibility(visibility);
     }
 
-    public void setListener(Listener listener) {
-        mListener = listener;
-    }
-
     public Uri getLookupUri() {
         return mLookupUri;
     }
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index a78185f..95216e6 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -123,6 +123,21 @@
         return null;
     }
 
+    /** Returns an optional Activity string that can be used to view the group. */
+    public String getViewGroupActivity() {
+        return null;
+    }
+
+    /** Returns an optional Activity string that can be used to view the stream item. */
+    public String getViewStreamItemActivity() {
+        return null;
+    }
+
+    /** Returns an optional Activity string that can be used to view the stream item photo. */
+    public String getViewStreamItemPhotoActivity() {
+        return null;
+    }
+
     public CharSequence getDisplayLabel(Context context) {
         return getResourceText(context, summaryResPackageName, titleRes, accountType);
     }
@@ -130,7 +145,7 @@
     /**
      * @return resource ID for the "invite contact" action label, or -1 if not defined.
      */
-    protected int getInviteContactActionResId(Context conext) {
+    protected int getInviteContactActionResId(Context context) {
         return -1;
     }
 
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index 5dd4d3b..791f0ae 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/ExternalAccountType.java
@@ -58,6 +58,10 @@
     private static final String ATTR_INVITE_CONTACT_ACTIVITY = "inviteContactActivity";
     private static final String ATTR_INVITE_CONTACT_ACTION_LABEL = "inviteContactActionLabel";
     private static final String ATTR_VIEW_CONTACT_NOTIFY_SERVICE = "viewContactNotifyService";
+    private static final String ATTR_VIEW_GROUP_ACTIVITY = "viewGroupActivity";
+    private static final String ATTR_VIEW_STREAM_ITEM_ACTIVITY = "viewStreamItemActivity";
+    private static final String ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY =
+            "viewStreamItemPhotoActivity";
     private static final String ATTR_DATA_SET = "dataSet";
     private static final String ATTR_EXTENSION_PACKAGE_NAMES = "extensionPackageNames";
 
@@ -73,6 +77,9 @@
     private String mInviteContactActivity;
     private String mInviteActionLabelAttribute;
     private String mViewContactNotifyService;
+    private String mViewGroupActivity;
+    private String mViewStreamItemActivity;
+    private String mViewStreamItemPhotoActivity;
     private List<String> mExtensionPackageNames;
     private int mInviteActionLabelResId;
     private String mAccountTypeLabelAttribute;
@@ -156,6 +163,21 @@
     }
 
     @Override
+    public String getViewGroupActivity() {
+        return mViewGroupActivity;
+    }
+
+    @Override
+    public String getViewStreamItemActivity() {
+        return mViewStreamItemActivity;
+    }
+
+    @Override
+    public String getViewStreamItemPhotoActivity() {
+        return mViewStreamItemPhotoActivity;
+    }
+
+    @Override
     public List<String> getExtensionPackageNames() {
         return mExtensionPackageNames;
     }
@@ -202,6 +224,12 @@
                     mInviteActionLabelAttribute = value;
                 } else if (ATTR_VIEW_CONTACT_NOTIFY_SERVICE.equals(attr)) {
                     mViewContactNotifyService = value;
+                } else if (ATTR_VIEW_GROUP_ACTIVITY.equals(attr)) {
+                    mViewGroupActivity = value;
+                } else if (ATTR_VIEW_STREAM_ITEM_ACTIVITY.equals(attr)) {
+                    mViewStreamItemActivity = value;
+                } else if (ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY.equals(attr)) {
+                    mViewStreamItemPhotoActivity = value;
                 } else if (ATTR_DATA_SET.equals(attr)) {
                     dataSet = value;
                 } else if (ATTR_EXTENSION_PACKAGE_NAMES.equals(attr)) {
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index 98a843e..682f700 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -18,8 +18,9 @@
 
 import com.android.contacts.ContactLoader;
 import com.android.contacts.R;
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.util.ContactBadgeUtil;
-import com.android.contacts.util.DataStatus;
 import com.android.contacts.util.StreamItemEntry;
 
 import android.app.PendingIntent;
@@ -33,8 +34,8 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Typeface;
 import android.net.Uri;
-import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.QuickContact;
+import android.provider.ContactsContract.StreamItems;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.style.AbsoluteSizeSpan;
@@ -44,7 +45,6 @@
 import android.view.View;
 import android.widget.RemoteViews;
 
-import java.util.HashMap;
 import java.util.List;
 
 public class SocialWidgetProvider extends AppWidgetProvider {
@@ -214,10 +214,15 @@
             views.setTextViewText(R.id.name_and_snippet, sb);
             views.setViewVisibility(R.id.name, View.GONE);
             views.setViewVisibility(R.id.name_and_snippet, View.VISIBLE);
-            if (!TextUtils.isEmpty(streamItem.getAction())
-                    && !TextUtils.isEmpty(streamItem.getActionUri())) {
-                final Intent intent = new Intent(streamItem.getAction(),
-                        Uri.parse(streamItem.getActionUri()));
+            final AccountTypeManager manager = AccountTypeManager.getInstance(context);
+            final AccountType accountType =
+                    manager.getAccountType(streamItem.getAccountType(), streamItem.getDataSet());
+            if (accountType.getViewStreamItemActivity() != null) {
+                final Uri uri = ContentUris.withAppendedId(StreamItems.CONTENT_URI,
+                        streamItem.getId());
+                final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+                intent.setClassName(accountType.resPackageName,
+                        accountType.getViewStreamItemActivity());
                 views.setOnClickPendingIntent(R.id.name_and_snippet_container,
                         PendingIntent.getActivity(context, 0, intent, 0));
             }
diff --git a/src/com/android/contacts/util/ContactBadgeUtil.java b/src/com/android/contacts/util/ContactBadgeUtil.java
index 2f37b4c..806264d 100644
--- a/src/com/android/contacts/util/ContactBadgeUtil.java
+++ b/src/com/android/contacts/util/ContactBadgeUtil.java
@@ -16,14 +16,12 @@
 
 package com.android.contacts.util;
 
-import com.android.contacts.ContactLoader;
 import com.android.contacts.R;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.text.TextUtils;
@@ -57,9 +55,9 @@
 
         String labelDisplayValue = null;
 
-        final Integer statusLabel = streamItem.getLabelRes();
+        final String statusLabelRes = streamItem.getLabelRes();
         final String statusResPackage = streamItem.getResPackage();
-        if (statusLabel  != null) {
+        if (statusLabelRes  != null) {
             Resources resources;
             if (TextUtils.isEmpty(statusResPackage)) {
                 resources = context.getResources();
@@ -75,11 +73,13 @@
             }
 
             if (resources != null) {
-                try {
-                    labelDisplayValue = resources.getString(statusLabel.intValue());
-                } catch (NotFoundException e) {
-                    Log.w(TAG, "Contact status update resource not found: " + statusResPackage + "@"
-                            + statusLabel.intValue());
+                final int resId = resources.getIdentifier(statusLabelRes, "string",
+                        statusResPackage);
+                if (resId == 0) {
+                    Log.w(TAG, "Contact status update resource not found: " + statusLabelRes +
+                            " in " + statusResPackage);
+                } else {
+                    labelDisplayValue = resources.getString(resId);
                 }
             }
         }
diff --git a/src/com/android/contacts/util/StreamItemEntry.java b/src/com/android/contacts/util/StreamItemEntry.java
index db15e3a..5959c46 100644
--- a/src/com/android/contacts/util/StreamItemEntry.java
+++ b/src/com/android/contacts/util/StreamItemEntry.java
@@ -37,26 +37,29 @@
     private final String mText;
     private final String mComments;
     private final long mTimestamp;
-    private final String mAction;
-    private final String mActionUri;
+    private final String mAccountType;
+    private final String mAccountName;
+    private final String mDataSet;
 
     // Package references for label and icon resources.
     private final String mResPackage;
-    private final int mIconRes;
-    private final int mLabelRes;
+    private final String mIconRes;
+    private final String mLabelRes;
 
     // Photos associated with this stream item.
     private List<StreamItemPhotoEntry> mPhotos;
 
     @NeededForTesting
-    public StreamItemEntry(long id, String text, String comments, long timestamp, String action,
-            String actionUri, String resPackage, int iconRes, int labelRes) {
+    public StreamItemEntry(long id, String text, String comments, long timestamp,
+            String accountType, String accountName, String dataSet, String resPackage,
+            String iconRes, String labelRes) {
         mId = id;
         mText = text;
         mComments = comments;
         mTimestamp = timestamp;
-        mAction = action;
-        mActionUri = actionUri;
+        mAccountType = accountType;
+        mAccountName = accountName;
+        mDataSet = dataSet;
         mResPackage = resPackage;
         mIconRes = iconRes;
         mLabelRes = labelRes;
@@ -70,11 +73,12 @@
         mText = getString(cursor, StreamItems.TEXT);
         mComments = getString(cursor, StreamItems.COMMENTS);
         mTimestamp = getLong(cursor, StreamItems.TIMESTAMP);
-        mAction = getString(cursor, StreamItems.ACTION);
-        mActionUri = getString(cursor, StreamItems.ACTION_URI);
+        mAccountType = getString(cursor, StreamItems.ACCOUNT_TYPE);
+        mAccountName = getString(cursor, StreamItems.ACCOUNT_NAME);
+        mDataSet = getString(cursor, StreamItems.DATA_SET);
         mResPackage = getString(cursor, StreamItems.RES_PACKAGE);
-        mIconRes = getInt(cursor, StreamItems.RES_ICON, -1);
-        mLabelRes = getInt(cursor, StreamItems.RES_LABEL, -1);
+        mIconRes = getString(cursor, StreamItems.RES_ICON);
+        mLabelRes = getString(cursor, StreamItems.RES_LABEL);
         mPhotos = new ArrayList<StreamItemPhotoEntry>();
     }
 
@@ -103,23 +107,27 @@
         return mTimestamp;
     }
 
-    public String getAction() {
-        return mAction;
+    public String getAccountType() {
+        return mAccountType;
     }
 
-    public String getActionUri() {
-        return mActionUri;
+    public String getAccountName() {
+        return mAccountName;
+    }
+
+    public String getDataSet() {
+        return mDataSet;
     }
 
     public String getResPackage() {
         return mResPackage;
     }
 
-    public int getIconRes() {
+    public String getIconRes() {
         return mIconRes;
     }
 
-    public int getLabelRes() {
+    public String getLabelRes() {
         return mLabelRes;
     }
 
@@ -132,11 +140,6 @@
         return cursor.getString(cursor.getColumnIndex(columnName));
     }
 
-    private static int getInt(Cursor cursor, String columnName, int missingValue) {
-        final int columnIndex = cursor.getColumnIndex(columnName);
-        return cursor.isNull(columnIndex) ? missingValue : cursor.getInt(columnIndex);
-    }
-
     private static long getLong(Cursor cursor, String columnName) {
         final int columnIndex = cursor.getColumnIndex(columnName);
         return cursor.getLong(columnIndex);
diff --git a/src/com/android/contacts/util/StreamItemPhotoEntry.java b/src/com/android/contacts/util/StreamItemPhotoEntry.java
index 6527454..ad69e5c 100644
--- a/src/com/android/contacts/util/StreamItemPhotoEntry.java
+++ b/src/com/android/contacts/util/StreamItemPhotoEntry.java
@@ -33,11 +33,9 @@
     private final int mHeight;
     private final int mWidth;
     private final int mFileSize;
-    private final String mAction;
-    private final String mActionUri;
 
     public StreamItemPhotoEntry(long id, int sortIndex, long photoFileId, String photoUri,
-            int height, int width, int fileSize, String action, String actionUri) {
+            int height, int width, int fileSize) {
         mId = id;
         mSortIndex = sortIndex;
         mPhotoFileId = photoFileId;
@@ -45,8 +43,6 @@
         mHeight = height;
         mWidth = width;
         mFileSize = fileSize;
-        mAction = action;
-        mActionUri = actionUri;
     }
 
     public StreamItemPhotoEntry(Cursor cursor) {
@@ -59,8 +55,6 @@
         mHeight = getInt(cursor, PhotoFiles.HEIGHT, -1);
         mWidth = getInt(cursor, PhotoFiles.WIDTH, -1);
         mFileSize = getInt(cursor, PhotoFiles.FILESIZE, -1);
-        mAction = getString(cursor, StreamItemPhotos.ACTION);
-        mActionUri = getString(cursor, StreamItemPhotos.ACTION_URI);
     }
 
     public long getId() {
@@ -91,14 +85,6 @@
         return mFileSize;
     }
 
-    public String getAction() {
-        return mAction;
-    }
-
-    public String getActionUri() {
-        return mActionUri;
-    }
-
     @Override
     public int compareTo(StreamItemPhotoEntry streamItemPhotoEntry) {
         // Sort index is used to compare, falling back to ID if neither entry has a
diff --git a/tests/src/com/android/contacts/ContactLoaderTest.java b/tests/src/com/android/contacts/ContactLoaderTest.java
index a731f24..3560ce1 100644
--- a/tests/src/com/android/contacts/ContactLoaderTest.java
+++ b/tests/src/com/android/contacts/ContactLoaderTest.java
@@ -16,7 +16,12 @@
 
 package com.android.contacts;
 
+import com.android.contacts.model.AccountType;
+import com.android.contacts.model.AccountWithDataSet;
+import com.android.contacts.model.BaseAccountType;
+import com.android.contacts.test.InjectedServices;
 import com.android.contacts.tests.mocks.ContactsMockContext;
+import com.android.contacts.tests.mocks.MockAccountTypeManager;
 import com.android.contacts.tests.mocks.MockContentProvider;
 
 import android.content.ContentUris;
@@ -36,18 +41,31 @@
  */
 @LargeTest
 public class ContactLoaderTest extends LoaderTestCase {
-    ContactsMockContext mMockContext;
-    MockContentProvider mContactsProvider;
+    private ContactsMockContext mMockContext;
+    private MockContentProvider mContactsProvider;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mMockContext = new ContactsMockContext(getContext());
         mContactsProvider = mMockContext.getContactsProvider();
+
+        InjectedServices services = new InjectedServices();
+        AccountType accountType = new BaseAccountType();
+        accountType.accountType = "mockAccountType";
+
+        AccountWithDataSet account =
+                new AccountWithDataSet("mockAccountName", "mockAccountType", null);
+
+        mMockContext.setMockAccountTypeManager(
+                new MockAccountTypeManager(
+                        new AccountType[] { accountType }, new AccountWithDataSet[] { account }));
     }
 
     @Override
     protected void tearDown() throws Exception {
+        mMockContext = null;
+        mContactsProvider = null;
         super.tearDown();
     }
 
diff --git a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
index 99ae834..d862d6e 100644
--- a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
+++ b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
@@ -20,12 +20,14 @@
 import com.android.contacts.util.StreamItemEntryBuilder;
 import com.google.common.collect.Lists;
 
-import android.content.Intent;
 import android.test.AndroidTestCase;
 import android.view.View;
 
 import java.util.ArrayList;
 
+// TODO: We should have tests for action, but that requires a mock sync-adapter that specifies
+// an action or doesn't
+
 /**
  * Unit tests for {@link StreamItemAdapter}.
  */
@@ -51,30 +53,13 @@
     public void testGetCount_Empty() {
         mAdapter.setStreamItems(createStreamItemList(0));
         // There is actually one view: the header.
-        assertEquals(1, mAdapter.getCount());
+        assertEquals(2, mAdapter.getCount());
     }
 
     public void testGetCount_NonEmpty() {
         mAdapter.setStreamItems(createStreamItemList(3));
         // There is one extra view: the header.
-        assertEquals(4, mAdapter.getCount());
-    }
-
-    public void testGetView_WithAction() {
-        StreamItemEntry streamItem = createStreamItemWithAction();
-        mAdapter.setStreamItems(Lists.newArrayList(streamItem));
-        mView = mAdapter.getView(1, null, null);
-        assertStreamItemViewHasTag(streamItem);
-        assertStreamItemViewHasOnClickListener();
-        assertStreamItemViewFocusable();
-    }
-
-    public void testGetView_WithoutAction() {
-        mAdapter.setStreamItems(Lists.newArrayList(createStreamItemWithoutAction()));
-        mView = mAdapter.getView(1, null, null);
-        assertStreamItemViewHasNoTag();
-        assertStreamItemViewHasNoOnClickListener();
-        assertStreamItemViewNotFocusable();
+        assertEquals(5, mAdapter.getCount());
     }
 
     public void testGetView_Header() {
@@ -91,22 +76,6 @@
                 "text #" + mCreateStreamItemEntryBuilderCounter++);
     }
 
-    /** Returns a stream item with an action and action URI set. */
-    private StreamItemEntry createStreamItemWithAction() {
-        return createStreamItemEntryBuilder()
-                .setAction(Intent.ACTION_VIEW)
-                .setActionUri("http://www.google.com")
-                .build();
-    }
-
-    /** Returns a stream item without an action and action URI set. */
-    private StreamItemEntry createStreamItemWithoutAction() {
-        return createStreamItemEntryBuilder()
-                .setAction(null)
-                .setActionUri(null)
-                .build();
-    }
-
     /** Creates a list containing the given number of {@link StreamItemEntry}s. */
     private ArrayList<StreamItemEntry> createStreamItemList(int count) {
         ArrayList<StreamItemEntry> list = Lists.newArrayList();
diff --git a/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java b/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
index 93ea4f4..2f959f4 100644
--- a/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
+++ b/tests/src/com/android/contacts/tests/mocks/ContactsMockContext.java
@@ -16,6 +16,8 @@
 
 package com.android.contacts.tests.mocks;
 
+import com.android.contacts.model.AccountTypeManager;
+
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -32,13 +34,11 @@
  * to mock content providers.
  */
 public class ContactsMockContext extends ContextWrapper {
-
-    private static final String TAG = "ContactsMockContext";
-
     private ContactsMockPackageManager mPackageManager;
     private MockContentResolver mContentResolver;
     private MockContentProvider mContactsProvider;
     private MockContentProvider mSettingsProvider;
+    private MockAccountTypeManager mMockAccountTypeManager;
     private Intent mIntentForStartActivity;
 
     public ContactsMockContext(Context base) {
@@ -53,6 +53,10 @@
         mContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
     }
 
+    public void setMockAccountTypeManager(MockAccountTypeManager mockAccountTypeManager) {
+        mMockAccountTypeManager = mockAccountTypeManager;
+    }
+
     @Override
     public ContentResolver getContentResolver() {
         return mContentResolver;
@@ -93,4 +97,12 @@
         mContactsProvider.verify();
         mSettingsProvider.verify();
     }
+
+    @Override
+    public Object getSystemService(String name) {
+        if (AccountTypeManager.ACCOUNT_TYPE_SERVICE.equals(name)) {
+           return mMockAccountTypeManager;
+        }
+        return super.getSystemService(name);
+    }
 }
diff --git a/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java b/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java
index e27c767..d6e95ef 100644
--- a/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java
+++ b/tests/src/com/android/contacts/tests/streamitems/StreamItemPopulatorActivity.java
@@ -83,15 +83,15 @@
             "<i>24567</i> <font color='blue' size='+1'><b>likes</b></font>"
     };
 
-    private Integer[] labelIds = new Integer[] {
-            R.string.attribution_google_plus,
-            R.string.attribution_google_talk,
-            R.string.attribution_flicker,
-            R.string.attribution_twitter
+    private String[] labelResources = new String[] {
+            "attribution_google_plus",
+            "attribution_google_talk",
+            "attribution_flicker",
+            "attribution_twitter"
     };
 
-    public Integer[] iconIds = new Integer[] {
-            R.drawable.default_icon,
+    public String[] iconResources = new String[] {
+            "default_icon"
     };
 
     // Photos to randomly select from.
@@ -264,10 +264,10 @@
                 + (includeAction ? " [a]" : ""));
         if (includeAttribution) {
             values.put(StreamItems.RES_PACKAGE, "com.android.contacts.tests");
-            int sourceIndex = randInt(labelIds.length);
-            values.put(StreamItems.RES_LABEL, labelIds[sourceIndex]);
-            if (sourceIndex < iconIds.length) {
-                values.put(StreamItems.RES_ICON, iconIds[sourceIndex]);
+            int sourceIndex = randInt(labelResources.length);
+            values.put(StreamItems.RES_LABEL, labelResources[sourceIndex]);
+            if (sourceIndex < iconResources.length) {
+                values.put(StreamItems.RES_ICON, iconResources[sourceIndex]);
             }
         }
         if (includeComments) {
@@ -280,10 +280,6 @@
                 System.currentTimeMillis() - randInt(360000000));
         values.put(RawContacts.ACCOUNT_TYPE, accountType);
         values.put(RawContacts.ACCOUNT_NAME, accountName);
-        if (includeAction) {
-            values.put(StreamItems.ACTION, Intent.ACTION_VIEW);
-            values.put(StreamItems.ACTION_URI, getGoogleSearchUri(place));
-        }
         return values;
     }
 
@@ -295,20 +291,9 @@
         values.put(StreamItemPhotos.PHOTO, loadPhotoFromResource(imageIndex));
         values.put(RawContacts.ACCOUNT_TYPE, accountType);
         values.put(RawContacts.ACCOUNT_NAME, accountName);
-        if (imageIndex < imageStrings.length) {
-            values.put(StreamItemPhotos.ACTION, Intent.ACTION_VIEW);
-            String queryTerm = imageStrings[imageIndex];
-            values.put(StreamItemPhotos.ACTION_URI, getGoogleSearchUri(queryTerm));
-
-        }
         return values;
     }
 
-    /** Returns the URI of the Google search results page for the given query. */
-    private String getGoogleSearchUri(String query) {
-        return "http://www.google.com/search?q=" + query.replace(" ", "+");
-    }
-
     private <T> T pickRandom(T[] from) {
         return from[randInt(from.length)];
     }
diff --git a/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java b/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java
index 8a17b4a..319ba48 100644
--- a/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java
+++ b/tests/src/com/android/contacts/util/StreamItemEntryBuilder.java
@@ -24,36 +24,42 @@
     private String mText;
     private String mComment;
     private long mTimestamp;
-    private String mAction;
-    private String mActionUri;
+    private String mAccountType;
+    private String mAccountName;
+    private String mDataSet;
     private String mResPackage;
-    private int mIconRes;
-    private int mLabelRes;
+    private String mIconRes;
+    private String mLabelRes;
 
     public StreamItemEntryBuilder() {}
 
-    public StreamItemEntryBuilder setText(String text) {
-        mText = text;
+    public StreamItemEntryBuilder setText(String value) {
+        mText = value;
         return this;
     }
 
-    public StreamItemEntryBuilder setComment(String comment) {
-        mComment = comment;
+    public StreamItemEntryBuilder setComment(String value) {
+        mComment = value;
         return this;
     }
 
-    public StreamItemEntryBuilder setAction(String action) {
-        mAction = action;
+    public StreamItemEntryBuilder setAccountType(String value) {
+        mAccountType = value;
         return this;
     }
 
-    public StreamItemEntryBuilder setActionUri(String actionUri) {
-        mActionUri = actionUri;
+    public StreamItemEntryBuilder setAccountName(String value) {
+        mAccountName = value;
+        return this;
+    }
+
+    public StreamItemEntryBuilder setDataSet(String value) {
+        mDataSet = value;
         return this;
     }
 
     public StreamItemEntry build() {
-        return new StreamItemEntry(mId, mText, mComment, mTimestamp, mAction, mActionUri,
-                mResPackage, mIconRes, mLabelRes);
+        return new StreamItemEntry(mId, mText, mComment, mTimestamp, mAccountType, mAccountName,
+                mDataSet, mResPackage, mIconRes, mLabelRes);
     }
 }
\ No newline at end of file