CallerInfo.java revision 84b4d37dd1e9269f73c2a9cacadcd88ec4256e3f
1/* 2 * Copyright (C) 2006 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 17package com.android.internal.telephony; 18 19import android.content.Context; 20import android.database.Cursor; 21import android.graphics.drawable.Drawable; 22import android.net.Uri; 23import android.provider.ContactsContract.PhoneLookup; 24import android.provider.ContactsContract.CommonDataKinds.Phone; 25import android.text.TextUtils; 26import android.telephony.TelephonyManager; 27import android.telephony.PhoneNumberUtils; 28import android.util.Config; 29import android.util.Log; 30 31/** 32 * Looks up caller information for the given phone number. 33 * 34 * {@hide} 35 */ 36public class CallerInfo { 37 private static final String TAG = "CallerInfo"; 38 39 public static final String UNKNOWN_NUMBER = "-1"; 40 public static final String PRIVATE_NUMBER = "-2"; 41 public static final String PAYPHONE_NUMBER = "-3"; 42 43 /** 44 * Please note that, any one of these member variables can be null, 45 * and any accesses to them should be prepared to handle such a case. 46 * 47 * Also, it is implied that phoneNumber is more often populated than 48 * name is, (think of calls being dialed/received using numbers where 49 * names are not known to the device), so phoneNumber should serve as 50 * a dependable fallback when name is unavailable. 51 * 52 * One other detail here is that this CallerInfo object reflects 53 * information found on a connection, it is an OUTPUT that serves 54 * mainly to display information to the user. In no way is this object 55 * used as input to make a connection, so we can choose to display 56 * whatever human-readable text makes sense to the user for a 57 * connection. This is especially relevant for the phone number field, 58 * since it is the one field that is most likely exposed to the user. 59 * 60 * As an example: 61 * 1. User dials "911" 62 * 2. Device recognizes that this is an emergency number 63 * 3. We use the "Emergency Number" string instead of "911" in the 64 * phoneNumber field. 65 * 66 * What we're really doing here is treating phoneNumber as an essential 67 * field here, NOT name. We're NOT always guaranteed to have a name 68 * for a connection, but the number should be displayable. 69 */ 70 public String name; 71 public String phoneNumber; 72 73 public String cnapName; 74 public int numberPresentation; 75 public int namePresentation; 76 public boolean contactExists; 77 78 public String phoneLabel; 79 /* Split up the phoneLabel into number type and label name */ 80 public int numberType; 81 public String numberLabel; 82 83 public int photoResource; 84 public long person_id; 85 public boolean needUpdate; 86 public Uri contactRefUri; 87 88 // fields to hold individual contact preference data, 89 // including the send to voicemail flag and the ringtone 90 // uri reference. 91 public Uri contactRingtoneUri; 92 public boolean shouldSendToVoicemail; 93 94 /** 95 * Drawable representing the caller image. This is essentially 96 * a cache for the image data tied into the connection / 97 * callerinfo object. The isCachedPhotoCurrent flag indicates 98 * if the image data needs to be reloaded. 99 */ 100 public Drawable cachedPhoto; 101 public boolean isCachedPhotoCurrent; 102 103 // Don't keep checking VM if it's going to throw an exception for this proc. 104 private static boolean sSkipVmCheck = false; 105 106 public CallerInfo() { 107 } 108 109 /** 110 * getCallerInfo given a Cursor. 111 * @param context the context used to retrieve string constants 112 * @param contactRef the URI to attach to this CallerInfo object 113 * @param cursor the first object in the cursor is used to build the CallerInfo object. 114 * @return the CallerInfo which contains the caller id for the given 115 * number. The returned CallerInfo is null if no number is supplied. 116 */ 117 public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) { 118 119 CallerInfo info = new CallerInfo(); 120 info.photoResource = 0; 121 info.phoneLabel = null; 122 info.numberType = 0; 123 info.numberLabel = null; 124 info.cachedPhoto = null; 125 info.isCachedPhotoCurrent = false; 126 info.contactExists = false; 127 128 if (Config.LOGV) Log.v(TAG, "construct callerInfo from cursor"); 129 130 if (cursor != null) { 131 if (cursor.moveToFirst()) { 132 133 int columnIndex; 134 135 // Look for the name 136 columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME); 137 if (columnIndex != -1) { 138 info.name = cursor.getString(columnIndex); 139 } 140 141 // Look for the number 142 columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER); 143 if (columnIndex != -1) { 144 info.phoneNumber = cursor.getString(columnIndex); 145 } 146 147 // Look for the label/type combo 148 columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL); 149 if (columnIndex != -1) { 150 int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE); 151 if (typeColumnIndex != -1) { 152 info.numberType = cursor.getInt(typeColumnIndex); 153 info.numberLabel = cursor.getString(columnIndex); 154 info.phoneLabel = Phone.getDisplayLabel(context, 155 info.numberType, info.numberLabel) 156 .toString(); 157 } 158 } 159 160 // Look for the person ID 161 columnIndex = cursor.getColumnIndex(PhoneLookup._ID); 162 if (columnIndex != -1) { 163 info.person_id = cursor.getLong(columnIndex); 164 } 165 166 // look for the custom ringtone, create from the string stored 167 // in the database. 168 columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE); 169 if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) { 170 info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex)); 171 } else { 172 info.contactRingtoneUri = null; 173 } 174 175 // look for the send to voicemail flag, set it to true only 176 // under certain circumstances. 177 columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL); 178 info.shouldSendToVoicemail = (columnIndex != -1) && 179 ((cursor.getInt(columnIndex)) == 1); 180 info.contactExists = true; 181 } 182 cursor.close(); 183 } 184 185 info.needUpdate = false; 186 info.name = normalize(info.name); 187 info.contactRefUri = contactRef; 188 189 return info; 190 } 191 192 /** 193 * getCallerInfo given a URI, look up in the call-log database 194 * for the uri unique key. 195 * @param context the context used to get the ContentResolver 196 * @param contactRef the URI used to lookup caller id 197 * @return the CallerInfo which contains the caller id for the given 198 * number. The returned CallerInfo is null if no number is supplied. 199 */ 200 public static CallerInfo getCallerInfo(Context context, Uri contactRef) { 201 202 return getCallerInfo(context, contactRef, 203 context.getContentResolver().query(contactRef, null, null, null, null)); 204 } 205 206 /** 207 * getCallerInfo given a phone number, look up in the call-log database 208 * for the matching caller id info. 209 * @param context the context used to get the ContentResolver 210 * @param number the phone number used to lookup caller id 211 * @return the CallerInfo which contains the caller id for the given 212 * number. The returned CallerInfo is null if no number is supplied. If 213 * a matching number is not found, then a generic caller info is returned, 214 * with all relevant fields empty or null. 215 */ 216 public static CallerInfo getCallerInfo(Context context, String number) { 217 if (TextUtils.isEmpty(number)) { 218 return null; 219 } else { 220 // Change the callerInfo number ONLY if it is an emergency number 221 // or if it is the voicemail number. If it is either, take a 222 // shortcut and skip the query. 223 if (PhoneNumberUtils.isEmergencyNumber(number)) { 224 CallerInfo ci = new CallerInfo(); 225 226 // Note we're setting the phone number here (refer to javadoc 227 // comments at the top of CallerInfo class). 228 ci.phoneNumber = context.getString( 229 com.android.internal.R.string.emergency_call_dialog_number_for_display); 230 return ci; 231 } else { 232 try { 233 if (!sSkipVmCheck && PhoneNumberUtils.compare(number, 234 TelephonyManager.getDefault().getVoiceMailNumber())) { 235 CallerInfo ci = new CallerInfo(); 236 237 // Note we're setting the phone number here (refer to javadoc 238 // comments at the top of CallerInfo class). 239 ci.phoneNumber = TelephonyManager.getDefault().getVoiceMailAlphaTag(); 240 // TODO: FIND ANOTHER ICON 241 //info.photoResource = android.R.drawable.badge_voicemail; 242 return ci; 243 } 244 } catch (SecurityException ex) { 245 // Don't crash if this process doesn't have permission to 246 // retrieve VM number. It's still allowed to look up caller info. 247 // But don't try it again. 248 sSkipVmCheck = true; 249 } 250 } 251 } 252 253 Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); 254 255 CallerInfo info = getCallerInfo(context, contactUri); 256 257 // if no query results were returned with a viable number, 258 // fill in the original number value we used to query with. 259 if (TextUtils.isEmpty(info.phoneNumber)) { 260 info.phoneNumber = number; 261 } 262 263 return info; 264 } 265 266 /** 267 * getCallerId: a convenience method to get the caller id for a given 268 * number. 269 * 270 * @param context the context used to get the ContentResolver. 271 * @param number a phone number. 272 * @return if the number belongs to a contact, the contact's name is 273 * returned; otherwise, the number itself is returned. 274 * 275 * TODO NOTE: This MAY need to refer to the Asynchronous Query API 276 * [startQuery()], instead of getCallerInfo, but since it looks like 277 * it is only being used by the provider calls in the messaging app: 278 * 1. android.provider.Telephony.Mms.getDisplayAddress() 279 * 2. android.provider.Telephony.Sms.getDisplayAddress() 280 * We may not need to make the change. 281 */ 282 public static String getCallerId(Context context, String number) { 283 CallerInfo info = getCallerInfo(context, number); 284 String callerID = null; 285 286 if (info != null) { 287 String name = info.name; 288 289 if (!TextUtils.isEmpty(name)) { 290 callerID = name; 291 } else { 292 callerID = number; 293 } 294 } 295 296 return callerID; 297 } 298 299 private static String normalize(String s) { 300 if (s == null || s.length() > 0) { 301 return s; 302 } else { 303 return null; 304 } 305 } 306} 307