1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.providers.contacts; 18 19 import android.content.ContentValues; 20 import android.content.Context; 21 import android.provider.CallLog.Calls; 22 import android.telephony.PhoneNumberUtils; 23 import android.text.TextUtils; 24 25 import com.android.i18n.phonenumbers.NumberParseException; 26 import com.android.i18n.phonenumbers.PhoneNumberUtil; 27 import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber; 28 import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder; 29 30 import com.google.android.collect.Sets; 31 32 import java.util.Locale; 33 import java.util.Set; 34 35 /** 36 * Default implementation of {@link CallLogInsertionHelper}. 37 * <p> 38 * It added the country ISO abbreviation and the geocoded location. 39 * It checks for legacy unknown numbers and updates number presentation. 40 * <p> 41 * It uses {@link PhoneNumberOfflineGeocoder} to compute the geocoded location of a phone number. 42 */ 43 /*package*/ class DefaultCallLogInsertionHelper implements CallLogInsertionHelper { 44 private static DefaultCallLogInsertionHelper sInstance; 45 46 private static final Set<String> LEGACY_UNKNOWN_NUMBERS = Sets.newHashSet("-1", "-2", "-3"); 47 48 private final CountryMonitor mCountryMonitor; 49 private PhoneNumberUtil mPhoneNumberUtil; 50 private PhoneNumberOfflineGeocoder mPhoneNumberOfflineGeocoder; 51 private final Locale mLocale; 52 getInstance(Context context)53 public static synchronized DefaultCallLogInsertionHelper getInstance(Context context) { 54 if (sInstance == null) { 55 sInstance = new DefaultCallLogInsertionHelper(context); 56 } 57 return sInstance; 58 } 59 DefaultCallLogInsertionHelper(Context context)60 private DefaultCallLogInsertionHelper(Context context) { 61 mCountryMonitor = new CountryMonitor(context); 62 mLocale = context.getResources().getConfiguration().locale; 63 } 64 65 @Override addComputedValues(ContentValues values)66 public void addComputedValues(ContentValues values) { 67 // Insert the current country code, so we know the country the number belongs to. 68 String countryIso = getCurrentCountryIso(); 69 values.put(Calls.COUNTRY_ISO, countryIso); 70 // Insert the geocoded location, so that we do not need to compute it on the fly. 71 values.put(Calls.GEOCODED_LOCATION, 72 getGeocodedLocationFor(values.getAsString(Calls.NUMBER), countryIso)); 73 74 final String number = values.getAsString(Calls.NUMBER); 75 if (LEGACY_UNKNOWN_NUMBERS.contains(number)) { 76 values.put(Calls.NUMBER_PRESENTATION, Calls.PRESENTATION_UNKNOWN); 77 values.put(Calls.NUMBER, ""); 78 } 79 80 // Check for a normalized number; if not present attempt to determine one now. 81 if (!values.containsKey(Calls.CACHED_NORMALIZED_NUMBER) && 82 !TextUtils.isEmpty(number)) { 83 String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); 84 if (!TextUtils.isEmpty(normalizedNumber)) { 85 values.put(Calls.CACHED_NORMALIZED_NUMBER, normalizedNumber); 86 } 87 } 88 } 89 getCurrentCountryIso()90 private String getCurrentCountryIso() { 91 return mCountryMonitor.getCountryIso(); 92 } 93 getPhoneNumberUtil()94 private synchronized PhoneNumberUtil getPhoneNumberUtil() { 95 if (mPhoneNumberUtil == null) { 96 mPhoneNumberUtil = PhoneNumberUtil.getInstance(); 97 } 98 return mPhoneNumberUtil; 99 } 100 parsePhoneNumber(String number, String countryIso)101 private PhoneNumber parsePhoneNumber(String number, String countryIso) { 102 try { 103 return getPhoneNumberUtil().parse(number, countryIso); 104 } catch (NumberParseException e) { 105 return null; 106 } 107 } 108 getPhoneNumberOfflineGeocoder()109 private synchronized PhoneNumberOfflineGeocoder getPhoneNumberOfflineGeocoder() { 110 if (mPhoneNumberOfflineGeocoder == null) { 111 mPhoneNumberOfflineGeocoder = PhoneNumberOfflineGeocoder.getInstance(); 112 } 113 return mPhoneNumberOfflineGeocoder; 114 } 115 116 @Override getGeocodedLocationFor(String number, String countryIso)117 public String getGeocodedLocationFor(String number, String countryIso) { 118 PhoneNumber structuredPhoneNumber = parsePhoneNumber(number, countryIso); 119 if (structuredPhoneNumber != null) { 120 return getPhoneNumberOfflineGeocoder().getDescriptionForNumber( 121 structuredPhoneNumber, mLocale); 122 } else { 123 return null; 124 } 125 } 126 } 127