184dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira/*
284dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * Copyright (C) 2011 The Android Open Source Project
384dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira *
484dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
584dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * you may not use this file except in compliance with the License.
684dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * You may obtain a copy of the License at
784dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira *
884dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
984dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira *
1084dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * Unless required by applicable law or agreed to in writing, software
1184dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
1284dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * See the License for the specific language governing permissions and
1484dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira * limitations under the License.
1584dd9a88f0d9984996e951e59e73cb76cd2eaa5eMindy Pereira */
1697d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
1797d7768576ff27d779d68f77e23925b69f3290bcMindy Pereirapackage com.android.ex.chips;
1897d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
1916923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport android.accounts.Account;
2097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.content.Context;
2197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.database.Cursor;
22a5d37c8a968edf94755215617b593d3f61738a92Makoto Onukiimport android.database.MatrixCursor;
234db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Caoimport android.graphics.drawable.StateListDrawable;
2416923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport android.net.Uri;
2516923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport android.provider.ContactsContract;
267a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedyimport android.provider.ContactsContract.Contacts;
27ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedyimport android.text.TextUtils;
281852931de1e24e77cb708f4ba010eaa269426657Mindy Pereiraimport android.text.util.Rfc822Token;
291852931de1e24e77cb708f4ba010eaa269426657Mindy Pereiraimport android.text.util.Rfc822Tokenizer;
3018987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereiraimport android.util.Log;
3197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.view.View;
3297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.view.ViewGroup;
3397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereiraimport android.widget.CursorAdapter;
3497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
3516923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport com.android.ex.chips.BaseRecipientAdapter.DirectoryListQuery;
3616923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport com.android.ex.chips.BaseRecipientAdapter.DirectorySearchParams;
37b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Linimport com.android.ex.chips.DropdownChipLayouter.AdapterType;
3880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylorimport com.android.ex.chips.Queries.Query;
39a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki
4003cfe3eee5635e419ab1d70d463b2b8beac72f00Mindy Pereiraimport java.util.ArrayList;
411852931de1e24e77cb708f4ba010eaa269426657Mindy Pereiraimport java.util.HashMap;
42a5d37c8a968edf94755215617b593d3f61738a92Makoto Onukiimport java.util.HashSet;
4316923ee63a79fce4be3f62b08bcd1f80617c1205mindypimport java.util.List;
4494fa301de71cc110671802eba8376c275b4055a4Scott Kennedyimport java.util.Map;
4594fa301de71cc110671802eba8376c275b4055a4Scott Kennedyimport java.util.Set;
461852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira
4780f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor/**
4880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor * RecipientAlternatesAdapter backs the RecipientEditTextView for managing contacts
4980f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor * queried by email or by phone number.
5080f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor */
5197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereirapublic class RecipientAlternatesAdapter extends CursorAdapter {
528af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    public static final int MAX_LOOKUPS = 50;
5397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
5497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    private final long mCurrentId;
5597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
56007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira    private int mCheckedItemPosition = -1;
57007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira
585086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira    private OnCheckedItemChangedListener mCheckedItemChangedListener;
595086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira
6018987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira    private static final String TAG = "RecipAlternates";
6118987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira
6280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor    public static final int QUERY_TYPE_EMAIL = 0;
6380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor    public static final int QUERY_TYPE_PHONE = 1;
647a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy    private final Long mDirectoryId;
65b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin    private DropdownChipLayouter mDropdownChipLayouter;
664db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    private final StateListDrawable mDeleteDrawable;
6780f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor
687a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy    private static final Map<String, String> sCorrectedPhotoUris = new HashMap<String, String>();
697a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
7016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp    public interface RecipientMatchCallback {
7194fa301de71cc110671802eba8376c275b4055a4Scott Kennedy        public void matchesFound(Map<String, RecipientEntry> results);
7294fa301de71cc110671802eba8376c275b4055a4Scott Kennedy        /**
7394fa301de71cc110671802eba8376c275b4055a4Scott Kennedy         * Called with all addresses that could not be resolved to valid recipients.
7494fa301de71cc110671802eba8376c275b4055a4Scott Kennedy         */
75f7e202d8b83bfbd73ca47ba7843ebc4dd57c2fa4Scott Kennedy        public void matchesNotFound(Set<String> unfoundAddresses);
7616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp    }
7716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp
7876f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert    public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
794b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ArrayList<String> inAddresses, Account account, RecipientMatchCallback callback,
804b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
814b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic        getMatchingRecipients(context, adapter, inAddresses, QUERY_TYPE_EMAIL, account, callback,
824b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                permissionsCheckListener);
8380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor    }
8480f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor
851852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira    /**
861852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira     * Get a HashMap of address to RecipientEntry that contains all contact
871852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira     * information for a contact with the provided address, if one exists. This
881852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira     * may block the UI, so run it in an async task.
891852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira     *
901852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira     * @param context Context.
917211747e51623ae1305053f533c09dd335e013a2Daisuke Miyakawa     * @param inAddresses Array of addresses on which to perform the lookup.
9216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp     * @param callback RecipientMatchCallback called when a match or matches are found.
931852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira     */
9476f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert    public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
9576f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert            ArrayList<String> inAddresses, int addressType, Account account,
964b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            RecipientMatchCallback callback,
974b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
9880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        Queries.Query query;
9980f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        if (addressType == QUERY_TYPE_EMAIL) {
10080f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor            query = Queries.EMAIL;
10180f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        } else {
10280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor            query = Queries.PHONE;
10380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        }
10403cfe3eee5635e419ab1d70d463b2b8beac72f00Mindy Pereira        int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.size());
10516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        HashSet<String> addresses = new HashSet<String>();
1061852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira        StringBuilder bindString = new StringBuilder();
1071852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira        // Create the "?" string and set up arguments.
1081852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira        for (int i = 0; i < addressesSize; i++) {
10903cfe3eee5635e419ab1d70d463b2b8beac72f00Mindy Pereira            Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase());
11016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            addresses.add(tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i));
1111852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira            bindString.append("?");
1121852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira            if (i < addressesSize - 1) {
1131852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira                bindString.append(",");
1141852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira            }
1151852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira        }
1161852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira
11718987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira        if (Log.isLoggable(TAG, Log.DEBUG)) {
11818987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira            Log.d(TAG, "Doing reverse lookup for " + addresses.toString());
11918987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira        }
12018987c44006700a2bfe614ec1e39a29ed5b23d78Mindy Pereira
12116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        String[] addressArray = new String[addresses.size()];
12216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        addresses.toArray(addressArray);
12316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        HashMap<String, RecipientEntry> recipientEntries = null;
12416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        Cursor c = null;
12516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp
12616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        try {
1274b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
128f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                c = context.getContentResolver().query(
129f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        query.getContentUri(),
130f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        query.getProjection(),
131f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        query.getProjection()[Queries.Query.DESTINATION] + " IN ("
132f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                + bindString.toString() + ")", addressArray, null);
133f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            }
1347a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            recipientEntries = processContactEntries(c, null /* directoryId */);
13516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            callback.matchesFound(recipientEntries);
13616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        } finally {
13716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            if (c != null) {
13816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                c.close();
13916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            }
14016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        }
1418af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein
1428af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein        final Set<String> matchesNotFound = new HashSet<String>();
1438af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein
1448af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein        getMatchingRecipientsFromDirectoryQueries(context, recipientEntries,
1454b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                addresses, account, matchesNotFound, query, callback, permissionsCheckListener);
1468af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein
1478af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein        getMatchingRecipientsFromExtensionMatcher(adapter, matchesNotFound, callback);
1488af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    }
1498af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein
1508af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    public static void getMatchingRecipientsFromDirectoryQueries(Context context,
1518af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein            Map<String, RecipientEntry> recipientEntries, Set<String> addresses,
1528af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein            Account account, Set<String> matchesNotFound,
1534b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            RecipientMatchCallback callback,
1544b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
1558af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein        getMatchingRecipientsFromDirectoryQueries(
1568af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein                context, recipientEntries, addresses, account,
1574b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                matchesNotFound, Queries.EMAIL, callback, permissionsCheckListener);
1588af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    }
1598af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein
1608af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    private static void getMatchingRecipientsFromDirectoryQueries(Context context,
1618af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein            Map<String, RecipientEntry> recipientEntries, Set<String> addresses,
1628af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein            Account account, Set<String> matchesNotFound, Queries.Query query,
1634b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            RecipientMatchCallback callback,
1644b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
16516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        // See if any entries did not resolve; if so, we need to check other
16616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        // directories
1678af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein
16816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        if (recipientEntries.size() < addresses.size()) {
169f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            // Run a directory query for each unmatched recipient.
170f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            HashSet<String> unresolvedAddresses = new HashSet<String>();
171f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            for (String address : addresses) {
172f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                if (!recipientEntries.containsKey(address)) {
173f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                    unresolvedAddresses.add(address);
174f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                }
175f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            }
176f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            matchesNotFound.addAll(unresolvedAddresses);
177f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic
17816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            final List<DirectorySearchParams> paramsList;
179539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy            Cursor directoryCursor = null;
180539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy            try {
1814b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
182f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                    directoryCursor = context.getContentResolver().query(
183f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                            DirectoryListQuery.URI, DirectoryListQuery.PROJECTION,
184f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                            null, null, null);
185f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                }
186771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                if (directoryCursor == null) {
187f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                    return;
188771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                }
189f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                paramsList = BaseRecipientAdapter.setupOtherDirectories(
190f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        context, directoryCursor, account);
191539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy            } finally {
192539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy                if (directoryCursor != null) {
193539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy                    directoryCursor.close();
194539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy                }
195539c2b12cca5e9bccd9acabc4721c876058a68d4Scott Kennedy            }
19694fa301de71cc110671802eba8376c275b4055a4Scott Kennedy
197771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy            if (paramsList != null) {
198771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                Cursor directoryContactsCursor = null;
199771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                for (String unresolvedAddress : unresolvedAddresses) {
200771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                    for (int i = 0; i < paramsList.size(); i++) {
201f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        final long directoryId = paramsList.get(i).directoryId;
202771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                        try {
203f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                            directoryContactsCursor = doQuery(unresolvedAddress, 1 /* limit */,
2044b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                                    directoryId, account, context, query, permissionsCheckListener);
205771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                            if (directoryContactsCursor != null
206f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                    && directoryContactsCursor.getCount() != 0) {
207f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                // We found the directory with at least one contact
208f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                final Map<String, RecipientEntry> entries =
209f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                        processContactEntries(directoryContactsCursor, directoryId);
21094fa301de71cc110671802eba8376c275b4055a4Scott Kennedy
211f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                for (final String address : entries.keySet()) {
212f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                    matchesNotFound.remove(address);
213f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                }
21494fa301de71cc110671802eba8376c275b4055a4Scott Kennedy
215f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                callback.matchesFound(entries);
216f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                break;
217f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                            }
218771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                        } finally {
219f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                            if (directoryContactsCursor != null) {
220f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                directoryContactsCursor.close();
221f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                directoryContactsCursor = null;
222f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                            }
223771e417fe305e0aa65f0a864f2b4f4da7606b6b1Scott Kennedy                        }
22416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                    }
2251852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira                }
2261852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira            }
2271852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira        }
2288af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    }
22994fa301de71cc110671802eba8376c275b4055a4Scott Kennedy
2308af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein    public static void getMatchingRecipientsFromExtensionMatcher(BaseRecipientAdapter adapter,
2318af0d3b6f34e03c08c8e67be2190da01c59889daAndrew Sapperstein            Set<String> matchesNotFound, RecipientMatchCallback callback) {
23276f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert        // If no matches found in contact provider or the directories, try the extension
23376f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert        // matcher.
23476f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert        // todo (aalbert): This whole method needs to be in the adapter?
23576f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert        if (adapter != null) {
23676f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert            final Map<String, RecipientEntry> entries =
23776f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert                    adapter.getMatchingRecipients(matchesNotFound);
23876f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert            if (entries != null && entries.size() > 0) {
23976f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert                callback.matchesFound(entries);
24076f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert                for (final String address : entries.keySet()) {
24176f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert                    matchesNotFound.remove(address);
24276f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert                }
24376f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert            }
24476f1f2d4eb66956814254b0e4f86da7aa8261bcbAlon Albert        }
24594fa301de71cc110671802eba8376c275b4055a4Scott Kennedy        callback.matchesNotFound(matchesNotFound);
24616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp    }
24716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp
2487a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy    private static HashMap<String, RecipientEntry> processContactEntries(Cursor c,
2497a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            Long directoryId) {
25016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        HashMap<String, RecipientEntry> recipientEntries = new HashMap<String, RecipientEntry>();
25116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        if (c != null && c.moveToFirst()) {
25216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            do {
25316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                String address = c.getString(Queries.Query.DESTINATION);
254ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
255ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                final RecipientEntry newRecipientEntry = RecipientEntry.constructTopLevelEntry(
25616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getString(Queries.Query.NAME),
25716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getInt(Queries.Query.DISPLAY_NAME_SOURCE),
25816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getString(Queries.Query.DESTINATION),
25916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getInt(Queries.Query.DESTINATION_TYPE),
26016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getString(Queries.Query.DESTINATION_LABEL),
26116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getLong(Queries.Query.CONTACT_ID),
2627a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        directoryId,
26316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getLong(Queries.Query.DATA_ID),
26416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        c.getString(Queries.Query.PHOTO_THUMBNAIL_URI),
265514f8a75f72fa2e735418ffb5d6e30aa914fbe7bScott Kennedy                        true,
2667a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        c.getString(Queries.Query.LOOKUP_KEY));
267ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
268ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                /*
269ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                 * In certain situations, we may have two results for one address, where one of the
270ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                 * results is just the email address, and the other has a name and photo, so we want
271ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                 * to use the better one.
272ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                 */
273ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                final RecipientEntry recipientEntry =
274ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                        getBetterRecipient(recipientEntries.get(address), newRecipientEntry);
275ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
276ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                recipientEntries.put(address, recipientEntry);
27716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                if (Log.isLoggable(TAG, Log.DEBUG)) {
27816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                    Log.d(TAG, "Received reverse look up information for " + address
27916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                            + " RESULTS: "
28016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                            + " NAME : " + c.getString(Queries.Query.NAME)
28116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                            + " CONTACT ID : " + c.getLong(Queries.Query.CONTACT_ID)
28216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                            + " ADDRESS :" + c.getString(Queries.Query.DESTINATION));
28316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                }
28416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            } while (c.moveToNext());
28516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        }
2861852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira        return recipientEntries;
2871852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira    }
2881852931de1e24e77cb708f4ba010eaa269426657Mindy Pereira
289ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy    /**
290ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy     * Given two {@link RecipientEntry}s for the same email address, this will return the one that
291ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy     * contains more complete information for display purposes. Defaults to <code>entry2</code> if
292ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy     * no significant differences are found.
293ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy     */
29478f38a09c9753c0ac1838ce0bfd3a6bc1a307ff7Scott Kennedy    static RecipientEntry getBetterRecipient(final RecipientEntry entry1,
295ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            final RecipientEntry entry2) {
296ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        // If only one has passed in, use it
297ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if (entry2 == null) {
298ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry1;
299ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
300ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
301ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if (entry1 == null) {
302ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry2;
303ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
304ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
305ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        // If only one has a display name, use it
306ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if (!TextUtils.isEmpty(entry1.getDisplayName())
307ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                && TextUtils.isEmpty(entry2.getDisplayName())) {
308ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry1;
309ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
310ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
311ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if (!TextUtils.isEmpty(entry2.getDisplayName())
312ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                && TextUtils.isEmpty(entry1.getDisplayName())) {
313ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry2;
314ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
315ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
316ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        // If only one has a display name that is not the same as the destination, use it
317ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if (!TextUtils.equals(entry1.getDisplayName(), entry1.getDestination())
318ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                && TextUtils.equals(entry2.getDisplayName(), entry2.getDestination())) {
319ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry1;
320ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
321ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
322ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if (!TextUtils.equals(entry2.getDisplayName(), entry2.getDestination())
323ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                && TextUtils.equals(entry1.getDisplayName(), entry1.getDestination())) {
324ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry2;
325ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
326ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
327ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        // If only one has a photo, use it
328ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if ((entry1.getPhotoThumbnailUri() != null || entry1.getPhotoBytes() != null)
329ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                && (entry2.getPhotoThumbnailUri() == null && entry2.getPhotoBytes() == null)) {
330ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry1;
331ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
332ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
333ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        if ((entry2.getPhotoThumbnailUri() != null || entry2.getPhotoBytes() != null)
334ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy                && (entry1.getPhotoThumbnailUri() == null && entry1.getPhotoBytes() == null)) {
335ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy            return entry2;
336ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        }
337ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
338ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        // Go with the second option as a default
339ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy        return entry2;
340ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy    }
341ef3f76c8c0e4fc83a0ab7fbe8db9a98cc1e2a357Scott Kennedy
34216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp    private static Cursor doQuery(CharSequence constraint, int limit, Long directoryId,
3434b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            Account account, Context context, Query query,
3444b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
3454b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic        if (!ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
346f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            if (Log.isLoggable(TAG, Log.DEBUG)) {
347f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                Log.d(TAG, "Not doing query because we don't have required permissions.");
348f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            }
349f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            return null;
350f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        }
35116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        final Uri.Builder builder = query
35216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                .getContentFilterUri()
35316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                .buildUpon()
35416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                .appendPath(constraint.toString())
35516923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY,
35616923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                        String.valueOf(limit + BaseRecipientAdapter.ALLOWANCE_FOR_DUPLICATES));
35716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        if (directoryId != null) {
35816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
35916923ee63a79fce4be3f62b08bcd1f80617c1205mindyp                    String.valueOf(directoryId));
36016923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        }
36116923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        if (account != null) {
36216923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            builder.appendQueryParameter(BaseRecipientAdapter.PRIMARY_ACCOUNT_NAME, account.name);
36316923ee63a79fce4be3f62b08bcd1f80617c1205mindyp            builder.appendQueryParameter(BaseRecipientAdapter.PRIMARY_ACCOUNT_TYPE, account.type);
36416923ee63a79fce4be3f62b08bcd1f80617c1205mindyp        }
365f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        return context.getContentResolver()
366f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                .query(builder.build(), query.getProjection(), null, null, null);
36716923ee63a79fce4be3f62b08bcd1f80617c1205mindyp    }
36816923ee63a79fce4be3f62b08bcd1f80617c1205mindyp
3697a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy    public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
3707a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
3714b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            DropdownChipLayouter dropdownChipLayouter,
3724b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
3734db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        this(context, contactId, directoryId, lookupKey, currentId, queryMode, listener,
3744b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                dropdownChipLayouter, null, permissionsCheckListener);
3754db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    }
3764db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao
3774db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao    public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
3784db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao            String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
3794b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            DropdownChipLayouter dropdownChipLayouter, StateListDrawable deleteDrawable,
3804b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
3817a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        super(context,
3824b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                getCursorForConstruction(context, contactId, directoryId, lookupKey, queryMode,
3834b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                        permissionsCheckListener),
3844b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic                0);
38597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        mCurrentId = currentId;
3867a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        mDirectoryId = directoryId;
3875086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira        mCheckedItemChangedListener = listener;
38880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor
389b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        mDropdownChipLayouter = dropdownChipLayouter;
3904db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao        mDeleteDrawable = deleteDrawable;
39180f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor    }
39280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor
3937a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy    private static Cursor getCursorForConstruction(Context context, long contactId,
3944b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            Long directoryId, String lookupKey, int queryType,
3954b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
396f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        final Uri uri;
3977a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        final String desiredMimeType;
398f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        final String[] projection;
399f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic
40080f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        if (queryType == QUERY_TYPE_EMAIL) {
401f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            projection = Queries.EMAIL.getProjection();
4027a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
4037a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (directoryId == null || lookupKey == null) {
4047a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                uri = Queries.EMAIL.getContentUri();
4057a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                desiredMimeType = null;
4067a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            } else {
407f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                uri = Contacts.getLookupUri(contactId, lookupKey)
408f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .buildUpon()
409f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .appendPath(Contacts.Entity.CONTENT_DIRECTORY)
410f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .appendQueryParameter(
411f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId))
412f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .build();
4137a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                desiredMimeType = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE;
4147a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
41580f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        } else {
416f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            projection = Queries.PHONE.getProjection();
4177a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
4187a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (lookupKey == null) {
4197a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                uri = Queries.PHONE.getContentUri();
4207a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                desiredMimeType = null;
4217a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            } else {
422f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                uri = Contacts.getLookupUri(contactId, lookupKey)
423f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .buildUpon()
424f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .appendPath(Contacts.Entity.CONTENT_DIRECTORY)
425f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .appendQueryParameter(
426f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                                ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId))
427f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                        .build();
4287a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                desiredMimeType = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE;
4297a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
430f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        }
431f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic
432f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        final String selection = new StringBuilder()
433f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                .append(projection[Queries.Query.CONTACT_ID])
434f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                .append(" = ?")
435f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                .toString();
436f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        final Cursor cursor;
4374b01e3b35a9634336e5de163ba7c4110785bf221Milos Stankovic        if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
438a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki            cursor = context.getContentResolver().query(
439f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic                    uri, projection, selection, new String[] {String.valueOf(contactId)}, null);
440f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic        } else {
441f1ad4f6dba7c6ea28f529736b8662faa6fb498f8Milos Stankovic            cursor = new MatrixCursor(projection);
44280f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        }
4437a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
4447a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        final Cursor resultCursor = removeUndesiredDestinations(cursor, desiredMimeType, lookupKey);
4457a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        cursor.close();
4467a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
4477a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        return resultCursor;
448a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki    }
449a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki
450a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki    /**
451a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * @return a new cursor based on the given cursor with all duplicate destinations removed.
452a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     *
453a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * It's only intended to use for the alternate list, so...
454a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * - This method ignores all other fields and dedupe solely on the destination.  Normally,
455a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * if a cursor contains multiple contacts and they have the same destination, we'd still want
456a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * to show both.
457a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * - This method creates a MatrixCursor, so all data will be kept in memory.  We wouldn't want
458a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * to do this if the original cursor is large, but it's okay here because the alternate list
459a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     * won't be that big.
4607a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy     *
4617a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy     * @param desiredMimeType If this is non-<code>null</code>, only entries with this mime type
4627a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy     *            will be added to the cursor
4637a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy     * @param lookupKey The lookup key used for this contact if there isn't one in the cursor. This
4647a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy     *            should be the same one used in the query that returned the cursor
465a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki     */
466a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki    // Visible for testing
4677a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy    static Cursor removeUndesiredDestinations(final Cursor original, final String desiredMimeType,
4687a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            final String lookupKey) {
469a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki        final MatrixCursor result = new MatrixCursor(
470a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                original.getColumnNames(), original.getCount());
471a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki        final HashSet<String> destinationsSeen = new HashSet<String>();
472a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki
4737a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        String defaultDisplayName = null;
4747a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        String defaultPhotoThumbnailUri = null;
4757a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        int defaultDisplayNameSource = 0;
4767a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
4777a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        // Find some nice defaults in case we need them
4787a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        original.moveToPosition(-1);
4797a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        while (original.moveToNext()) {
4807a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            final String mimeType = original.getString(Query.MIME_TYPE);
4817a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
4827a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(
4837a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    mimeType)) {
4847a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                // Store this data
4857a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                defaultDisplayName = original.getString(Query.NAME);
4867a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                defaultPhotoThumbnailUri = original.getString(Query.PHOTO_THUMBNAIL_URI);
4877a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                defaultDisplayNameSource = original.getInt(Query.DISPLAY_NAME_SOURCE);
4887a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                break;
4897a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
4907a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy        }
4917a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
492a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki        original.moveToPosition(-1);
493a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki        while (original.moveToNext()) {
4947a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (desiredMimeType != null) {
4957a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                final String mimeType = original.getString(Query.MIME_TYPE);
4967a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                if (!desiredMimeType.equals(mimeType)) {
4977a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    continue;
4987a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                }
4997a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
500a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki            final String destination = original.getString(Query.DESTINATION);
501a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki            if (destinationsSeen.contains(destination)) {
502a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                continue;
503a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki            }
504a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki            destinationsSeen.add(destination);
505a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki
5067a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            final Object[] row = new Object[] {
507a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getString(Query.NAME),
508a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getString(Query.DESTINATION),
509a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getInt(Query.DESTINATION_TYPE),
510a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getString(Query.DESTINATION_LABEL),
511a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getLong(Query.CONTACT_ID),
512a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getLong(Query.DATA_ID),
513a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki                    original.getString(Query.PHOTO_THUMBNAIL_URI),
5147a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    original.getInt(Query.DISPLAY_NAME_SOURCE),
5157a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    original.getString(Query.LOOKUP_KEY),
5167a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    original.getString(Query.MIME_TYPE)
5177a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            };
5187a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
5197a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (row[Query.NAME] == null) {
5207a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                row[Query.NAME] = defaultDisplayName;
5217a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
5227a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (row[Query.PHOTO_THUMBNAIL_URI] == null) {
5237a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                row[Query.PHOTO_THUMBNAIL_URI] = defaultPhotoThumbnailUri;
5247a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
5257a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if ((Integer) row[Query.DISPLAY_NAME_SOURCE] == 0) {
5267a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                row[Query.DISPLAY_NAME_SOURCE] = defaultDisplayNameSource;
5277a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
5287a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (row[Query.LOOKUP_KEY] == null) {
5297a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                row[Query.LOOKUP_KEY] = lookupKey;
5307a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
5317a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
5327a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            // Ensure we don't have two '?' like content://.../...?account_name=...?sz=...
5337a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            final String photoThumbnailUri = (String) row[Query.PHOTO_THUMBNAIL_URI];
5347a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            if (photoThumbnailUri != null) {
5357a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                if (sCorrectedPhotoUris.containsKey(photoThumbnailUri)) {
5367a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    row[Query.PHOTO_THUMBNAIL_URI] = sCorrectedPhotoUris.get(photoThumbnailUri);
5377a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                } else if (photoThumbnailUri.indexOf('?') != photoThumbnailUri.lastIndexOf('?')) {
5387a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    final String[] parts = photoThumbnailUri.split("\\?");
5397a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    final StringBuilder correctedUriBuilder = new StringBuilder();
5407a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    for (int i = 0; i < parts.length; i++) {
5417a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        if (i == 1) {
5427a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                            correctedUriBuilder.append("?"); // We only want one of these
5437a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        } else if (i > 1) {
5447a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                            correctedUriBuilder.append("&"); // And we want these elsewhere
5457a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        }
5467a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                        correctedUriBuilder.append(parts[i]);
5477a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    }
5487a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
5497a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    final String correctedUri = correctedUriBuilder.toString();
5507a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    sCorrectedPhotoUris.put(photoThumbnailUri, correctedUri);
5517a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                    row[Query.PHOTO_THUMBNAIL_URI] = correctedUri;
5527a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                }
5537a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            }
5547a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy
5557a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy            result.addRow(row);
556a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki        }
557a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki
558a5d37c8a968edf94755215617b593d3f61738a92Makoto Onuki        return result;
55997d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
56097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
56197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    @Override
56297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    public long getItemId(int position) {
56397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        Cursor c = getCursor();
5643bb52162b7e842243d4a14e73c15b20dbd1804d7Mindy Pereira        if (c.moveToPosition(position)) {
56580f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor            c.getLong(Queries.Query.DATA_ID);
5663bb52162b7e842243d4a14e73c15b20dbd1804d7Mindy Pereira        }
5673bb52162b7e842243d4a14e73c15b20dbd1804d7Mindy Pereira        return -1;
56897d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
56997d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
57097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    public RecipientEntry getRecipientEntry(int position) {
57197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        Cursor c = getCursor();
57297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        c.moveToPosition(position);
57380f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        return RecipientEntry.constructTopLevelEntry(
57480f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor                c.getString(Queries.Query.NAME),
57500adb32f3cea49ec82467c0e1a9e42659b556836Makoto Onuki                c.getInt(Queries.Query.DISPLAY_NAME_SOURCE),
57680f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor                c.getString(Queries.Query.DESTINATION),
57780f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor                c.getInt(Queries.Query.DESTINATION_TYPE),
57880f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor                c.getString(Queries.Query.DESTINATION_LABEL),
57980f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor                c.getLong(Queries.Query.CONTACT_ID),
5807a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                mDirectoryId,
58180f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor                c.getLong(Queries.Query.DATA_ID),
582ccb8e237ec80934d1c983bb61f66b75541786ddcmindyp                c.getString(Queries.Query.PHOTO_THUMBNAIL_URI),
583514f8a75f72fa2e735418ffb5d6e30aa914fbe7bScott Kennedy                true,
5847a4e67708498ec46c2e9b3bad69d3807d88c064eScott Kennedy                c.getString(Queries.Query.LOOKUP_KEY));
58597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
58697d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
58797d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    @Override
58897d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    public View getView(int position, View convertView, ViewGroup parent) {
58967ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira        Cursor cursor = getCursor();
59067ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira        cursor.moveToPosition(position);
59197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        if (convertView == null) {
5924ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao            convertView = mDropdownChipLayouter.newView(AdapterType.RECIPIENT_ALTERNATES);
593007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira        }
59480f4abfb682426384e88fb1dddc682be1c8a6c7fTom Taylor        if (cursor.getLong(Queries.Query.DATA_ID) == mCurrentId) {
595007a76baab414c9d432d31c661668b1bd07e3f80Mindy Pereira            mCheckedItemPosition = position;
5965086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira            if (mCheckedItemChangedListener != null) {
5975086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira                mCheckedItemChangedListener.onCheckedItemChanged(mCheckedItemPosition);
5985086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira            }
59997d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        }
60067ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira        bindView(convertView, convertView.getContext(), cursor);
60197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira        return convertView;
60297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
60397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
60497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    @Override
60597d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    public void bindView(View view, Context context, Cursor cursor) {
60667ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira        int position = cursor.getPosition();
60767ad489cd290f7d2b468b4d69ce679edeac9bb7aMindy Pereira        RecipientEntry entry = getRecipientEntry(position);
608b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin
609b10d1c652d0416c284d9792fc9a0a92b3acd51caKevin Lin        mDropdownChipLayouter.bindView(view, null, entry, position,
6104db8cccf3332ad7c6fb1915f9f0f169953c3953aJin Cao                AdapterType.RECIPIENT_ALTERNATES, null, mDeleteDrawable);
61197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
61297d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
61397d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    @Override
61497d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    public View newView(Context context, Cursor cursor, ViewGroup parent) {
6154ddcdaed9ef5ea83910a0513e87538130270e2e4Jin Cao        return mDropdownChipLayouter.newView(AdapterType.RECIPIENT_ALTERNATES);
61697d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
61797d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira
6185086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira    /*package*/ static interface OnCheckedItemChangedListener {
6195086391a478c3b1badbb86074c3cef72126c7d0fMindy Pereira        public void onCheckedItemChanged(int position);
62097d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira    }
62197d7768576ff27d779d68f77e23925b69f3290bcMindy Pereira}
622