diff options
Diffstat (limited to 'src/com/android/dialer/calllog/ContactInfoHelper.java')
| -rw-r--r-- | src/com/android/dialer/calllog/ContactInfoHelper.java | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/com/android/dialer/calllog/ContactInfoHelper.java b/src/com/android/dialer/calllog/ContactInfoHelper.java new file mode 100644 index 000000000..b6f0662f2 --- /dev/null +++ b/src/com/android/dialer/calllog/ContactInfoHelper.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dialer.calllog; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.PhoneLookup; +import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; + +import com.android.contacts.util.UriUtils; + +/** + * Utility class to look up the contact information for a given number. + */ +public class ContactInfoHelper { + private final Context mContext; + private final String mCurrentCountryIso; + + public ContactInfoHelper(Context context, String currentCountryIso) { + mContext = context; + mCurrentCountryIso = currentCountryIso; + } + + /** + * Returns the contact information for the given number. + * <p> + * If the number does not match any contact, returns a contact info containing only the number + * and the formatted number. + * <p> + * If an error occurs during the lookup, it returns null. + * + * @param number the number to look up + * @param countryIso the country associated with this number + */ + public ContactInfo lookupNumber(String number, String countryIso) { + final ContactInfo info; + + // Determine the contact info. + if (PhoneNumberUtils.isUriNumber(number)) { + // This "number" is really a SIP address. + ContactInfo sipInfo = queryContactInfoForSipAddress(number); + if (sipInfo == null || sipInfo == ContactInfo.EMPTY) { + // Check whether the "username" part of the SIP address is + // actually the phone number of a contact. + String username = PhoneNumberUtils.getUsernameFromUriNumber(number); + if (PhoneNumberUtils.isGlobalPhoneNumber(username)) { + sipInfo = queryContactInfoForPhoneNumber(username, countryIso); + } + } + info = sipInfo; + } else { + // Look for a contact that has the given phone number. + ContactInfo phoneInfo = queryContactInfoForPhoneNumber(number, countryIso); + + if (phoneInfo == null || phoneInfo == ContactInfo.EMPTY) { + // Check whether the phone number has been saved as an "Internet call" number. + phoneInfo = queryContactInfoForSipAddress(number); + } + info = phoneInfo; + } + + final ContactInfo updatedInfo; + if (info == null) { + // The lookup failed. + updatedInfo = null; + } else { + // If we did not find a matching contact, generate an empty contact info for the number. + if (info == ContactInfo.EMPTY) { + // Did not find a matching contact. + updatedInfo = new ContactInfo(); + updatedInfo.number = number; + updatedInfo.formattedNumber = formatPhoneNumber(number, null, countryIso); + } else { + updatedInfo = info; + } + } + return updatedInfo; + } + + /** + * Looks up a contact using the given URI. + * <p> + * It returns null if an error occurs, {@link ContactInfo#EMPTY} if no matching contact is + * found, or the {@link ContactInfo} for the given contact. + * <p> + * The {@link ContactInfo#formattedNumber} field is always set to {@code null} in the returned + * value. + */ + private ContactInfo lookupContactFromUri(Uri uri) { + final ContactInfo info; + Cursor phonesCursor = + mContext.getContentResolver().query( + uri, PhoneQuery._PROJECTION, null, null, null); + + if (phonesCursor != null) { + try { + if (phonesCursor.moveToFirst()) { + info = new ContactInfo(); + long contactId = phonesCursor.getLong(PhoneQuery.PERSON_ID); + String lookupKey = phonesCursor.getString(PhoneQuery.LOOKUP_KEY); + info.lookupUri = Contacts.getLookupUri(contactId, lookupKey); + info.name = phonesCursor.getString(PhoneQuery.NAME); + info.type = phonesCursor.getInt(PhoneQuery.PHONE_TYPE); + info.label = phonesCursor.getString(PhoneQuery.LABEL); + info.number = phonesCursor.getString(PhoneQuery.MATCHED_NUMBER); + info.normalizedNumber = phonesCursor.getString(PhoneQuery.NORMALIZED_NUMBER); + info.photoId = phonesCursor.getLong(PhoneQuery.PHOTO_ID); + info.photoUri = + UriUtils.parseUriOrNull(phonesCursor.getString(PhoneQuery.PHOTO_URI)); + info.formattedNumber = null; + } else { + info = ContactInfo.EMPTY; + } + } finally { + phonesCursor.close(); + } + } else { + // Failed to fetch the data, ignore this request. + info = null; + } + return info; + } + + /** + * Determines the contact information for the given SIP address. + * <p> + * It returns the contact info if found. + * <p> + * If no contact corresponds to the given SIP address, returns {@link ContactInfo#EMPTY}. + * <p> + * If the lookup fails for some other reason, it returns null. + */ + private ContactInfo queryContactInfoForSipAddress(String sipAddress) { + final ContactInfo info; + + // "contactNumber" is a SIP address, so use the PhoneLookup table with the SIP parameter. + Uri.Builder uriBuilder = PhoneLookup.CONTENT_FILTER_URI.buildUpon(); + uriBuilder.appendPath(Uri.encode(sipAddress)); + uriBuilder.appendQueryParameter(PhoneLookup.QUERY_PARAMETER_SIP_ADDRESS, "1"); + return lookupContactFromUri(uriBuilder.build()); + } + + /** + * Determines the contact information for the given phone number. + * <p> + * It returns the contact info if found. + * <p> + * If no contact corresponds to the given phone number, returns {@link ContactInfo#EMPTY}. + * <p> + * If the lookup fails for some other reason, it returns null. + */ + private ContactInfo queryContactInfoForPhoneNumber(String number, String countryIso) { + String contactNumber = number; + if (!TextUtils.isEmpty(countryIso)) { + // Normalize the number: this is needed because the PhoneLookup query below does not + // accept a country code as an input. + String numberE164 = PhoneNumberUtils.formatNumberToE164(number, countryIso); + if (!TextUtils.isEmpty(numberE164)) { + // Only use it if the number could be formatted to E164. + contactNumber = numberE164; + } + } + + // The "contactNumber" is a regular phone number, so use the PhoneLookup table. + Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(contactNumber)); + ContactInfo info = lookupContactFromUri(uri); + if (info != null && info != ContactInfo.EMPTY) { + info.formattedNumber = formatPhoneNumber(number, null, countryIso); + } + return info; + } + + /** + * Format the given phone number + * + * @param number the number to be formatted. + * @param normalizedNumber the normalized number of the given number. + * @param countryIso the ISO 3166-1 two letters country code, the country's + * convention will be used to format the number if the normalized + * phone is null. + * + * @return the formatted number, or the given number if it was formatted. + */ + private String formatPhoneNumber(String number, String normalizedNumber, + String countryIso) { + if (TextUtils.isEmpty(number)) { + return ""; + } + // If "number" is really a SIP address, don't try to do any formatting at all. + if (PhoneNumberUtils.isUriNumber(number)) { + return number; + } + if (TextUtils.isEmpty(countryIso)) { + countryIso = mCurrentCountryIso; + } + return PhoneNumberUtils.formatNumber(number, normalizedNumber, countryIso); + } +} |
