1758f56580b973894213569b61b1ae23b293071c2Walter Jang/*
2758f56580b973894213569b61b1ae23b293071c2Walter Jang * Copyright (C) 2016 The Android Open Source Project
3758f56580b973894213569b61b1ae23b293071c2Walter Jang *
4758f56580b973894213569b61b1ae23b293071c2Walter Jang * Licensed under the Apache License, Version 2.0 (the "License");
5758f56580b973894213569b61b1ae23b293071c2Walter Jang * you may not use this file except in compliance with the License.
6758f56580b973894213569b61b1ae23b293071c2Walter Jang * You may obtain a copy of the License at
7758f56580b973894213569b61b1ae23b293071c2Walter Jang *
8758f56580b973894213569b61b1ae23b293071c2Walter Jang *      http://www.apache.org/licenses/LICENSE-2.0
9758f56580b973894213569b61b1ae23b293071c2Walter Jang *
10758f56580b973894213569b61b1ae23b293071c2Walter Jang * Unless required by applicable law or agreed to in writing, software
11758f56580b973894213569b61b1ae23b293071c2Walter Jang * distributed under the License is distributed on an "AS IS" BASIS,
12758f56580b973894213569b61b1ae23b293071c2Walter Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13758f56580b973894213569b61b1ae23b293071c2Walter Jang * See the License for the specific language governing permissions and
14758f56580b973894213569b61b1ae23b293071c2Walter Jang * limitations under the License.
15758f56580b973894213569b61b1ae23b293071c2Walter Jang */
16758f56580b973894213569b61b1ae23b293071c2Walter Jang
17758f56580b973894213569b61b1ae23b293071c2Walter Jangpackage com.android.contacts.group;
18758f56580b973894213569b61b1ae23b293071c2Walter Jang
199970f301c1944c3d8155e1718ac34abbe8f69199Sean Midfordimport android.app.Fragment;
209970f301c1944c3d8155e1718ac34abbe8f69199Sean Midfordimport android.content.ContentResolver;
21758f56580b973894213569b61b1ae23b293071c2Walter Jangimport android.content.Context;
22758f56580b973894213569b61b1ae23b293071c2Walter Jangimport android.content.Intent;
23758f56580b973894213569b61b1ae23b293071c2Walter Jangimport android.database.Cursor;
24758f56580b973894213569b61b1ae23b293071c2Walter Jangimport android.net.Uri;
2538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wangimport android.os.Bundle;
26ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midfordimport android.provider.ContactsContract;
2738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wangimport android.provider.ContactsContract.Contacts;
28758f56580b973894213569b61b1ae23b293071c2Walter Jangimport android.provider.ContactsContract.Groups;
293fafbb29c949ba998af2104451859ed81b06f663Wenyi Wangimport android.text.TextUtils;
30758f56580b973894213569b61b1ae23b293071c2Walter Jang
310a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.ContactsUtils;
32758f56580b973894213569b61b1ae23b293071c2Walter Jangimport com.android.contacts.GroupListLoader;
336927bf35fa2d1b4261e25c46bcd4951cd7b3208aWenyi Wangimport com.android.contacts.activities.ContactSelectionActivity;
3469c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.list.ContactsSectionIndexer;
35d8effeb5adf3fc9d81e552c41450400eb86076c7yaoluimport com.android.contacts.list.UiIntentActions;
360a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.model.account.GoogleAccountType;
37758f56580b973894213569b61b1ae23b293071c2Walter Jang
3838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wangimport java.util.ArrayList;
393fafbb29c949ba998af2104451859ed81b06f663Wenyi Wangimport java.util.Arrays;
403fafbb29c949ba998af2104451859ed81b06f663Wenyi Wangimport java.util.HashSet;
4138860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wangimport java.util.List;
423fafbb29c949ba998af2104451859ed81b06f663Wenyi Wangimport java.util.Set;
433fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang
44758f56580b973894213569b61b1ae23b293071c2Walter Jang/**
45758f56580b973894213569b61b1ae23b293071c2Walter Jang * Group utility methods.
46758f56580b973894213569b61b1ae23b293071c2Walter Jang */
47758f56580b973894213569b61b1ae23b293071c2Walter Jangpublic final class GroupUtil {
48758f56580b973894213569b61b1ae23b293071c2Walter Jang
495c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai    public final static String ALL_GROUPS_SELECTION =
505c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai            Groups.ACCOUNT_TYPE + " NOT NULL AND " + Groups.ACCOUNT_NAME + " NOT NULL AND "
515c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                    + Groups.DELETED + "=0";
525c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai
535c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai    public final static String DEFAULT_SELECTION = ALL_GROUPS_SELECTION + " AND "
545c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai            + Groups.AUTO_ADD + "=0 AND " + Groups.FAVORITES + "=0";
555c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai
566927bf35fa2d1b4261e25c46bcd4951cd7b3208aWenyi Wang    public static final String ACTION_ADD_TO_GROUP = "addToGroup";
57cc8f272af38bd46710b8186424caf515215f2582Wenyi Wang    public static final String ACTION_CREATE_GROUP = "createGroup";
58cc8f272af38bd46710b8186424caf515215f2582Wenyi Wang    public static final String ACTION_DELETE_GROUP = "deleteGroup";
596927bf35fa2d1b4261e25c46bcd4951cd7b3208aWenyi Wang    public static final String ACTION_REMOVE_FROM_GROUP = "removeFromGroup";
60cc8f272af38bd46710b8186424caf515215f2582Wenyi Wang    public static final String ACTION_SWITCH_GROUP = "switchGroup";
61cc8f272af38bd46710b8186424caf515215f2582Wenyi Wang    public static final String ACTION_UPDATE_GROUP = "updateGroup";
626927bf35fa2d1b4261e25c46bcd4951cd7b3208aWenyi Wang
639970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford    public static final int RESULT_SEND_TO_SELECTION = 100;
649970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford
653fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang    // System IDs of FFC groups in Google accounts
663fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang    private static final Set<String> FFC_GROUPS =
673fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang            new HashSet(Arrays.asList("Friends", "Family", "Coworkers"));
683fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang
69758f56580b973894213569b61b1ae23b293071c2Walter Jang    private GroupUtil() {
70758f56580b973894213569b61b1ae23b293071c2Walter Jang    }
71758f56580b973894213569b61b1ae23b293071c2Walter Jang
72758f56580b973894213569b61b1ae23b293071c2Walter Jang    /** Returns a {@link GroupListItem} read from the given cursor and position. */
73b8b86d1a272b313fd2b3ff9e324ce014f24aa44dWenyi Wang    public static GroupListItem getGroupListItem(Cursor cursor, int position) {
74758f56580b973894213569b61b1ae23b293071c2Walter Jang        if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(position)) {
75758f56580b973894213569b61b1ae23b293071c2Walter Jang            return null;
76758f56580b973894213569b61b1ae23b293071c2Walter Jang        }
77758f56580b973894213569b61b1ae23b293071c2Walter Jang        String accountName = cursor.getString(GroupListLoader.ACCOUNT_NAME);
78758f56580b973894213569b61b1ae23b293071c2Walter Jang        String accountType = cursor.getString(GroupListLoader.ACCOUNT_TYPE);
79758f56580b973894213569b61b1ae23b293071c2Walter Jang        String dataSet = cursor.getString(GroupListLoader.DATA_SET);
80758f56580b973894213569b61b1ae23b293071c2Walter Jang        long groupId = cursor.getLong(GroupListLoader.GROUP_ID);
81758f56580b973894213569b61b1ae23b293071c2Walter Jang        String title = cursor.getString(GroupListLoader.TITLE);
82758f56580b973894213569b61b1ae23b293071c2Walter Jang        int memberCount = cursor.getInt(GroupListLoader.MEMBER_COUNT);
833fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang        boolean isReadOnly = cursor.getInt(GroupListLoader.IS_READ_ONLY) == 1;
843fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang        String systemId = cursor.getString(GroupListLoader.SYSTEM_ID);
85758f56580b973894213569b61b1ae23b293071c2Walter Jang
86758f56580b973894213569b61b1ae23b293071c2Walter Jang        // Figure out if this is the first group for this account name / account type pair by
87758f56580b973894213569b61b1ae23b293071c2Walter Jang        // checking the previous entry. This is to determine whether or not we need to display an
88758f56580b973894213569b61b1ae23b293071c2Walter Jang        // account header in this item.
89758f56580b973894213569b61b1ae23b293071c2Walter Jang        int previousIndex = position - 1;
90758f56580b973894213569b61b1ae23b293071c2Walter Jang        boolean isFirstGroupInAccount = true;
91758f56580b973894213569b61b1ae23b293071c2Walter Jang        if (previousIndex >= 0 && cursor.moveToPosition(previousIndex)) {
92758f56580b973894213569b61b1ae23b293071c2Walter Jang            String previousGroupAccountName = cursor.getString(GroupListLoader.ACCOUNT_NAME);
93758f56580b973894213569b61b1ae23b293071c2Walter Jang            String previousGroupAccountType = cursor.getString(GroupListLoader.ACCOUNT_TYPE);
94758f56580b973894213569b61b1ae23b293071c2Walter Jang            String previousGroupDataSet = cursor.getString(GroupListLoader.DATA_SET);
95758f56580b973894213569b61b1ae23b293071c2Walter Jang
96dd2d8e27d8548893122c469bd1b68d5117fc5318Walter Jang            if (TextUtils.equals(accountName, previousGroupAccountName)
97dd2d8e27d8548893122c469bd1b68d5117fc5318Walter Jang                    && TextUtils.equals(accountType, previousGroupAccountType)
98dd2d8e27d8548893122c469bd1b68d5117fc5318Walter Jang                    && TextUtils.equals(dataSet, previousGroupDataSet)) {
99758f56580b973894213569b61b1ae23b293071c2Walter Jang                isFirstGroupInAccount = false;
100758f56580b973894213569b61b1ae23b293071c2Walter Jang            }
101758f56580b973894213569b61b1ae23b293071c2Walter Jang        }
102758f56580b973894213569b61b1ae23b293071c2Walter Jang
103758f56580b973894213569b61b1ae23b293071c2Walter Jang        return new GroupListItem(accountName, accountType, dataSet, groupId, title,
1043fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang                isFirstGroupInAccount, memberCount, isReadOnly, systemId);
105758f56580b973894213569b61b1ae23b293071c2Walter Jang    }
106758f56580b973894213569b61b1ae23b293071c2Walter Jang
1079970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford    public static List<String> getSendToDataForIds(Context context, long[] ids, String scheme) {
1089970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        final List<String> items = new ArrayList<>();
1099970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        final String sIds = GroupUtil.convertArrayToString(ids);
1109970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        final String select = (ContactsUtils.SCHEME_MAILTO.equals(scheme)
1119970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                ? GroupMembersFragment.Query.EMAIL_SELECTION
1129970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                + " AND " + ContactsContract.CommonDataKinds.Email._ID + " IN (" + sIds + ")"
1139970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                : GroupMembersFragment.Query.PHONE_SELECTION
1149970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                + " AND " + ContactsContract.CommonDataKinds.Phone._ID + " IN (" + sIds + ")");
1159970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        final ContentResolver contentResolver = context.getContentResolver();
1169970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        final Cursor cursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,
1179970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                ContactsUtils.SCHEME_MAILTO.equals(scheme)
1189970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                        ? GroupMembersFragment.Query.EMAIL_PROJECTION
1199970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                        : GroupMembersFragment.Query.PHONE_PROJECTION,
1209970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                select, null, null);
1219970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford
1229970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        if (cursor == null) {
1239970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford            return items;
1249970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        }
1259970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford
1269970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        try {
1279970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford            cursor.moveToPosition(-1);
1289970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford            while (cursor.moveToNext()) {
1299970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                final String data = cursor.getString(GroupMembersFragment.Query.DATA1);
1309970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford
1319970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                if (!TextUtils.isEmpty(data)) {
1329970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                    items.add(data);
1339970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                }
1349970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford            }
1359970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        } finally {
1369970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford            cursor.close();
1379970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        }
1389970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford
1399970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        return items;
1409970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford    }
1419970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford
142ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    /** Returns an Intent to send emails/phones to some activity/app */
1439970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford    public static void startSendToSelectionActivity(
1449970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford            Fragment fragment, String itemsList, String sendScheme, String title) {
145ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        final Intent intent = new Intent(Intent.ACTION_SENDTO,
146ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford                Uri.fromParts(sendScheme, itemsList, null));
1479970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford        fragment.startActivityForResult(
1489970f301c1944c3d8155e1718ac34abbe8f69199Sean Midford                Intent.createChooser(intent, title), RESULT_SEND_TO_SELECTION);
149ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    }
150ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford
151ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    /** Returns an Intent to pick emails/phones to send to selection (or group) */
1524b2ccd27dbb05d7cc1d340ce18182ccb2b9a3326Sean Midford    public static Intent createSendToSelectionPickerIntent(Context context, long[] ids,
1534b2ccd27dbb05d7cc1d340ce18182ccb2b9a3326Sean Midford            long[] defaultSelection, String sendScheme, String title) {
154ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        final Intent intent = new Intent(context, ContactSelectionActivity.class);
155ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        intent.setAction(UiIntentActions.ACTION_SELECT_ITEMS);
156ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        intent.setType(ContactsUtils.SCHEME_MAILTO.equals(sendScheme)
157ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford                ? ContactsContract.CommonDataKinds.Email.CONTENT_TYPE
158ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford                : ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
1594b2ccd27dbb05d7cc1d340ce18182ccb2b9a3326Sean Midford        intent.putExtra(UiIntentActions.SELECTION_ITEM_LIST, ids);
1604b2ccd27dbb05d7cc1d340ce18182ccb2b9a3326Sean Midford        intent.putExtra(UiIntentActions.SELECTION_DEFAULT_SELECTION, defaultSelection);
161b460f44f6517f269bac35f339f57e603669f45d7Sean Midford        intent.putExtra(UiIntentActions.SELECTION_SEND_SCHEME, sendScheme);
162b460f44f6517f269bac35f339f57e603669f45d7Sean Midford        intent.putExtra(UiIntentActions.SELECTION_SEND_TITLE, title);
163b460f44f6517f269bac35f339f57e603669f45d7Sean Midford
164ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        return intent;
165ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    }
166ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford
167d8effeb5adf3fc9d81e552c41450400eb86076c7yaolu    /** Returns an Intent to pick contacts to add to a group. */
16841c6886cabf68370f160ccd68d173bd6a59a1a07John Shao    public static Intent createPickMemberIntent(Context context,
169428824eaca7ed60c14add0a1d45edfe4535059bbWalter Jang            GroupMetaData groupMetaData, ArrayList<String> memberContactIds) {
1706927bf35fa2d1b4261e25c46bcd4951cd7b3208aWenyi Wang        final Intent intent = new Intent(context, ContactSelectionActivity.class);
17141c6886cabf68370f160ccd68d173bd6a59a1a07John Shao        intent.setAction(Intent.ACTION_PICK);
1721110d678aee0b1967898e83334a63df49a7e30f6Walter Jang        intent.setType(Groups.CONTENT_TYPE);
173428824eaca7ed60c14add0a1d45edfe4535059bbWalter Jang        intent.putExtra(UiIntentActions.GROUP_ACCOUNT_NAME, groupMetaData.accountName);
174428824eaca7ed60c14add0a1d45edfe4535059bbWalter Jang        intent.putExtra(UiIntentActions.GROUP_ACCOUNT_TYPE, groupMetaData.accountType);
175428824eaca7ed60c14add0a1d45edfe4535059bbWalter Jang        intent.putExtra(UiIntentActions.GROUP_ACCOUNT_DATA_SET, groupMetaData.dataSet);
176d8effeb5adf3fc9d81e552c41450400eb86076c7yaolu        intent.putExtra(UiIntentActions.GROUP_CONTACT_IDS, memberContactIds);
177d8effeb5adf3fc9d81e552c41450400eb86076c7yaolu        return intent;
178d8effeb5adf3fc9d81e552c41450400eb86076c7yaolu    }
179d8effeb5adf3fc9d81e552c41450400eb86076c7yaolu
180ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    public static String convertArrayToString(long[] list) {
181ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        if (list == null || list.length == 0) return "";
182ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        return Arrays.toString(list).replace("[", "").replace("]", "");
183ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    }
184ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford
185ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    public static long[] convertLongSetToLongArray(Set<Long> set) {
186ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        final Long[] contactIds = set.toArray(new Long[set.size()]);
187ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        final long[] result = new long[contactIds.length];
188ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        for (int i = 0; i < contactIds.length; i++) {
189ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford            result[i] = contactIds[i];
190ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        }
191ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        return result;
192ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    }
193ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford
194ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    public static long[] convertStringSetToLongArray(Set<String> set) {
195ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        final String[] contactIds = set.toArray(new String[set.size()]);
196ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        final long[] result = new long[contactIds.length];
197ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        for (int i = 0; i < contactIds.length; i++) {
198ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford            try {
199ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford                result[i] = Long.parseLong(contactIds[i]);
200ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford            } catch (NumberFormatException e) {
201ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford                result[i] = -1;
202ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford            }
203ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        }
204ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford        return result;
205ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford    }
206ff6f1bb6782fe92b8745ef4acb6c622fef3d0cbcSean Midford
2070680a31c87d083eca56ef6093de54bbb3b5c2d27Walter Jang    /**
208f9dd12948a7844ddcf5edb8778d7edbf50dd0e82John Shao     * Returns true if it's an empty and read-only group and the system ID of
2093fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang     * the group is one of "Friends", "Family" and "Coworkers".
2103fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang     */
2113fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang    public static boolean isEmptyFFCGroup(GroupListItem groupListItem) {
212f9dd12948a7844ddcf5edb8778d7edbf50dd0e82John Shao        return groupListItem.isReadOnly()
2133fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang                && isSystemIdFFC(groupListItem.getSystemId())
2143fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang                && (groupListItem.getMemberCount() <= 0);
2153fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang    }
2163fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang
2173fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang    private static boolean isSystemIdFFC(String systemId) {
2183fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang        return !TextUtils.isEmpty(systemId) && FFC_GROUPS.contains(systemId);
2193fafbb29c949ba998af2104451859ed81b06f663Wenyi Wang    }
2209afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang
2219afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang    /**
2227967545e62b473503473b2c9e127cef405f67201Wenyi Wang     * Returns true the URI is a group URI.
2237967545e62b473503473b2c9e127cef405f67201Wenyi Wang     */
2247967545e62b473503473b2c9e127cef405f67201Wenyi Wang    public static boolean isGroupUri(Uri uri) {
2257967545e62b473503473b2c9e127cef405f67201Wenyi Wang        return  uri != null && uri.toString().startsWith(Groups.CONTENT_URI.toString());
2267967545e62b473503473b2c9e127cef405f67201Wenyi Wang    }
2277967545e62b473503473b2c9e127cef405f67201Wenyi Wang
2287967545e62b473503473b2c9e127cef405f67201Wenyi Wang    /**
2299afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang     * Sort groups alphabetically and in a localized way.
2309afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang     */
2319afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang    public static String getGroupsSortOrder() {
2329afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang        return Groups.TITLE + " COLLATE LOCALIZED ASC";
2339afaddec062bc1c9f3d7bb30992d70198fbe0840Wenyi Wang    }
23438860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang
23538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    /**
23638860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang     * The sum of the last element in counts[] and the last element in positions[] is the total
23738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang     * number of remaining elements in cursor. If count is more than what's in the indexer now,
23838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang     * then we don't need to trim.
23938860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang     */
24038860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    public static boolean needTrimming(int count, int[] counts, int[] positions) {
24138860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        // The sum of the last element in counts[] and the last element in positions[] is
24238860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        // the total number of remaining elements in cursor. If mCount is more than
24338860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        // what's in the indexer now, then we don't need to trim.
24438860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        return positions.length > 0 && counts.length > 0
24538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                && count <= (counts[counts.length - 1] + positions[positions.length - 1]);
24638860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    }
24738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang
24838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    /**
24938860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang     * Update Bundle extras so as to update indexer.
25038860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang     */
25138860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    public static void updateBundle(Bundle bundle, ContactsSectionIndexer indexer,
25238860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            List<Integer> subscripts, String[] sections, int[] counts) {
25338860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        for (int i : subscripts) {
25438860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            final int filteredContact = indexer.getSectionForPosition(i);
25538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            if (filteredContact < counts.length && filteredContact >= 0) {
25638860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                counts[filteredContact]--;
25738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                if (counts[filteredContact] == 0) {
25838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                    sections[filteredContact] = "";
25938860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                }
26038860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            }
26138860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        }
26238860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        final String[] newSections = clearEmptyString(sections);
26338860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        bundle.putStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES, newSections);
26438860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        final int[] newCounts = clearZeros(counts);
26538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        bundle.putIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS, newCounts);
26638860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    }
26738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang
26838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    private static String[] clearEmptyString(String[] strings) {
26938860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        final List<String> list = new ArrayList<>();
27038860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        for (String s : strings) {
27138860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            if (!TextUtils.isEmpty(s)) {
27238860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                list.add(s);
27338860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            }
27438860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        }
27538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        return list.toArray(new String[list.size()]);
27638860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    }
27738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang
27838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    private static int[] clearZeros(int[] numbers) {
27938860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        final List<Integer> list = new ArrayList<>();
28038860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        for (int n : numbers) {
28138860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            if (n > 0) {
28238860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang                list.add(n);
28338860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            }
28438860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        }
28538860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        final int[] array = new int[list.size()];
28638860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        for(int i = 0; i < list.size(); i++) {
28738860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang            array[i] = list.get(i);
28838860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        }
28938860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang        return array;
29038860a58d52eacbeb922412bbfc31905cdd8bdc1Wenyi Wang    }
2912d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
2922d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott    /**
2932d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott     * Stores column ordering for the projection of a query of ContactsContract.Groups
2942d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott     */
2952d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott    public static final class GroupsProjection {
2962d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int groupId;
2972d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int title;
2982d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int summaryCount;
2992d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int systemId;
3002d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int accountName;
3012d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int accountType;
3022d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int dataSet;
3032d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int autoAdd;
3042d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int favorites;
3052d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int isReadOnly;
3062d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public final int deleted;
3072d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3082d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public GroupsProjection(Cursor cursor) {
3092d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            groupId = cursor.getColumnIndex(Groups._ID);
3102d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            title = cursor.getColumnIndex(Groups.TITLE);
3112d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            summaryCount = cursor.getColumnIndex(Groups.SUMMARY_COUNT);
3122d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            systemId = cursor.getColumnIndex(Groups.SYSTEM_ID);
3132d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            accountName = cursor.getColumnIndex(Groups.ACCOUNT_NAME);
3142d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            accountType = cursor.getColumnIndex(Groups.ACCOUNT_TYPE);
3152d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            dataSet = cursor.getColumnIndex(Groups.DATA_SET);
3162d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            autoAdd = cursor.getColumnIndex(Groups.AUTO_ADD);
3172d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            favorites = cursor.getColumnIndex(Groups.FAVORITES);
3182d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            isReadOnly = cursor.getColumnIndex(Groups.GROUP_IS_READ_ONLY);
3192d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            deleted = cursor.getColumnIndex(Groups.DELETED);
3202d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3212d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3222d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public GroupsProjection(String[] projection) {
3232d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            List<String> list = Arrays.asList(projection);
3242d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            groupId = list.indexOf(Groups._ID);
3252d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            title = list.indexOf(Groups.TITLE);
3262d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            summaryCount = list.indexOf(Groups.SUMMARY_COUNT);
3272d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            systemId = list.indexOf(Groups.SYSTEM_ID);
3282d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            accountName = list.indexOf(Groups.ACCOUNT_NAME);
3292d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            accountType = list.indexOf(Groups.ACCOUNT_TYPE);
3302d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            dataSet = list.indexOf(Groups.DATA_SET);
3312d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            autoAdd = list.indexOf(Groups.AUTO_ADD);
3322d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            favorites = list.indexOf(Groups.FAVORITES);
3332d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            isReadOnly = list.indexOf(Groups.GROUP_IS_READ_ONLY);
3342d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            deleted = list.indexOf(Groups.DELETED);
3352d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3362d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3372d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public String getTitle(Cursor cursor) {
3382d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            return cursor.getString(title);
3392d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3402d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3412d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public long getId(Cursor cursor) {
3422d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            return cursor.getLong(groupId);
3432d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3442d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3452d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public String getSystemId(Cursor cursor) {
3462d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            return cursor.getString(systemId);
3472d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3482d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3492d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public int getSummaryCount(Cursor cursor) {
3502d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            return cursor.getInt(summaryCount);
3512d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3522d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott
3532d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        public boolean isEmptyFFCGroup(Cursor cursor) {
3542d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            if (accountType == -1 || isReadOnly == -1 ||
3552d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott                    systemId == -1 || summaryCount == -1) {
3562d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott                throw new IllegalArgumentException("Projection is missing required columns");
3572d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            }
3582d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott            return GoogleAccountType.ACCOUNT_TYPE.equals(cursor.getString(accountType))
3592d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott                    && cursor.getInt(isReadOnly) != 0
3602d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott                    && isSystemIdFFC(cursor.getString(systemId))
3612d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott                    && cursor.getInt(summaryCount) <= 0;
3622d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott        }
3632d97b5f89ae1ae1b5e782e40b82ba60f0588f964Marcus Hagerott    }
3646bb8718b04da174f3642fbdcefea0fee6086db3dWalter Jang}
365