From 94202fe1217b9f63e1f5c314379a9f0021e96ea8 Mon Sep 17 00:00:00 2001 From: David Brown Date: Fri, 10 Jun 2011 16:24:05 -0700 Subject: Add "geoDescription" to CallerInfo As of change https://android-git.corp.google.com/g/111296 the libphonenumber library now provides an API ("PhoneNumberOfflineGeocoder") to look up a geographical description string for a given number. This change adds a new CallerInfo field called "geoDescription", and uses the PhoneNumberOfflineGeocoder to look it up (if the contact lookup fails) during the CallerInfoAsyncQuery sequence. See https://android-git.corp.google.com/g/114715 for the corresponding change under apps/Phone, to display this string (along with the raw number) in the incoming-call UI. Also some other minor cleanup: - fixed spelling of the "normalizedNumber" field - tiny javadoc and code style cleanup - slight CallManager and CallerInfo debug output cleanup Bug: 4595580 Change-Id: I900d8f48e953d1b24983602cb5467a5c6a6c518a --- .../android/internal/telephony/CallManager.java | 20 +++--- .../com/android/internal/telephony/CallerInfo.java | 83 ++++++++++++++++++++-- .../internal/telephony/CallerInfoAsyncQuery.java | 31 ++++++-- 3 files changed, 115 insertions(+), 19 deletions(-) diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java index 7abae09..171b371 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -1803,33 +1803,33 @@ public final class CallManager { Call call; StringBuilder b = new StringBuilder(); - b.append("########### Dump CallManager ############"); - b.append("\nCallManager state = " + getState()); + b.append("CallManager {"); + b.append("\nstate = " + getState()); call = getActiveFgCall(); - b.append("\n - Foreground: " + getActiveFgCallState()); + b.append("\n- Foreground: " + getActiveFgCallState()); b.append(" from " + call.getPhone()); - b.append("\n Conn: ").append(getFgCallConnections()); + b.append("\n Conn: ").append(getFgCallConnections()); call = getFirstActiveBgCall(); - b.append("\n - Background: " + call.getState()); + b.append("\n- Background: " + call.getState()); b.append(" from " + call.getPhone()); - b.append("\n Conn: ").append(getBgCallConnections()); + b.append("\n Conn: ").append(getBgCallConnections()); call = getFirstActiveRingingCall(); - b.append("\n - Ringing: " +call.getState()); + b.append("\n- Ringing: " +call.getState()); b.append(" from " + call.getPhone()); for (Phone phone : getAllPhones()) { if (phone != null) { - b.append("\n Phone: " + phone + ", name = " + phone.getPhoneName() + b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName() + ", state = " + phone.getState()); call = phone.getForegroundCall(); - b.append("\n - Foreground: ").append(call); + b.append("\n- Foreground: ").append(call); call = phone.getBackgroundCall(); b.append(" Background: ").append(call); call = phone.getRingingCall(); b.append(" Ringing: ").append(call); } } - b.append("\n########## End Dump CallManager ##########"); + b.append("\n}"); return b.toString(); } } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 014901d..457fa7a 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -19,6 +19,7 @@ package com.android.internal.telephony; import android.content.Context; import android.database.Cursor; import android.graphics.drawable.Drawable; +import android.location.CountryDetector; import android.net.Uri; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Data; @@ -29,6 +30,13 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import com.google.i18n.phonenumbers.NumberParseException; +import com.google.i18n.phonenumbers.PhoneNumberOfflineGeocoder; +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; + +import java.util.Locale; + /** * Looks up caller information for the given phone number. @@ -72,7 +80,8 @@ public class CallerInfo { */ public String name; public String phoneNumber; - public String nomalizedNumber; + public String normalizedNumber; + public String geoDescription; public String cnapName; public int numberPresentation; @@ -131,7 +140,7 @@ public class CallerInfo { info.isCachedPhotoCurrent = false; info.contactExists = false; - if (VDBG) Log.v(TAG, "construct callerInfo from cursor"); + if (VDBG) Log.v(TAG, "getCallerInfo() based on cursor..."); if (cursor != null) { if (cursor.moveToFirst()) { @@ -156,7 +165,7 @@ public class CallerInfo { // Look for the normalized number columnIndex = cursor.getColumnIndex(PhoneLookup.NORMALIZED_NUMBER); if (columnIndex != -1) { - info.nomalizedNumber = cursor.getString(columnIndex); + info.normalizedNumber = cursor.getString(columnIndex); } // Look for the label/type combo @@ -236,6 +245,8 @@ public class CallerInfo { * with all relevant fields empty or null. */ public static CallerInfo getCallerInfo(Context context, String number) { + if (VDBG) Log.v(TAG, "getCallerInfo() based on number..."); + if (TextUtils.isEmpty(number)) { return null; } @@ -473,6 +484,66 @@ public class CallerInfo { } /** + * Updates this CallerInfo's geoDescription field, based on the raw + * phone number in the phoneNumber field. + * + * (Note that the various getCallerInfo() methods do *not* set the + * geoDescription automatically; you need to call this method + * explicitly to get it.) + * + * @param context the context used to look up the current locale / country + * @param fallbackNumber if this CallerInfo's phoneNumber field is empty, + * this specifies a fallback number to use instead. + */ + public void updateGeoDescription(Context context, String fallbackNumber) { + String number = TextUtils.isEmpty(phoneNumber) ? fallbackNumber : phoneNumber; + geoDescription = getGeoDescription(context, number); + } + + /** + * @return a geographical description string for the specified number. + * @see com.google.i18n.phonenumbers.PhoneNumberOfflineGeocoder + */ + private static String getGeoDescription(Context context, String number) { + if (VDBG) Log.v(TAG, "getGeoDescription('" + number + "')..."); + + if (TextUtils.isEmpty(number)) { + return null; + } + + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance(); + + String countryIso; + Locale locale = context.getResources().getConfiguration().locale; + CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + countryIso = detector.detectCountry().getCountryIso(); + } else { + countryIso = locale.getCountry(); + Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " + + countryIso); + } + + PhoneNumber pn = null; + try { + pn = util.parse(number, countryIso); + if (VDBG) Log.v(TAG, "- parsed number: " + pn); + } catch (NumberParseException e) { + Log.w(TAG, "getGeoDescription: NumberParseException for incoming number '" + number + "'"); + } + + if (pn != null) { + String description = geocoder.getDescriptionForNumber(pn, locale); + if (VDBG) Log.v(TAG, "- got description: '" + description + "'"); + return description; + } else { + return null; + } + } + + /** * @return a string debug representation of this instance. */ public String toString() { @@ -482,8 +553,11 @@ public class CallerInfo { if (VERBOSE_DEBUG) { return new StringBuilder(384) + .append(super.toString() + " { ") .append("\nname: " + name) .append("\nphoneNumber: " + phoneNumber) + .append("\nnormalizedNumber: " + normalizedNumber) + .append("\ngeoDescription: " + geoDescription) .append("\ncnapName: " + cnapName) .append("\nnumberPresentation: " + numberPresentation) .append("\nnamePresentation: " + namePresentation) @@ -502,10 +576,11 @@ public class CallerInfo { .append("\nemergency: " + mIsEmergency) .append("\nvoicemail " + mIsVoiceMail) .append("\ncontactExists " + contactExists) + .append(" }") .toString(); } else { return new StringBuilder(128) - .append("CallerInfo { ") + .append(super.toString() + " { ") .append("name " + ((name == null) ? "null" : "non-null")) .append(", phoneNumber " + ((phoneNumber == null) ? "null" : "non-null")) .append(" }") diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index c47e076..bbd4232 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -34,9 +34,11 @@ import android.text.TextUtils; import android.util.Log; /** - * ASYNCHRONOUS QUERY API + * Helper class to make it easier to run asynchronous caller-id lookup queries. + * @see CallerInfo + * + * {@hide} */ - public class CallerInfoAsyncQuery { private static final boolean DBG = false; private static final String LOG_TAG = "CallerInfoAsyncQuery"; @@ -239,12 +241,31 @@ public class CallerInfoAsyncQuery { + mCallerInfo); } + // Final step: look up the geocoded description. + // + // For now, do this only if we *don't* have a valid name (i.e. if + // no contacts matched the phone number of the incoming call), + // since that's the only case where the incoming-call UI cares + // about this field. + // (TODO: But if we ever want the UI to show the geoDescription + // even when we *do* match a contact, we'll need to either call + // updateGeoDescription() unconditionally here, or possibly add a + // new parameter to CallerInfoAsyncQuery.startQuery() to force + // the geoDescription field to be populated.) + if (TextUtils.isEmpty(mCallerInfo.name)) { + // Actually when no contacts match the incoming phone number, + // the CallerInfo object is totally blank here (i.e. no name + // *or* phoneNumber). So we need to pass in cw.number as + // a fallback number. + mCallerInfo.updateGeoDescription(mQueryContext, cw.number); + } + // Use the number entered by the user for display. if (!TextUtils.isEmpty(cw.number)) { CountryDetector detector = (CountryDetector) mQueryContext.getSystemService( Context.COUNTRY_DETECTOR); mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number, - mCallerInfo.nomalizedNumber, + mCallerInfo.normalizedNumber, detector.detectCountry().getCountryIso()); } } @@ -412,7 +433,7 @@ public class CallerInfoAsyncQuery { * Method to create a new CallerInfoAsyncQueryHandler object, ensuring correct * state of context and uri. */ - private void allocate (Context context, Uri contactRef) { + private void allocate(Context context, Uri contactRef) { if ((context == null) || (contactRef == null)){ throw new QueryPoolException("Bad context or query uri."); } @@ -424,7 +445,7 @@ public class CallerInfoAsyncQuery { /** * Releases the relevant data. */ - private void release () { + private void release() { mHandler.mQueryContext = null; mHandler.mQueryUri = null; mHandler.mCallerInfo = null; -- cgit v1.1