Merge "Bring account view up to spec (E2)" into ub-contactsdialer-f-dev
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index b68d34c..8683809 100755
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -1142,7 +1142,8 @@
 
     /**
      * Creates an intent that can be sent to this service to split a contact into it's constituent
-     * pieces.
+     * pieces. This will set the raw contact ids to TYPE_AUTOMATIC for AggregationExceptions so
+     * they may be re-merged by the auto-aggregator.
      */
     public static Intent createSplitContactIntent(Context context, long[][] rawContactIds,
             ResultReceiver receiver) {
@@ -1193,7 +1194,7 @@
     }
 
     /**
-     * Adds insert aggregation exception ContentProviderOperations between {@param rawContactIds1}
+     * Insert aggregation exception ContentProviderOperations between {@param rawContactIds1}
      * and {@param rawContactIds2} to {@param operations}.
      * @return false if an error occurred, true otherwise.
      */
@@ -1546,13 +1547,13 @@
     }
 
     /**
-     * Construct a {@link AggregationExceptions#TYPE_KEEP_SEPARATE} ContentProviderOperation.
+     * Construct a {@link AggregationExceptions#TYPE_AUTOMATIC} ContentProviderOperation.
      */
     private void buildSplitContactDiff(ArrayList<ContentProviderOperation> operations,
             long rawContactId1, long rawContactId2) {
         final Builder builder =
                 ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
-        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_SEPARATE);
+        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_AUTOMATIC);
         builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1);
         builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2);
         operations.add(builder.build());
diff --git a/src/com/android/contacts/ContactsDrawerActivity.java b/src/com/android/contacts/ContactsDrawerActivity.java
index a12d0e1..6ae6a59 100644
--- a/src/com/android/contacts/ContactsDrawerActivity.java
+++ b/src/com/android/contacts/ContactsDrawerActivity.java
@@ -43,6 +43,7 @@
 import android.view.SubMenu;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.LinearLayout;
 import android.widget.Toast;
 
 import com.android.contacts.activities.GroupMembersActivity;
@@ -53,6 +54,7 @@
 import com.android.contacts.common.list.ContactListFilter;
 import com.android.contacts.common.list.ContactListFilterController;
 import com.android.contacts.common.model.AccountTypeManager;
+import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.preference.ContactsPreferenceActivity;
 import com.android.contacts.common.util.AccountFilterUtil;
@@ -488,6 +490,16 @@
             menuItem.setIcon(filter.icon);
             // Get rid of the default menu item overlay and show original account icons.
             menuItem.getIcon().setColorFilter(Color.TRANSPARENT, PorterDuff.Mode.SRC_ATOP);
+            // Create a dummy action view to attach extra hidden content description to the menuItem
+            // for Talkback. We want Talkback to read out the account type but not have it be part
+            // of the menuItem title.
+            final AccountType account = AccountTypeManager.getInstance(this)
+                    .getAccountType(filter.accountType, filter.dataSet);
+            LinearLayout view = (LinearLayout) LayoutInflater.from(this)
+                    .inflate(R.layout.account_type_info, null);
+            view.setContentDescription(account.getDisplayLabel(this));
+            view.setVisibility(View.VISIBLE);
+            menuItem.setActionView(view);
         }
 
         if (getContactListFilter() != null) {
diff --git a/src/com/android/contacts/activities/GroupMembersActivity.java b/src/com/android/contacts/activities/GroupMembersActivity.java
index edd93dd..f8efa85 100644
--- a/src/com/android/contacts/activities/GroupMembersActivity.java
+++ b/src/com/android/contacts/activities/GroupMembersActivity.java
@@ -25,7 +25,6 @@
 import android.os.Bundle;
 import android.provider.ContactsContract.RawContacts;
 import android.support.v4.view.GravityCompat;
-import android.support.v7.app.ActionBar;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
diff --git a/src/com/android/contacts/group/GroupMembersAdapter.java b/src/com/android/contacts/group/GroupMembersAdapter.java
index 622db67..af1f61e 100644
--- a/src/com/android/contacts/group/GroupMembersAdapter.java
+++ b/src/com/android/contacts/group/GroupMembersAdapter.java
@@ -73,8 +73,8 @@
 
     public GroupMembersAdapter(Context context) {
         super(context, GroupMembersQuery.CONTACT_ID);
+
         mUnknownNameText = context.getText(R.string.missing_name);
-        setSectionHeaderDisplayEnabled(true);
     }
 
     /** Sets the ID of the group whose members will be displayed. */
@@ -83,7 +83,7 @@
     }
 
     /** Returns the lookup Uri for the contact at the given position in the underlying cursor. */
-    public Uri getContactLookupUri(int position) {
+    public Uri getContactUri(int position) {
         final Cursor cursor = (Cursor) getItem(position);
         final long contactId = cursor.getLong(GroupMembersQuery.CONTACT_ID);
         final String lookupKey = cursor.getString(GroupMembersQuery.CONTACT_LOOKUP_KEY);
@@ -135,13 +135,6 @@
         return ((Cursor) getItem(position)).getString(GroupMembersQuery.CONTACT_DISPLAY_NAME);
     }
 
-    public Uri getContactUri(int position) {
-        final Cursor cursor = (Cursor) getItem(position);
-        final long contactId = cursor.getLong(GroupMembersQuery.CONTACT_ID);
-        final String lookupKey = cursor.getString(GroupMembersQuery.CONTACT_LOOKUP_KEY);
-        return Contacts.getLookupUri(contactId, lookupKey);
-    }
-
     @Override
     protected ContactListItemView newView(Context context, int partition, Cursor cursor,
             int position, ViewGroup parent) {
@@ -155,7 +148,6 @@
     protected void bindView(View v, int partition, Cursor cursor, int position) {
         super.bindView(v, partition, cursor, position);
         final ContactListItemView view = (ContactListItemView) v;
-        bindViewId(view, cursor, GroupMembersQuery.CONTACT_ID);
         bindSectionHeaderAndDivider(view, position);
         bindName(view, cursor);
         bindPhoto(view, cursor);
diff --git a/src/com/android/contacts/group/GroupMembersFragment.java b/src/com/android/contacts/group/GroupMembersFragment.java
index 266e5fc..a187510 100644
--- a/src/com/android/contacts/group/GroupMembersFragment.java
+++ b/src/com/android/contacts/group/GroupMembersFragment.java
@@ -17,7 +17,6 @@
 
 import android.app.Activity;
 import android.app.LoaderManager.LoaderCallbacks;
-import android.content.Context;
 import android.content.CursorLoader;
 import android.content.Loader;
 import android.content.res.Configuration;
@@ -162,8 +161,15 @@
 
         @Override
         public boolean moveToPosition(int position) {
-            if (position >= mCount || position < 0) return false;
-            return super.moveToPosition(mIndex[position]);
+            if (position >= mCount) {
+                mPos = mCount;
+                return false;
+            } else if (position < 0) {
+                mPos = -1;
+                return false;
+            }
+            mPos = mIndex[position];
+            return super.moveToPosition(mPos);
         }
 
         @Override
@@ -397,8 +403,7 @@
             return;
         }
         if (mListener != null) {
-            final Uri contactLookupUri = getAdapter().getContactLookupUri(position);
-            mListener.onGroupMemberListItemClicked(position, contactLookupUri);
+            mListener.onGroupMemberListItemClicked(position, uri);
         }
     }
 
diff --git a/src/com/android/contacts/list/GroupMemberPickerFragment.java b/src/com/android/contacts/list/GroupMemberPickerFragment.java
index 519a6a9..6f4d0c0 100644
--- a/src/com/android/contacts/list/GroupMemberPickerFragment.java
+++ b/src/com/android/contacts/list/GroupMemberPickerFragment.java
@@ -148,8 +148,15 @@
 
         @Override
         public boolean moveToPosition(int position) {
-            if (position >= mCount || position < 0) return false;
-            return super.moveToPosition(mIndex[position]);
+            if (position >= mCount) {
+                mPos = mCount;
+                return false;
+            } else if (position < 0) {
+                mPos = -1;
+                return false;
+            }
+            mPos = mIndex[position];
+            return super.moveToPosition(mPos);
         }
 
         @Override
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 7a01ede..16f137e 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -958,21 +958,25 @@
         // 2. App doesn't have permission, user denied it previously.
         // 3. App has permission.
         // Permission explanation card is displayed only for case 1.
+        final boolean hasTelephonyFeature =
+                getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+
         final boolean hasCalendarPermission = PermissionsUtil.hasPermission(
                 this, Manifest.permission.READ_CALENDAR);
-        final boolean hasSMSPermission = PermissionsUtil.hasPermission(
-                this, Manifest.permission.READ_SMS);
+        final boolean hasSMSPermission = hasTelephonyFeature
+                && PermissionsUtil.hasPermission(this, Manifest.permission.READ_SMS);
 
         final boolean wasCalendarPermissionDenied =
                 ActivityCompat.shouldShowRequestPermissionRationale(
                         this, Manifest.permission.READ_CALENDAR);
         final boolean wasSMSPermissionDenied =
-                ActivityCompat.shouldShowRequestPermissionRationale(
+                hasTelephonyFeature && ActivityCompat.shouldShowRequestPermissionRationale(
                         this, Manifest.permission.READ_SMS);
 
         final boolean shouldDisplayCalendarMessage =
                 !hasCalendarPermission && !wasCalendarPermissionDenied;
-        final boolean shouldDisplaySMSMessage = !hasSMSPermission && !wasSMSPermissionDenied;
+        final boolean shouldDisplaySMSMessage =
+                hasTelephonyFeature && !hasSMSPermission && !wasSMSPermissionDenied;
         mShouldShowPermissionExplanation = shouldDisplayCalendarMessage || shouldDisplaySMSMessage;
 
         if (shouldDisplayCalendarMessage && shouldDisplaySMSMessage) {