Allow sync adapter to rename the "View Updates" button

Bug:5382678
Change-Id: Id848c018788d31927b27863ea86d45159aa31040
diff --git a/res/layout-sw580dp/group_source_button.xml b/res/layout-sw580dp/group_source_button.xml
index a058990..e0fe4a9 100644
--- a/res/layout-sw580dp/group_source_button.xml
+++ b/res/layout-sw580dp/group_source_button.xml
@@ -29,12 +29,12 @@
     android:padding="10dip" >
 
     <TextView
+        android:id="@android:id/title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
         android:duplicateParentState="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:text="@string/view_updates_from_group"/>
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
 
     <ImageView
         android:id="@android:id/icon"
diff --git a/res/layout-w470dp/group_source_button.xml b/res/layout-w470dp/group_source_button.xml
index 1acd510..af62c2c 100644
--- a/res/layout-w470dp/group_source_button.xml
+++ b/res/layout-w470dp/group_source_button.xml
@@ -34,12 +34,12 @@
         android:orientation="horizontal">
 
         <TextView
+            android:id="@android:id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="@color/action_bar_button_text_color"
-            android:text="@string/view_updates_from_group"
             style="@android:style/Widget.Holo.ActionBar.TabText"/>
 
         <ImageView
diff --git a/res/layout/group_source_button.xml b/res/layout/group_source_button.xml
index 49aa2db..8d09033 100644
--- a/res/layout/group_source_button.xml
+++ b/res/layout/group_source_button.xml
@@ -30,6 +30,7 @@
     android:paddingRight="16dip" >
 
     <TextView
+        android:id="@android:id/title"
         android:layout_width="0dip"
         android:layout_height="wrap_content"
         android:layout_weight="1"
@@ -37,7 +38,6 @@
         android:duplicateParentState="true"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textColor="@color/action_bar_button_text_color"
-        android:text="@string/view_updates_from_group"
         style="@android:style/Widget.Holo.ActionBar.TabText"/>
 
     <FrameLayout
diff --git a/src/com/android/contacts/group/GroupDetailDisplayUtils.java b/src/com/android/contacts/group/GroupDetailDisplayUtils.java
index bb4cd5c..da5e0e9 100644
--- a/src/com/android/contacts/group/GroupDetailDisplayUtils.java
+++ b/src/com/android/contacts/group/GroupDetailDisplayUtils.java
@@ -24,6 +24,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
+import android.widget.TextView;
 
 public class GroupDetailDisplayUtils {
 
@@ -39,13 +40,21 @@
 
     public static void bindGroupSourceView(Context context, View view, String accountTypeString,
             String dataSet) {
-        ImageView accountIcon = (ImageView) view.findViewById(android.R.id.icon);
-        if (accountIcon == null) {
-            throw new IllegalStateException("Group source view must contain view with id"
-                    + "android.R.id.icon");
-        }
         AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(context);
         AccountType accountType = accountTypeManager.getAccountType(accountTypeString, dataSet);
+
+        TextView label = (TextView) view.findViewById(android.R.id.title);
+        if (label == null) {
+            throw new IllegalStateException("Group source view must contain a TextView with id"
+                    + "android.R.id.label");
+        }
+        label.setText(accountType.getViewGroupLabel(context));
+
+        ImageView accountIcon = (ImageView) view.findViewById(android.R.id.icon);
+        if (accountIcon == null) {
+            throw new IllegalStateException("Group source view must contain an ImageView with id"
+                    + "android.R.id.icon");
+        }
         accountIcon.setImageDrawable(accountType.getDisplayIcon(context));
     }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index 21e17bd..15158dc 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.model;
 
+import com.android.contacts.R;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 import com.google.common.annotations.VisibleForTesting;
@@ -148,7 +149,14 @@
     /**
      * @return resource ID for the "invite contact" action label, or -1 if not defined.
      */
-    protected int getInviteContactActionResId(Context context) {
+    protected int getInviteContactActionResId() {
+        return -1;
+    }
+
+    /**
+     * @return resource ID for the "view group" label, or -1 if not defined.
+     */
+    protected int getViewGroupLabelResId() {
         return -1;
     }
 
@@ -174,8 +182,20 @@
      * the contact card.  (If not defined, returns null.)
      */
     public CharSequence getInviteContactActionLabel(Context context) {
-        return getResourceText(context, summaryResPackageName, getInviteContactActionResId(context),
-                "");
+        return getResourceText(context, summaryResPackageName, getInviteContactActionResId(), "");
+    }
+
+    /**
+     * Returns a label for the "view group" action. If not defined, this falls back to our
+     * own "View Updates" string
+     */
+    public CharSequence getViewGroupLabel(Context context) {
+        final CharSequence customTitle =
+                getResourceText(context, summaryResPackageName, getViewGroupLabelResId(), null);
+
+        return customTitle == null
+                ? context.getText(R.string.view_updates_from_group)
+                : customTitle;
     }
 
     /**
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index ca064c7..0518ea5 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_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_GROUP_ACTION_LABEL = "viewGroupActionLabel";
     private static final String ATTR_VIEW_STREAM_ITEM_ACTIVITY = "viewStreamItemActivity";
     private static final String ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY =
             "viewStreamItemPhotoActivity";
@@ -75,12 +76,14 @@
     private String mCreateContactActivityClassName;
     private String mInviteContactActivity;
     private String mInviteActionLabelAttribute;
+    private int mInviteActionLabelResId;
     private String mViewContactNotifyService;
     private String mViewGroupActivity;
+    private String mViewGroupLabelAttribute;
+    private int mViewGroupLabelResId;
     private String mViewStreamItemActivity;
     private String mViewStreamItemPhotoActivity;
     private List<String> mExtensionPackageNames;
-    private int mInviteActionLabelResId;
     private String mAccountTypeLabelAttribute;
     private String mAccountTypeIconAttribute;
     private boolean mInitSuccessful;
@@ -111,6 +114,8 @@
         mExtensionPackageNames = new ArrayList<String>();
         mInviteActionLabelResId = resolveExternalResId(context, mInviteActionLabelAttribute,
                 summaryResPackageName, ATTR_INVITE_CONTACT_ACTION_LABEL);
+        mViewGroupLabelResId = resolveExternalResId(context, mViewGroupLabelAttribute,
+                summaryResPackageName, ATTR_VIEW_GROUP_ACTION_LABEL);
         titleRes = resolveExternalResId(context, mAccountTypeLabelAttribute,
                 this.resPackageName, ATTR_ACCOUNT_LABEL);
         iconRes = resolveExternalResId(context, mAccountTypeIconAttribute,
@@ -167,7 +172,7 @@
     }
 
     @Override
-    protected int getInviteContactActionResId(Context context) {
+    protected int getInviteContactActionResId() {
         return mInviteActionLabelResId;
     }
 
@@ -182,6 +187,11 @@
     }
 
     @Override
+    protected int getViewGroupLabelResId() {
+        return mViewGroupLabelResId;
+    }
+
+    @Override
     public String getViewStreamItemActivity() {
         return mViewStreamItemActivity;
     }
@@ -242,6 +252,8 @@
                     mViewContactNotifyService = value;
                 } else if (ATTR_VIEW_GROUP_ACTIVITY.equals(attr)) {
                     mViewGroupActivity = value;
+                } else if (ATTR_VIEW_GROUP_ACTION_LABEL.equals(attr)) {
+                    mViewGroupLabelAttribute = value;
                 } else if (ATTR_VIEW_STREAM_ITEM_ACTIVITY.equals(attr)) {
                     mViewStreamItemActivity = value;
                 } else if (ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY.equals(attr)) {
diff --git a/tests/src/com/android/contacts/model/AccountTypeTest.java b/tests/src/com/android/contacts/model/AccountTypeTest.java
index 9f7e7a2..42fe200 100644
--- a/tests/src/com/android/contacts/model/AccountTypeTest.java
+++ b/tests/src/com/android/contacts/model/AccountTypeTest.java
@@ -69,7 +69,7 @@
                 resPackageName = packageName;
                 summaryResPackageName = packageName;
             }
-            @Override protected int getInviteContactActionResId(Context conext) {
+            @Override protected int getInviteContactActionResId() {
                 return externalResID;
             }