Merge "Remove repetitive text in menu options for Contact details"
diff --git a/res/drawable-hdpi/tab_selected_focused_holo.9.png b/res/drawable-hdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..feaaa2d
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_holo.9.png b/res/drawable-hdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..b939b5d
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..ccb7342
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..4f59d32
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_holo.9.png b/res/drawable-hdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..de9f4f2
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..8e706b0
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_focused_holo.9.png b/res/drawable-mdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..ffe76c7
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_holo.9.png b/res/drawable-mdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..6ccbd47
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..834b1f5
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..9cf9398
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_holo.9.png b/res/drawable-mdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..5834c1f
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..b205bc7
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_focused_holo.9.png b/res/drawable-xhdpi/tab_selected_focused_holo.9.png
new file mode 100644
index 0000000..8bb6ec5
--- /dev/null
+++ b/res/drawable-xhdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_holo.9.png b/res/drawable-xhdpi/tab_selected_holo.9.png
new file mode 100644
index 0000000..81d5b34
--- /dev/null
+++ b/res/drawable-xhdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_pressed_holo.9.png b/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
new file mode 100644
index 0000000..9ae1441
--- /dev/null
+++ b/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_focused_holo.9.png b/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
new file mode 100644
index 0000000..5973936
--- /dev/null
+++ b/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_holo.9.png b/res/drawable-xhdpi/tab_unselected_holo.9.png
new file mode 100644
index 0000000..1590ba8
--- /dev/null
+++ b/res/drawable-xhdpi/tab_unselected_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png b/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
new file mode 100644
index 0000000..b781355
--- /dev/null
+++ b/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable/action_bar_tab.xml b/res/drawable/action_bar_tab.xml
new file mode 100644
index 0000000..7676549
--- /dev/null
+++ b/res/drawable/action_bar_tab.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_pressed="true"
+        android:state_selected="true"
+        android:drawable="@drawable/tab_selected_pressed_holo"/>
+    <item
+        android:state_focused="true"
+        android:state_selected="true"
+        android:drawable="@drawable/tab_selected_focused_holo"/>
+    <item
+        android:state_focused="true"
+        android:state_selected="false"
+        android:drawable="@drawable/tab_unselected_focused_holo"/>
+    <item
+        android:state_pressed="true"
+        android:state_selected="false"
+        android:drawable="@drawable/tab_unselected_pressed_holo"/>
+    <item
+        android:state_focused="false"
+        android:state_selected="true"
+        android:state_pressed="false"
+        android:drawable="@drawable/tab_selected_holo"/>
+    <item
+        android:state_focused="false"
+        android:state_pressed="false"
+        android:state_selected="false"
+        android:drawable="@drawable/tab_unselected_holo"/>
+</selector>
\ No newline at end of file
diff --git a/res/layout/contact_tile_frequent.xml b/res/layout/contact_tile_frequent.xml
index fc9c04c..14cb04e 100644
--- a/res/layout/contact_tile_frequent.xml
+++ b/res/layout/contact_tile_frequent.xml
@@ -52,7 +52,7 @@
             android:id="@+id/contact_tile_status"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textSize="12sp"
+            android:textSize="14sp"
             android:ellipsize="end"
             android:singleLine="true"
             android:textColor="#cccccc"
diff --git a/res/layout/contact_tile_frequent_phone.xml b/res/layout/contact_tile_frequent_phone.xml
index e0ea0fb..50c1fc2 100644
--- a/res/layout/contact_tile_frequent_phone.xml
+++ b/res/layout/contact_tile_frequent_phone.xml
@@ -47,11 +47,11 @@
             android:id="@+id/contact_tile_phone_number"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textSize="12sp"
+            android:textSize="14sp"
             android:ellipsize="end"
             android:singleLine="true"
-            android:textColor="#cccccc"
-            android:layout_marginLeft="12dip"
+            android:textColor="@color/dialtacts_secondary_text_color"
+            android:layout_marginLeft="8dip"
             android:layout_toRightOf="@id/contact_tile_quick"
             android:layout_below="@id/contact_tile_name" />
 
@@ -59,14 +59,30 @@
             android:id="@+id/contact_tile_phone_type"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textSize="12sp"
+            android:textSize="14sp"
             android:ellipsize="end"
             android:singleLine="true"
-            android:textColor="#cccccc"
+            android:textAllCaps="true"
+            android:textColor="@color/dialtacts_secondary_text_color"
             android:layout_marginLeft="12dip"
             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: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" />
+
     </RelativeLayout>
 
 </view>
diff --git a/res/layout/contact_tile_starred.xml b/res/layout/contact_tile_starred.xml
index d667a34..3b74946 100644
--- a/res/layout/contact_tile_starred.xml
+++ b/res/layout/contact_tile_starred.xml
@@ -61,7 +61,7 @@
             android:layout_marginLeft="4dip"
             style="@style/ContactTileStatusText" />
 
-        <ImageButton
+       <ImageButton
             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_secondary_target.xml b/res/layout/contact_tile_starred_secondary_target.xml
index 887fa5d..3558166 100644
--- a/res/layout/contact_tile_starred_secondary_target.xml
+++ b/res/layout/contact_tile_starred_secondary_target.xml
@@ -61,14 +61,14 @@
         </FrameLayout>
 
         <View
-            android:id="@+id/vertical_divider"
+            android:id="@+id/secondary_vertical_divider"
             android:layout_width="1dip"
-            android:layout_height="24dip"
+            android:layout_height="32dip"
             android:layout_alignParentBottom="true"
             android:layout_alignParentRight="true"
-            android:layout_marginBottom="12dip"
             android:layout_marginRight="44dip"
-            android:background="?android:attr/dividerVertical" />
+            android:layout_marginBottom="8dip"
+            android:background="@drawable/ic_divider_dashed_holo_dark" />
 
         <ImageButton
             android:id="@+id/contact_tile_push_state"
@@ -78,14 +78,28 @@
 
         <ImageButton
             android:id="@+id/contact_tile_secondary_button"
-            android:src="@drawable/ic_tab_unselected_contacts"
+            android:src="@drawable/ic_contacts_holo_dark"
             android:background="?android:attr/selectableItemBackground"
             android:layout_height="@dimen/contact_tile_shadowbox_height"
-            android:layout_width="32dip"
+            android:layout_width="48dip"
             android:layout_alignParentBottom="true"
             android:layout_alignParentRight="true"
-            android:layout_marginLeft="8dip"
-            android:layout_marginRight="8dip" />
+            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: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>
 
diff --git a/res/layout/list_separator.xml b/res/layout/list_separator.xml
index af83584..7d57ef7 100644
--- a/res/layout/list_separator.xml
+++ b/res/layout/list_separator.xml
@@ -15,8 +15,30 @@
 -->
 
 <!-- Layout used for list separators. -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    style="?android:attr/listSeparatorTextViewStyle"
-    android:gravity="left|center_vertical"
-    android:id="@+id/header_text"
-/>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:orientation="vertical"
+    android:layout_height="32dip"
+    android:divider="?android:attr/dividerVertical"
+    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" />
+
+        <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/menu-sw580dp-w720dp/actions.xml b/res/menu-sw580dp-w720dp/actions.xml
index 4f0da2c..0b8303a 100644
--- a/res/menu-sw580dp-w720dp/actions.xml
+++ b/res/menu-sw580dp-w720dp/actions.xml
@@ -16,7 +16,7 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item
         android:id="@+id/menu_search"
-        android:icon="@android:drawable/ic_menu_search"
+        android:icon="@drawable/ic_ab_search_holo_dark"
         android:title="@string/menu_search"
         android:showAsAction="always" />
 
diff --git a/res/menu-sw580dp/actions.xml b/res/menu-sw580dp/actions.xml
index b6cdfbf..8732927 100644
--- a/res/menu-sw580dp/actions.xml
+++ b/res/menu-sw580dp/actions.xml
@@ -16,7 +16,7 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item
         android:id="@+id/menu_search"
-        android:icon="@android:drawable/ic_menu_search"
+        android:icon="@drawable/ic_ab_search_holo_dark"
         android:title="@string/menu_search"
         android:showAsAction="ifRoom" />
 
diff --git a/res/values-sw580dp-w720dp/styles.xml b/res/values-sw580dp-w720dp/styles.xml
index a6cbb9b..05ac532 100644
--- a/res/values-sw580dp-w720dp/styles.xml
+++ b/res/values-sw580dp-w720dp/styles.xml
@@ -16,6 +16,7 @@
 <resources>
     <style name="PeopleTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
+        <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
         <item name="list_item_height">66dip</item>
diff --git a/res/values-sw580dp/styles.xml b/res/values-sw580dp/styles.xml
index b9b87cf..871d566 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-sw580dp/styles.xml
@@ -16,6 +16,7 @@
 <resources>
     <style name="PeopleTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
+        <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
         <item name="list_item_height">66dip</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0005484..6e6cadb 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -95,4 +95,8 @@
 
     <!-- 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>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6d4c4b2..a137361 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -123,6 +123,7 @@
 
     <style name="PeopleTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
+        <item name="android:actionBarTabStyle">@style/ContactsActionBarTabView</item>
         <item name="android:textColorPrimary">@color/primary_text_color</item>
         <item name="android:textColorSecondary">@color/secondary_text_color</item>
         <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
@@ -160,6 +161,10 @@
         <item name="android:backgroundStacked">@drawable/ab_solid_custom_blue_inverse_holo</item>
     </style>
 
+    <style name="ContactsActionBarTabView" parent="@android:style/Widget.Holo.ActionBar.TabView">
+        <item name="android:background">@drawable/action_bar_tab</item>
+    </style>
+
     <!-- TODO: Clean up this file so themes aren't copied. -->
     <style name="GroupDetailTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar">
         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
@@ -280,8 +285,6 @@
 
     <style name="ContactTileStarred">
         <item name="android:focusable">true</item>
-        <item name="android:padding">1px</item>
-        <item name="android:background">@drawable/list_selector</item>
     </style>
 
     <style name="ContactTileStarredName">
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index 8416721..064deb5 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -30,6 +30,7 @@
 import android.content.Context;
 import android.content.Entity;
 import android.content.Entity.NamedContentValues;
+import android.content.Intent;
 import android.content.Loader;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -784,7 +785,7 @@
 
             HashMap<String, AccountType> result = new HashMap<String, AccountType>(allInvitables);
 
-            // Remove the ones that already has a raw contact in the current contact
+            // Remove the ones that already have a raw contact in the current contact
             for (Entity entity : contactData.getEntities()) {
                 final String type = entity.getEntityValues().getAsString(RawContacts.ACCOUNT_TYPE);
                 if (!TextUtils.isEmpty(type)) {
@@ -1095,12 +1096,45 @@
                     mContact.setLoadingPhoto(true);
                     new AsyncPhotoLoader().execute(mContact.getPhotoUri());
                 }
+
+                // inform the source of the data that this contact is being looked at
+                postViewNotificationToSyncAdapter();
             }
 
             deliverResult(mContact);
         }
     }
 
+    /**
+     * Posts a message to the contributing sync adapters that have opted-in, notifying them
+     * that the contact has just been loaded
+     */
+    private void postViewNotificationToSyncAdapter() {
+        Context context = getContext();
+        for (Entity entity : mContact.getEntities()) {
+            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(
+                    type, dataSet);
+            final String serviceName = accountType.getViewContactNotifyServiceClassName();
+            final String resPackageName = accountType.resPackageName;
+            if (!TextUtils.isEmpty(serviceName) && !TextUtils.isEmpty(resPackageName)) {
+                final long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
+                final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
+                final Intent intent = new Intent();
+                intent.setClassName(resPackageName, serviceName);
+                intent.setAction(Intent.ACTION_VIEW);
+                intent.setDataAndType(uri, RawContacts.CONTENT_ITEM_TYPE);
+                try {
+                    context.startService(intent);
+                } catch (Exception e) {
+                    Log.e(TAG, "Error sending message to source-app", e);
+                }
+            }
+        }
+    }
+
     private class AsyncPhotoLoader extends AsyncTask<String, Void, byte[]> {
 
         private static final int BUFFER_SIZE = 1024*16;
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index 8d3cd75..265550b 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -19,7 +19,6 @@
 import com.android.contacts.ContactLoader;
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.R;
-import com.android.contacts.activities.ContactDetailActivity;
 import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
 import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.internal.util.Objects;
@@ -29,7 +28,6 @@
 import android.app.LoaderManager;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ActivityNotFoundException;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Loader;
diff --git a/src/com/android/contacts/list/ContactTileAdapter.java b/src/com/android/contacts/list/ContactTileAdapter.java
index 0d4eb8c..cc0a184 100644
--- a/src/com/android/contacts/list/ContactTileAdapter.java
+++ b/src/com/android/contacts/list/ContactTileAdapter.java
@@ -341,6 +341,7 @@
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
         int itemViewType = getItemViewType(position);
+
         if (itemViewType == ViewTypes.DIVIDER) {
             // Checking For Divider First so not to cast convertView
             return convertView == null ? getDivider() : convertView;
@@ -353,7 +354,7 @@
             // Creating new row if needed
             contactTileRowView = new ContactTileRow(mContext, itemViewType);
         }
-        contactTileRowView.configureRow(contactList);
+        contactTileRowView.configureRow(contactList, position == getCount() - 1);
         return contactTileRowView;
     }
 
@@ -455,21 +456,21 @@
         /**
          * Configures the row to add {@link ContactEntry}s information to the views
          */
-        public void configureRow(ArrayList<ContactEntry> list) {
+        public void configureRow(ArrayList<ContactEntry> list, boolean isLastRow) {
             int columnCount = mItemViewType == ViewTypes.FREQUENT ? 1 : mColumnCount;
 
             // Adding tiles to row and filling in contact information
             for (int columnCounter = 0; columnCounter < columnCount; columnCounter++) {
                 ContactEntry entry =
                         columnCounter < list.size() ? list.get(columnCounter) : null;
-                addTileFromEntry(entry, columnCounter);
+                addTileFromEntry(entry, columnCounter, isLastRow);
             }
         }
 
-        private void addTileFromEntry(ContactEntry entry, int tileIndex) {
+        private void addTileFromEntry(ContactEntry entry, int childIndex, boolean isLastRow) {
             final ContactTileView contactTile;
 
-            if (getChildCount() <= tileIndex) {
+            if (getChildCount() <= childIndex) {
                 contactTile = (ContactTileView) inflate(mContext, mLayoutResId, null);
                 contactTile.setLayoutParams(new LinearLayout.LayoutParams(0,
                         LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
@@ -477,10 +478,15 @@
                 contactTile.setListener(mContactTileListener);
                 addView(contactTile);
             } else {
-                contactTile = (ContactTileView) getChildAt(tileIndex);
+                contactTile = (ContactTileView) getChildAt(childIndex);
             }
             contactTile.setClickable(entry != null);
             contactTile.loadFromContact(entry);
+
+            contactTile.setVerticalDividerVisibility(
+                    childIndex >= mColumnCount - 1 ? View.GONE : View.VISIBLE);
+            contactTile.setHorizontalDividerVisibility(
+                    isLastRow ? View.GONE : View.VISIBLE);
         }
     }
 
diff --git a/src/com/android/contacts/list/ContactTileView.java b/src/com/android/contacts/list/ContactTileView.java
index 4dfa876..ef9c2fb 100644
--- a/src/com/android/contacts/list/ContactTileView.java
+++ b/src/com/android/contacts/list/ContactTileView.java
@@ -49,6 +49,8 @@
     private ContactPhotoManager mPhotoManager = null;
     private ImageButton mPushState;
     private Listener mListener;
+    private View mVerticalDivider;
+    private View mHorizontalDivider;
 
     public ContactTileView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -66,6 +68,8 @@
         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);
+        mHorizontalDivider = findViewById(R.id.contact_tile_horizontal_divider);
 
         OnClickListener listener = new OnClickListener() {
             @Override
@@ -148,6 +152,14 @@
         }
     }
 
+    public void setVerticalDividerVisibility(int visibility) {
+        if (mVerticalDivider != null) mVerticalDivider.setVisibility(visibility);
+    }
+
+    public void setHorizontalDividerVisibility(int visibility) {
+        if (mHorizontalDivider != null) mHorizontalDivider.setVisibility(visibility);
+    }
+
     public void setListener(Listener listener) {
         mListener = listener;
     }
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index e652d7b..a78185f 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -113,6 +113,16 @@
         return null;
     }
 
+    /**
+     * Returns an optional service that can be launched whenever a contact is being looked at.
+     * This allows the sync adapter to provide more up-to-date information.
+     * The service class should reside in the sync adapter package as determined by
+     * {@link #resPackageName}.
+     */
+    public String getViewContactNotifyServiceClassName() {
+        return null;
+    }
+
     public CharSequence getDisplayLabel(Context context) {
         return getResourceText(context, summaryResPackageName, titleRes, accountType);
     }
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index e5af8f8..5dd4d3b 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/ExternalAccountType.java
@@ -57,6 +57,7 @@
     private static final String ATTR_CREATE_CONTACT_ACTIVITY = "createContactActivity";
     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_DATA_SET = "dataSet";
     private static final String ATTR_EXTENSION_PACKAGE_NAMES = "extensionPackageNames";
 
@@ -71,6 +72,7 @@
     private String mCreateContactActivityClassName;
     private String mInviteContactActivity;
     private String mInviteActionLabelAttribute;
+    private String mViewContactNotifyService;
     private List<String> mExtensionPackageNames;
     private int mInviteActionLabelResId;
     private String mAccountTypeLabelAttribute;
@@ -149,6 +151,11 @@
     }
 
     @Override
+    public String getViewContactNotifyServiceClassName() {
+        return mViewContactNotifyService;
+    }
+
+    @Override
     public List<String> getExtensionPackageNames() {
         return mExtensionPackageNames;
     }
@@ -193,6 +200,8 @@
                     mInviteContactActivity = value;
                 } else if (ATTR_INVITE_CONTACT_ACTION_LABEL.equals(attr)) {
                     mInviteActionLabelAttribute = value;
+                } else if (ATTR_VIEW_CONTACT_NOTIFY_SERVICE.equals(attr)) {
+                    mViewContactNotifyService = value;
                 } else if (ATTR_DATA_SET.equals(attr)) {
                     dataSet = value;
                 } else if (ATTR_EXTENSION_PACKAGE_NAMES.equals(attr)) {