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