CallerInfo.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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.Contacts; 24import android.provider.Contacts.People; 25import android.provider.Contacts.Phones; 26import android.text.TextUtils; 27import android.telephony.TelephonyManager; 28import android.telephony.PhoneNumberUtils; 29import android.util.Config; 30import android.util.Log; 31 32/** 33 * Looks up caller information for the given phone number. 34 * 35 * {@hide} 36 */ 37public class CallerInfo { 38 private static final String TAG = "CallerInfo"; 39 40 public static final String UNKNOWN_NUMBER = "-1"; 41 public static final String PRIVATE_NUMBER = "-2"; 42 43 public String name; 44 public String phoneNumber; 45 public String phoneLabel; 46 /* Split up the phoneLabel into number type and label name */ 47 public int numberType; 48 public String numberLabel; 49 50 public int photoResource; 51 public long person_id; 52 public boolean needUpdate; 53 public Uri contactRefUri; 54 55 // fields to hold individual contact preference data, 56 // including the send to voicemail flag and the ringtone 57 // uri reference. 58 public Uri contactRingtoneUri; 59 public boolean shouldSendToVoicemail; 60 61 /** 62 * Drawable representing the caller image. This is essentially 63 * a cache for the image data tied into the connection / 64 * callerinfo object. The isCachedPhotoCurrent flag indicates 65 * if the image data needs to be reloaded. 66 */ 67 public Drawable cachedPhoto; 68 public boolean isCachedPhotoCurrent; 69 70 // Don't keep checking VM if it's going to throw an exception for this proc. 71 private static boolean sSkipVmCheck = false; 72 73 public CallerInfo() { 74 } 75 76 /** 77 * getCallerInfo given a Cursor. 78 * @param context the context used to retrieve string constants 79 * @param contactRef the URI to attach to this CallerInfo object 80 * @param cursor the first object in the cursor is used to build the CallerInfo object. 81 * @return the CallerInfo which contains the caller id for the given 82 * number. The returned CallerInfo is null if no number is supplied. 83 */ 84 public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) { 85 86 CallerInfo info = new CallerInfo(); 87 info.photoResource = 0; 88 info.phoneLabel = null; 89 info.numberType = 0; 90 info.numberLabel = null; 91 info.cachedPhoto = null; 92 info.isCachedPhotoCurrent = false; 93 94 if (Config.LOGV) Log.v(TAG, "construct callerInfo from cursor"); 95 96 if (cursor != null) { 97 if (cursor.moveToFirst()) { 98 99 int columnIndex; 100 101 // Look for the name 102 columnIndex = cursor.getColumnIndex(People.NAME); 103 if (columnIndex != -1) { 104 info.name = cursor.getString(columnIndex); 105 } 106 107 // Look for the number 108 columnIndex = cursor.getColumnIndex(Phones.NUMBER); 109 if (columnIndex != -1) { 110 info.phoneNumber = cursor.getString(columnIndex); 111 } 112 113 // Look for the label/type combo 114 columnIndex = cursor.getColumnIndex(Phones.LABEL); 115 if (columnIndex != -1) { 116 int typeColumnIndex = cursor.getColumnIndex(Phones.TYPE); 117 if (typeColumnIndex != -1) { 118 info.numberType = cursor.getInt(typeColumnIndex); 119 info.numberLabel = cursor.getString(columnIndex); 120 info.phoneLabel = Contacts.Phones.getDisplayLabel(context, 121 info.numberType, info.numberLabel) 122 .toString(); 123 } 124 } 125 126 // Look for the person ID 127 columnIndex = cursor.getColumnIndex(Phones.PERSON_ID); 128 if (columnIndex != -1) { 129 info.person_id = cursor.getLong(columnIndex); 130 } else { 131 columnIndex = cursor.getColumnIndex(People._ID); 132 if (columnIndex != -1) { 133 info.person_id = cursor.getLong(columnIndex); 134 } 135 } 136 137 // look for the custom ringtone, create from the string stored 138 // in the database. 139 columnIndex = cursor.getColumnIndex(People.CUSTOM_RINGTONE); 140 if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) { 141 info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex)); 142 } else { 143 info.contactRingtoneUri = null; 144 } 145 146 // look for the send to voicemail flag, set it to true only 147 // under certain circumstances. 148 columnIndex = cursor.getColumnIndex(People.SEND_TO_VOICEMAIL); 149 info.shouldSendToVoicemail = (columnIndex != -1) && 150 ((cursor.getInt(columnIndex)) == 1); 151 } 152 cursor.close(); 153 } 154 155 info.needUpdate = false; 156 info.name = normalize(info.name); 157 info.contactRefUri = contactRef; 158 159 return info; 160 } 161 162 /** 163 * getCallerInfo given a URI, look up in the call-log database 164 * for the uri unique key. 165 * @param context the context used to get the ContentResolver 166 * @param contactRef the URI used to lookup caller id 167 * @return the CallerInfo which contains the caller id for the given 168 * number. The returned CallerInfo is null if no number is supplied. 169 */ 170 public static CallerInfo getCallerInfo(Context context, Uri contactRef) { 171 172 return getCallerInfo(context, contactRef, 173 context.getContentResolver().query(contactRef, null, null, null, null)); 174 } 175 176 /** 177 * getCallerInfo given a phone number, look up in the call-log database 178 * for the matching caller id info. 179 * @param context the context used to get the ContentResolver 180 * @param number the phone number used to lookup caller id 181 * @return the CallerInfo which contains the caller id for the given 182 * number. The returned CallerInfo is null if no number is supplied. If 183 * a matching number is not found, then a generic caller info is returned, 184 * with all relevant fields empty or null. 185 */ 186 public static CallerInfo getCallerInfo(Context context, String number) { 187 if (TextUtils.isEmpty(number)) { 188 return null; 189 } else { 190 // Change the callerInfo number ONLY if it is an emergency number 191 // or if it is the voicemail number. If it is either, take a 192 // shortcut and skip the query. 193 if (PhoneNumberUtils.isEmergencyNumber(number)) { 194 CallerInfo ci = new CallerInfo(); 195 ci.phoneNumber = context.getString( 196 com.android.internal.R.string.emergency_call_dialog_number_for_display); 197 return ci; 198 } else { 199 try { 200 if (!sSkipVmCheck && PhoneNumberUtils.compare(number, 201 TelephonyManager.getDefault().getVoiceMailNumber())) { 202 CallerInfo ci = new CallerInfo(); 203 ci.name = TelephonyManager.getDefault().getVoiceMailAlphaTag(); 204 // TODO: FIND ANOTHER ICON 205 //info.photoResource = android.R.drawable.badge_voicemail; 206 return ci; 207 } 208 } catch (SecurityException ex) { 209 // Don't crash if this process doesn't have permission to 210 // retrieve VM number. It's still allowed to look up caller info. 211 // But don't try it again. 212 sSkipVmCheck = true; 213 } 214 } 215 } 216 217 Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, number); 218 219 CallerInfo info = getCallerInfo(context, contactUri); 220 221 // if no query results were returned with a viable number, 222 // fill in the original number value we used to query with. 223 if (TextUtils.isEmpty(info.phoneNumber)) { 224 info.phoneNumber = number; 225 } 226 227 return info; 228 } 229 230 /** 231 * getCallerId: a convenience method to get the caller id for a given 232 * number. 233 * 234 * @param context the context used to get the ContentResolver. 235 * @param number a phone number. 236 * @return if the number belongs to a contact, the contact's name is 237 * returned; otherwise, the number itself is returned. 238 * 239 * TODO NOTE: This MAY need to refer to the Asynchronous Query API 240 * [startQuery()], instead of getCallerInfo, but since it looks like 241 * it is only being used by the provider calls in the messaging app: 242 * 1. android.provider.Telephony.Mms.getDisplayAddress() 243 * 2. android.provider.Telephony.Sms.getDisplayAddress() 244 * We may not need to make the change. 245 */ 246 public static String getCallerId(Context context, String number) { 247 CallerInfo info = getCallerInfo(context, number); 248 String callerID = null; 249 250 if (info != null) { 251 String name = info.name; 252 253 if (!TextUtils.isEmpty(name)) { 254 callerID = name; 255 } else { 256 callerID = number; 257 } 258 } 259 260 return callerID; 261 } 262 263 private static String normalize(String s) { 264 if (s == null || s.length() > 0) { 265 return s; 266 } else { 267 return null; 268 } 269 } 270} 271 272