Merge "Check newly-created group rather than the last one"
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 4edacdf..880460b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -376,10 +376,9 @@
         <item name="android:fontFamily">sans-serif</item>
     </style>
 
-    <!-- Inherit from Theme.Material.Light.Dialog instead of Theme.Material.Light.Dialog.Alert
-        since the Alert dialog is private. They are identical anyway. -->
-    <style name="ContactsAlertDialogTheme" parent="@android:style/Theme.Material.Light.Dialog">
+    <style name="ContactsAlertDialogTheme" parent="Theme.AppCompat.Light.Dialog.MinWidth">
         <item name="android:colorAccent">@color/primary_color</item>
+        <item name="colorAccent">@color/primary_color</item>
     </style>
 
     <style name="EditKindIconStyle">
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index b9fc949..b68d34c 100755
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -133,6 +133,7 @@
     public static final int CP2_ERROR = 0;
     public static final int CONTACTS_LINKED = 1;
     public static final int CONTACTS_SPLIT = 2;
+    public static final int BAD_ARGUMENTS = 3;
 
     private static final HashSet<String> ALLOWED_DATA_COLUMNS = Sets.newHashSet(
         Data.MIMETYPE,
@@ -1155,14 +1156,17 @@
     private void splitContact(Intent intent) {
         final long rawContactIds[][] = (long[][]) intent
                 .getSerializableExtra(EXTRA_RAW_CONTACT_IDS);
+        final ResultReceiver receiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER);
         if (rawContactIds == null) {
             Log.e(TAG, "Invalid argument for splitContact request");
+            if (receiver != null) {
+                receiver.send(BAD_ARGUMENTS, new Bundle());
+            }
             return;
         }
         final int batchSize = MAX_CONTACTS_PROVIDER_BATCH_SIZE;
         final ContentResolver resolver = getContentResolver();
         final ArrayList<ContentProviderOperation> operations = new ArrayList<>(batchSize);
-        final ResultReceiver receiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER);
         for (int i = 0; i < rawContactIds.length; i++) {
             for (int j = 0; j < rawContactIds.length; j++) {
                 if (i != j) {
@@ -1295,6 +1299,9 @@
         final long[][] separatedRawContactIds = getSeparatedRawContactIds(contactIds);
         if (rawContactIds == null) {
             Log.e(TAG, "Invalid arguments for joinSeveralContacts request");
+            if (receiver != null) {
+                receiver.send(BAD_ARGUMENTS, new Bundle());
+            }
             return;
         }
 
diff --git a/src/com/android/contacts/GroupListLoader.java b/src/com/android/contacts/GroupListLoader.java
index fbb68db..5bb240f 100644
--- a/src/com/android/contacts/GroupListLoader.java
+++ b/src/com/android/contacts/GroupListLoader.java
@@ -40,6 +40,8 @@
         Groups._ID,
         Groups.TITLE,
         Groups.SUMMARY_COUNT,
+        Groups.GROUP_IS_READ_ONLY,
+        Groups.SYSTEM_ID,
     };
 
     public final static int ACCOUNT_NAME = 0;
@@ -48,16 +50,18 @@
     public final static int GROUP_ID = 3;
     public final static int TITLE = 4;
     public final static int MEMBER_COUNT = 5;
+    public final static int IS_READ_ONLY = 6;
+    public final static int SYSTEM_ID = 7;
 
     private static final Uri GROUP_LIST_URI = Groups.CONTENT_SUMMARY_URI;
 
     public GroupListLoader(Context context) {
+        // Sort groups from all accounts alphabettically and in a localized way.
         super(context,
                 GROUP_LIST_URI,
                 COLUMNS,
                 DEFAULT_SELECTION,
                 null,
-                Groups.ACCOUNT_TYPE + ", " + Groups.ACCOUNT_NAME + ", " + Groups.DATA_SET + ", " +
-                Groups.TITLE + " COLLATE NOCASE ASC");
+                Groups.TITLE + " COLLATE LOCALIZED ASC");
     }
 }
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index aa507e7..892e831 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -253,6 +253,14 @@
         mProviderStatusWatcher.addListener(this);
 
         mIsRecreatedInstance = (savedState != null);
+
+        // Use FILTER_TYPE_ALL_ACCOUNTS filter if the activity is not a re-created one.
+        // This is useful when user upgrades app while an account filter or a custom filter was
+        // stored in sharedPreference in a previous version of Contacts app.
+        final ContactListFilter filter = mIsRecreatedInstance
+                ? mContactListFilterController.getFilter() : createAllAccountsFilter();
+        persistFilterIfNeeded(filter);
+
         createViewsAndFragments(savedState);
 
         if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
@@ -401,10 +409,7 @@
 
         mAllFragment.setOnContactListActionListener(new ContactBrowserActionListener());
         mAllFragment.setCheckBoxListListener(new CheckBoxListListener());
-        final int listType =  mContactListFilterController.getFilter().filterType ==
-                ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS
-                ? ListEvent.ListType.ALL_CONTACTS : ListEvent.ListType.ACCOUNT;
-        mAllFragment.setListType(listType);
+        mAllFragment.setListType(ListEvent.ListType.ALL_CONTACTS);
 
         if (areGroupWritableAccountsAvailable() && mGroupsFragment != null) {
             mGroupsFragment.setListener(this);
@@ -513,8 +518,7 @@
             final int tabToOpen;
             switch (actionCode) {
                 case ContactsRequest.ACTION_ALL_CONTACTS:
-                    filter = ContactListFilter.createFilterWithType(
-                            ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+                    filter = createAllAccountsFilter();
                     tabToOpen = TabState.ALL;
                     break;
                 case ContactsRequest.ACTION_CONTACTS_WITH_PHONES:
@@ -925,6 +929,9 @@
         if (groupListItems != null) {
             // Add each group
             for (GroupListItem groupListItem : groupListItems) {
+                if (GroupUtil.isEmptyFFCGroup(groupListItem)) {
+                    continue;
+                }
                 final String title = groupListItem.getTitle();
                 final MenuItem menuItem =
                         subMenu.add(R.id.nav_groups_items, Menu.NONE, Menu.NONE, title);
@@ -964,6 +971,7 @@
                 public boolean onMenuItemClick(MenuItem item) {
                     final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
                     drawer.closeDrawer(GravityCompat.START);
+                    mAllFragment.setListType(ListEvent.ListType.ACCOUNT);
                     AccountFilterUtil.handleAccountFilterResult(
                             mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
                     return true;
@@ -1085,15 +1093,14 @@
             ContactListFilter currentFilter = mAllFragment.getFilter();
             if (currentFilter != null
                     && currentFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
-                filter = ContactListFilter.createFilterWithType(
-                        ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+                filter = createAllAccountsFilter();
                 setFilterAndUpdateTitle(filter);
             } else {
                 filter = ContactListFilter.createFilterWithType(
                         ContactListFilter.FILTER_TYPE_SINGLE_CONTACT);
                 setFilterAndUpdateTitle(filter, /* restoreSelectedUri */ false);
             }
-            mContactListFilterController.setContactListFilter(filter, true);
+            persistFilterIfNeeded(filter);
         }
     }
 
@@ -1266,12 +1273,7 @@
         } else if (id == R.id.nav_help) {
             HelpUtils.launchHelpAndFeedbackForMainScreen(this);
         } else if (id == R.id.nav_all_contacts) {
-            final Intent intent = new Intent();
-            final ContactListFilter filter = ContactListFilter.createFilterWithType(
-                    ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
-            intent.putExtra(AccountFilterUtil.EXTRA_CONTACT_LIST_FILTER, filter);
-            AccountFilterUtil.handleAccountFilterResult(
-                    mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
+            switchToAllContacts();
         } else if (id == R.id.nav_blocked_numbers) {
             final Intent intent = TelecomManagerUtil.createManageBlockedNumbersIntent(
                     (TelecomManager) getSystemService(Context.TELECOM_SERVICE));
@@ -1459,6 +1461,9 @@
                 Logger.logScreenView(this, ScreenType.SEARCH_EXIT);
                 Logger.logSearchEvent(mAllFragment.createSearchState());
             }
+        } else if (mContactListFilterController.getFilter().filterType !=
+                ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
+            switchToAllContacts();
         } else {
             super.onBackPressed();
         }
@@ -1538,4 +1543,22 @@
             getSupportActionBar().setTitle(actionBarTitle);
         }
     }
+
+    private void switchToAllContacts() {
+        final Intent intent = new Intent();
+        final ContactListFilter filter = createAllAccountsFilter();
+        intent.putExtra(AccountFilterUtil.EXTRA_CONTACT_LIST_FILTER, filter);
+        AccountFilterUtil.handleAccountFilterResult(
+                mContactListFilterController, AppCompatActivity.RESULT_OK, intent);
+    }
+
+    private ContactListFilter createAllAccountsFilter() {
+        return ContactListFilter.createFilterWithType(ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+    }
+
+    // Persist filter only when it's of the type FILTER_TYPE_ALL_ACCOUNTS.
+    private void persistFilterIfNeeded(ContactListFilter filter) {
+        mContactListFilterController.setContactListFilter(filter, /* persistent */
+                filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+    }
 }
diff --git a/src/com/android/contacts/group/GroupListItem.java b/src/com/android/contacts/group/GroupListItem.java
index a06ec38..f2359b6 100644
--- a/src/com/android/contacts/group/GroupListItem.java
+++ b/src/com/android/contacts/group/GroupListItem.java
@@ -27,9 +27,12 @@
     private final String mTitle;
     private final boolean mIsFirstGroupInAccount;
     private final int mMemberCount;
+    private final boolean mIsReadOnly;
+    private final String mSystemId;
 
     public GroupListItem(String accountName, String accountType, String dataSet, long groupId,
-            String title, boolean isFirstGroupInAccount, int memberCount) {
+            String title, boolean isFirstGroupInAccount, int memberCount, boolean isReadOnly,
+            String systemId) {
         mAccountName = accountName;
         mAccountType = accountType;
         mDataSet = dataSet;
@@ -37,6 +40,8 @@
         mTitle = title;
         mIsFirstGroupInAccount = isFirstGroupInAccount;
         mMemberCount = memberCount;
+        mIsReadOnly = isReadOnly;
+        mSystemId = systemId;
     }
 
     public String getAccountName() {
@@ -70,4 +75,12 @@
     public boolean isFirstGroupInAccount() {
         return mIsFirstGroupInAccount;
     }
+
+    public boolean isReadOnly() {
+        return mIsReadOnly;
+    }
+
+    public String getSystemId() {
+        return mSystemId;
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/group/GroupNameEditDialogFragment.java b/src/com/android/contacts/group/GroupNameEditDialogFragment.java
index bc877a2..8fcd63d 100644
--- a/src/com/android/contacts/group/GroupNameEditDialogFragment.java
+++ b/src/com/android/contacts/group/GroupNameEditDialogFragment.java
@@ -15,7 +15,6 @@
  */
 package com.android.contacts.group;
 
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.app.FragmentManager;
@@ -23,10 +22,10 @@
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
-import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
@@ -91,9 +90,7 @@
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         // Build a dialog with two buttons and a view of a single EditText input field
-        final ContextThemeWrapper context = new ContextThemeWrapper(getActivity(),
-                android.R.style.Theme_Holo_Light_Dialog_MinWidth);
-        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
                 .setTitle(mIsInsert
                         ? R.string.group_name_dialog_insert_title
                         : R.string.group_name_dialog_update_title)
diff --git a/src/com/android/contacts/group/GroupUtil.java b/src/com/android/contacts/group/GroupUtil.java
index a45cdb5..2057a94 100644
--- a/src/com/android/contacts/group/GroupUtil.java
+++ b/src/com/android/contacts/group/GroupUtil.java
@@ -22,14 +22,20 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.ContactsContract.Groups;
+import android.text.TextUtils;
 import android.widget.ImageView;
 
 import com.android.contacts.GroupListLoader;
 import com.android.contacts.activities.GroupMembersActivity;
 import com.android.contacts.common.ContactPhotoManager;
 import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
+import com.android.contacts.common.model.account.GoogleAccountType;
 import com.google.common.base.Objects;
 
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * Group utility methods.
  */
@@ -38,6 +44,10 @@
     private static final String LEGACY_CONTACTS_AUTHORITY = "contacts";
     private static final String LEGACY_CONTACTS_URI = "content://contacts/groups";
 
+    // System IDs of FFC groups in Google accounts
+    private static final Set<String> FFC_GROUPS =
+            new HashSet(Arrays.asList("Friends", "Family", "Coworkers"));
+
     private GroupUtil() {
     }
 
@@ -52,6 +62,8 @@
         long groupId = cursor.getLong(GroupListLoader.GROUP_ID);
         String title = cursor.getString(GroupListLoader.TITLE);
         int memberCount = cursor.getInt(GroupListLoader.MEMBER_COUNT);
+        boolean isReadOnly = cursor.getInt(GroupListLoader.IS_READ_ONLY) == 1;
+        String systemId = cursor.getString(GroupListLoader.SYSTEM_ID);
 
         // Figure out if this is the first group for this account name / account type pair by
         // checking the previous entry. This is to determine whether or not we need to display an
@@ -71,7 +83,7 @@
         }
 
         return new GroupListItem(accountName, accountType, dataSet, groupId, title,
-                isFirstGroupInAccount, memberCount);
+                isFirstGroupInAccount, memberCount, isReadOnly, systemId);
     }
 
     /**
@@ -122,4 +134,19 @@
         final Uri legacyContentUri = Uri.parse(LEGACY_CONTACTS_URI);
         return ContentUris.withAppendedId(legacyContentUri, groupId);
     }
+
+    /**
+     * Returns true if it's an empty and read-only group of a Google account and the system ID of
+     * the group is one of "Friends", "Family" and "Coworkers".
+     */
+    public static boolean isEmptyFFCGroup(GroupListItem groupListItem) {
+        return GoogleAccountType.ACCOUNT_TYPE.equals(groupListItem.getAccountType())
+                && groupListItem.isReadOnly()
+                && isSystemIdFFC(groupListItem.getSystemId())
+                && (groupListItem.getMemberCount() <= 0);
+    }
+
+    private static boolean isSystemIdFFC(String systemId) {
+        return !TextUtils.isEmpty(systemId) && FFC_GROUPS.contains(systemId);
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index 436c3a2..2060068 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -216,7 +216,11 @@
 
         mFilter = filter;
         mLastSelectedPosition = -1;
-        saveFilter();
+
+        if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) {
+            saveFilter();
+        }
+
         if (restoreSelectedUri) {
             mSelectedContactUri = null;
             restoreSelectedUri(true);