1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.util; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.Manifest; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.pm.PackageManager; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.CommonDataKinds.Email; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.CommonDataKinds.Phone; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.CommonDataKinds.StructuredName; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.Contacts; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.Directory; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.DisplayNameSources; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.PhoneLookup; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.Profile; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.View; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.ex.chips.RecipientEntry; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.CursorQueryData; 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.FrequentContactsCursorQueryData; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsSmsUtils; 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.contact.AddContactsConfirmationDialog; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.annotations.VisibleForTesting; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Utility class including logic to list, filter, and lookup phone and emails in CP2. 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd@VisibleForTesting 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ContactUtil { 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Index of different columns in phone or email queries. All queries below should confirm to 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * this column content and ordering so that caller can use the uniformed way to process 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * returned cursors. 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_CONTACT_ID = 0; 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_DISPLAY_NAME = 1; 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_PHOTO_URI = 2; 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_PHONE_EMAIL = 3; 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_PHONE_EMAIL_TYPE = 4; 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_PHONE_EMAIL_LABEL = 5; 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // An optional lookup_id column used by PhoneLookupQuery that is needed when querying for 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // contact information. 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_LOOKUP_KEY = 6; 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // An optional _id column to query results that need to be displayed in a list view. 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_DATA_ID = 7; 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // An optional sort_key column for displaying contact section labels. 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_SORT_KEY = 8; 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Lookup key column index specific to frequent contacts query. 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_LOOKUP_KEY_FREQUENT = 3; 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Constants for listing and filtering phones. 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class PhoneQuery { 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String SORT_KEY = Phone.SORT_KEY_PRIMARY; 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.CONTACT_ID, // 0 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.DISPLAY_NAME_PRIMARY, // 1 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.PHOTO_THUMBNAIL_URI, // 2 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.NUMBER, // 3 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.TYPE, // 4 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.LABEL, // 5 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.LOOKUP_KEY, // 6 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone._ID, // 7 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneQuery.SORT_KEY, // 8 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Constants for looking up phone numbers. 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class PhoneLookupQuery { 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // The _ID field points to the contact id of the content 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup._ID, // 0 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup.DISPLAY_NAME, // 1 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup.PHOTO_THUMBNAIL_URI, // 2 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup.NUMBER, // 3 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup.TYPE, // 4 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup.LABEL, // 5 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneLookup.LOOKUP_KEY, // 6 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // The data id is not included as part of the projection since it's not part of 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // PhoneLookup. This is okay because the _id field serves as both the data id and 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // contact id. Also we never show the results directly in a list view so we are not 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // concerned about duplicated _id's (namely, the same contact has two same phone 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // numbers) 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class FrequentContactQuery { 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Contacts._ID, // 0 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Contacts.DISPLAY_NAME, // 1 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Contacts.PHOTO_URI, // 2 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.LOOKUP_KEY, // 3 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Constants for listing and filtering emails. 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class EmailQuery { 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String SORT_KEY = Email.SORT_KEY_PRIMARY; 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.CONTACT_ID, // 0 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.DISPLAY_NAME_PRIMARY, // 1 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.PHOTO_THUMBNAIL_URI, // 2 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.ADDRESS, // 3 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.TYPE, // 4 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.LABEL, // 5 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email.LOOKUP_KEY, // 6 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Email._ID, // 7 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd EmailQuery.SORT_KEY, // 8 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_SELF_QUERY_LOOKUP_KEY = 3; 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Constants for querying self from CP2. 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class SelfQuery { 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Profile._ID, // 0 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Profile.DISPLAY_NAME_PRIMARY, // 1 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Profile.PHOTO_THUMBNAIL_URI, // 2 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Profile.LOOKUP_KEY // 3 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Phone number, type, label and data_id is not provided in this projection since 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Profile CONTENT_URI doesn't include this information. Also, we don't need it 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // we just need the name and avatar url. 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class StructuredNameQuery { 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.DISPLAY_NAME, 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.GIVEN_NAME, 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.FAMILY_NAME, 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.PREFIX, 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.MIDDLE_NAME, 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.SUFFIX 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_STRUCTURED_NAME_DISPLAY_NAME = 0; 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_STRUCTURED_NAME_GIVEN_NAME = 1; 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_STRUCTURED_NAME_FAMILY_NAME = 2; 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_STRUCTURED_NAME_PREFIX = 3; 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_STRUCTURED_NAME_MIDDLE_NAME = 4; 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_STRUCTURED_NAME_SUFFIX = 5; 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final long INVALID_CONTACT_ID = -1; 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This class is static. No need to create an instance. 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ContactUtil() { 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Shows a contact card or add to contacts dialog for the given contact info 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param view The view whose click triggered this to show 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param contactId The id of the contact in the android contacts DB 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param contactLookupKey The lookup key from contacts DB 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param avatarUri Uri to the avatar image if available 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param normalizedDestination The normalized phone number or email 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void showOrAddContact(final View view, final long contactId, 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String contactLookupKey, final Uri avatarUri, 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String normalizedDestination) { 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (contactId > ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && !TextUtils.isEmpty(contactLookupKey)) { 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri lookupUri = 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactsContract.Contacts.getLookupUri(contactId, contactLookupKey); 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactsContract.QuickContact.showQuickContact(view.getContext(), view, lookupUri, 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactsContract.QuickContact.MODE_LARGE, null); 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (!TextUtils.isEmpty(normalizedDestination) && !TextUtils.equals( 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd normalizedDestination, ParticipantData.getUnknownSenderDestination())) { 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final AddContactsConfirmationDialog dialog = new AddContactsConfirmationDialog( 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd view.getContext(), avatarUri, normalizedDestination); 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd dialog.show(); 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData getSelf(final Context context) { 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new CursorQueryData(context, Profile.CONTENT_URI, SelfQuery.PROJECTION, null, null, 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null); 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get a list of phones sorted by contact name. One contact may have multiple phones. 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * In that case, each phone will be returned as a separate record in the result cursor. 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData getPhones(final Context context) { 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // The AOSP Contacts provider allows adding a ContactsContract.REMOVE_DUPLICATE_ENTRIES 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // query parameter that removes duplicate (raw) numbers. Unfortunately, we can't use that 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // because it causes the some phones' contacts provider to return incorrect sections. 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = Phone.CONTENT_URI.buildUpon().appendQueryParameter( 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT)) 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true") 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .build(); 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new CursorQueryData(context, uri, PhoneQuery.PROJECTION, null, null, 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneQuery.SORT_KEY); 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Lookup a destination (phone, email). Supplied destination should be a relatively complete 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * one for this to succeed. PhoneLookup / EmailLookup URI will apply some smartness to do a 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * loose match to see whether there is a contact that matches this destination. 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData lookupDestination(final Context context, 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String destination) { 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (MmsSmsUtils.isEmailAddress(destination)) { 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return ContactUtil.lookupEmail(context, destination); 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return ContactUtil.lookupPhone(context, destination); 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns whether the search text indicates an email based search or a phone number based one. 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static boolean shouldFilterForEmail(final String searchText) { 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return searchText != null && searchText.contains("@"); 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get a list of destinations (phone, email) matching the partial destination. 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData filterDestination(final Context context, 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String destination) { 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (shouldFilterForEmail(destination)) { 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return ContactUtil.filterEmails(context, destination); 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return ContactUtil.filterPhones(context, destination); 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 277b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak * Get a list of destinations (phone, email) matching the partial destination in work profile. 278b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak */ 279b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak public static CursorQueryData filterDestinationEnterprise(final Context context, 280b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final String destination) { 281b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak if (shouldFilterForEmail(destination)) { 282b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return ContactUtil.filterEmailsEnterprise(context, destination); 283b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } else { 284b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return ContactUtil.filterPhonesEnterprise(context, destination); 285b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 286b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 287b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak 288b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak /** 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get a list of phones matching a search criteria. The search may be on contact name or 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * phone number. In case search is on contact name, all matching contact's phone number 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * will be returned. 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * NOTE: This is visible for testing only, clients should only call filterDestination() since 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * we support email addresses as well. 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData filterPhones(final Context context, final String query) { 297b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return filterPhonesInternal(context, Phone.CONTENT_FILTER_URI, query, Directory.DEFAULT); 298b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 299b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak 300b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak /** 301b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak * Similar to {@link #filterPhones(Context, String)}, but search in work profile instead. 302b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak */ 303b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak public static CursorQueryData filterPhonesEnterprise(final Context context, 304b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final String query) { 305b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return filterPhonesInternal(context, Phone.ENTERPRISE_CONTENT_FILTER_URI, query, 306b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak Directory.ENTERPRISE_DEFAULT); 307b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 308b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak 309b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak private static CursorQueryData filterPhonesInternal(final Context context, 310b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final Uri phoneFilterBaseUri, final String query, final long directoryId) { 311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 314b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak Uri phoneFilterUri = buildDirectorySearchUri(phoneFilterBaseUri, query, directoryId); 315b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return new CursorQueryData(context, 316b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak phoneFilterUri, 317b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak PhoneQuery.PROJECTION, null, null, 318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneQuery.SORT_KEY); 319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Lookup a phone based on a phone number. Supplied phone should be a relatively complete 322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * phone number for this to succeed. PhoneLookup URI will apply some smartness to do a 323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * loose match to see whether there is a contact that matches this phone. 324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * NOTE: This is visible for testing only, clients should only call lookupDestination() since 325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * we support email addresses as well. 326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData lookupPhone(final Context context, final String phone) { 329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = getPhoneLookupUri().buildUpon() 334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .appendPath(phone).build(); 335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new CursorQueryData(context, uri, PhoneLookupQuery.PROJECTION, null, null, null); 337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get frequently contacted people. This queries for Contacts.CONTENT_STREQUENT_URI, which 341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * includes both starred or frequently contacted people. 342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData getFrequentContacts(final Context context) { 344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new FrequentContactsCursorQueryData(context, FrequentContactQuery.PROJECTION, 349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, null, null); 350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get a list of emails matching a search criteria. In Bugle, since email is not a common 354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * usage scenario, we should only do email search after user typed in a query indicating 355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * an intention to search by email (for example, "joe@"). 356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * NOTE: This is visible for testing only, clients should only call filterDestination() since 357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * we support email addresses as well. 358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData filterEmails(final Context context, final String query) { 361b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return filterEmailsInternal(context, Email.CONTENT_FILTER_URI, query, Directory.DEFAULT); 362b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 363b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak 364b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak /** 365b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak * Similar to {@link #filterEmails(Context, String)}, but search in work profile instead. 366b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak */ 367b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak public static CursorQueryData filterEmailsEnterprise(final Context context, 368b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final String query) { 369b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return filterEmailsInternal(context, Email.ENTERPRISE_CONTENT_FILTER_URI, query, 370b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak Directory.ENTERPRISE_DEFAULT); 371b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 372b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak 373b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak private static CursorQueryData filterEmailsInternal(final Context context, 374b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final Uri filterEmailsBaseUri, final String query, final long directoryId) { 375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 378b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final Uri filterEmailsUri = buildDirectorySearchUri(filterEmailsBaseUri, query, 379b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak directoryId); 380b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return new CursorQueryData(context, 381b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak filterEmailsUri, 382b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak PhoneQuery.PROJECTION, null, null, 383b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak PhoneQuery.SORT_KEY); 384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Lookup emails based a complete email address. Since there is no special logic needed for 388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * email lookup, this simply calls filterEmails. 389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * NOTE: This is visible for testing only, clients should only call lookupDestination() since 390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * we support email addresses as well. 391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static CursorQueryData lookupEmail(final Context context, final String email) { 394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = getEmailContentLookupUri().buildUpon() 399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .appendPath(email).appendQueryParameter( 400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT)) 401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .build(); 402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new CursorQueryData(context, uri, EmailQuery.PROJECTION, null, null, 404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd EmailQuery.SORT_KEY); 405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Looks up the structured name for a contact. 409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param primaryOnly If there are multiple raw contacts, set this flag to return only the 411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * name used as the primary display name. Otherwise, this method returns all names. 412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static CursorQueryData lookupStructuredName(final Context context, final long contactId, 414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean primaryOnly) { 415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission()) { 416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return CursorQueryData.getEmptyQueryData(); 417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: Handle enterprise contacts 420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri uri = ContactsContract.Contacts.CONTENT_URI.buildUpon() 421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .appendPath(String.valueOf(contactId)) 422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .appendPath(ContactsContract.Contacts.Data.CONTENT_DIRECTORY).build(); 423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String selection = ContactsContract.Data.MIMETYPE + "=?"; 425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String[] selectionArgs = { 426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredName.CONTENT_ITEM_TYPE 427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (primaryOnly) { 429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selection += " AND " + Contacts.DISPLAY_NAME_PRIMARY + "=" 430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + StructuredName.DISPLAY_NAME; 431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new CursorQueryData(context, uri, 434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StructuredNameQuery.PROJECTION, selection, selectionArgs, null); 435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Looks up the first name for a contact. If there are multiple raw 439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * contacts, this returns the name that is associated with the contact's 440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * primary display name. The name is null when contact id does not exist 441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * (possibly because it is a corp contact) or it does not have a first name. 442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static String lookupFirstName(final Context context, final long contactId) { 444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isEnterpriseContactId(contactId)) { 445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return null; 446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 447d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String firstName = null; 448d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor nameCursor = null; 449d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 450d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd nameCursor = ContactUtil.lookupStructuredName(context, contactId, true) 451d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .performSynchronousQuery(); 452d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (nameCursor != null && nameCursor.moveToFirst()) { 453d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd firstName = nameCursor.getString(ContactUtil.INDEX_STRUCTURED_NAME_GIVEN_NAME); 454d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 455d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 456d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (nameCursor != null) { 457d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd nameCursor.close(); 458d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 459d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 460d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return firstName; 461d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 462d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 463d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 464d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Creates a RecipientEntry from the provided data fields (from the contacts cursor). 465d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param firstLevel whether this item is the first entry of this contact in the list. 466d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 467d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static RecipientEntry createRecipientEntry(final String displayName, 468d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int displayNameSource, final String destination, final int destinationType, 469d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String destinationLabel, final long contactId, final String lookupKey, 470d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long dataId, final String photoThumbnailUri, final boolean firstLevel) { 471d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (firstLevel) { 472d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return RecipientEntry.constructTopLevelEntry(displayName, displayNameSource, 473d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd destination, destinationType, destinationLabel, contactId, null, dataId, 474d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd photoThumbnailUri, true, lookupKey); 475d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 476d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return RecipientEntry.constructSecondLevelEntry(displayName, displayNameSource, 477d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd destination, destinationType, destinationLabel, contactId, null, dataId, 478d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd photoThumbnailUri, true, lookupKey); 479d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 480d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 481d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 482d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 483d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Creates a RecipientEntry for PhoneQuery result. The result is then displayed in the 484d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * contact search drop down or as replacement chips in the chips edit box. 485d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 486d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static RecipientEntry createRecipientEntryForPhoneQuery(final Cursor cursor, 487d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isFirstLevel) { 488d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long contactId = cursor.getLong(ContactUtil.INDEX_CONTACT_ID); 489d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String displayName = cursor.getString( 490d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_DISPLAY_NAME); 491d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String photoThumbnailUri = cursor.getString( 492d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHOTO_URI); 493d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String destination = cursor.getString( 494d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHONE_EMAIL); 495d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int destinationType = cursor.getInt( 496d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHONE_EMAIL_TYPE); 497d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String destinationLabel = cursor.getString( 498d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHONE_EMAIL_LABEL); 499d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String lookupKey = cursor.getString( 500d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_LOOKUP_KEY); 501d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 502d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // PhoneQuery uses the contact id as the data id ("_id"). 503d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long dataId = contactId; 504d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 505d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return createRecipientEntry(displayName, 506d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DisplayNameSources.STRUCTURED_NAME, destination, destinationType, 507d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd destinationLabel, contactId, lookupKey, dataId, photoThumbnailUri, 508d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd isFirstLevel); 509d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 510d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 511d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 512d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns if a given contact id is valid. 513d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 514d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean isValidContactId(final long contactId) { 515d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return contactId >= 0; 516d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 517d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 518d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 519d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns if a given contact id belongs to managed profile. 520d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 521d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean isEnterpriseContactId(final long contactId) { 522e2ccf8bff59da2b54fb037557ad93fc4c317c506Tony Mak return OsUtil.isAtLeastL() && ContactsContract.Contacts.isEnterpriseContactId(contactId); 523d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 524d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 525d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 526d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns Email lookup uri that will query both primary and corp profile 527d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 528d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static Uri getEmailContentLookupUri() { 529e2ccf8bff59da2b54fb037557ad93fc4c317c506Tony Mak if (OsUtil.isAtLeastM()) { 530e2ccf8bff59da2b54fb037557ad93fc4c317c506Tony Mak return Email.ENTERPRISE_CONTENT_LOOKUP_URI; 531d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 532d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return Email.CONTENT_LOOKUP_URI; 533d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 534d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 535d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 536d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns PhoneLookup URI. 537d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 538d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static Uri getPhoneLookupUri() { 539e2ccf8bff59da2b54fb037557ad93fc4c317c506Tony Mak if (OsUtil.isAtLeastM()) { 540d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI; 541d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 542d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return PhoneLookup.CONTENT_FILTER_URI; 543d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 544d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 545d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean hasReadContactsPermission() { 546d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return OsUtil.hasPermission(Manifest.permission.READ_CONTACTS); 547d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 548b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak 549b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak private static Uri buildDirectorySearchUri(final Uri uri, final String query, 550b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak final long directoryId) { 551b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak return uri.buildUpon() 552b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak .appendPath(query).appendQueryParameter( 553b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)) 554b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak .build(); 555b7fc988f231394077c08b5ede4d1a7310da57406Tony Mak } 556d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 557