blob: 3b0d7ff171f4fedf2aa874685598eb033896307b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Debashish Chatterjee29c15752011-07-04 09:48:13 +010017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018package android.provider;
19
20import android.content.ContentResolver;
21import android.content.ContentValues;
22import android.content.Context;
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -080023import android.database.Cursor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.net.Uri;
Daisuke Miyakawae23362a2012-05-06 16:54:25 -070025import android.provider.ContactsContract.CommonDataKinds.Callable;
Daisuke Miyakawaf4685912011-06-25 12:31:13 -070026import android.provider.ContactsContract.CommonDataKinds.Phone;
27import android.provider.ContactsContract.DataUsageFeedback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Chiao Cheng509e1f12012-08-01 15:40:55 -070030import com.android.internal.telephony.CallerInfo;
31import com.android.internal.telephony.PhoneConstants;
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033/**
34 * The CallLog provider contains information about placed and received calls.
35 */
36public class CallLog {
37 public static final String AUTHORITY = "call_log";
38
39 /**
40 * The content:// style URL for this provider
41 */
42 public static final Uri CONTENT_URI =
43 Uri.parse("content://" + AUTHORITY);
44
45 /**
46 * Contains the recent calls.
47 */
48 public static class Calls implements BaseColumns {
49 /**
50 * The content:// style URL for this table
51 */
52 public static final Uri CONTENT_URI =
53 Uri.parse("content://call_log/calls");
54
55 /**
56 * The content:// style URL for filtering this table on phone numbers
57 */
58 public static final Uri CONTENT_FILTER_URI =
59 Uri.parse("content://call_log/calls/filter");
60
61 /**
Chiao Cheng509e1f12012-08-01 15:40:55 -070062 * Query parameter used to limit the number of call logs returned.
63 * <p>
64 * TYPE: integer
65 */
66 public static final String LIMIT_PARAM_KEY = "limit";
67
68 /**
69 * Query parameter used to specify the starting record to return.
70 * <p>
71 * TYPE: integer
72 */
73 public static final String OFFSET_PARAM_KEY = "offset";
74
75 /**
Flavio Lerda9ef78f02011-06-29 10:51:59 +010076 * An optional URI parameter which instructs the provider to allow the operation to be
77 * applied to voicemail records as well.
78 * <p>
79 * TYPE: Boolean
80 * <p>
81 * Using this parameter with a value of {@code true} will result in a security error if the
82 * calling package does not have appropriate permissions to access voicemails.
83 *
84 * @hide
85 */
86 public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
87
88 /**
Yorke Lee0a173932013-12-12 17:29:03 -080089 * Content uri used to access call log entries, including voicemail records. You must have
90 * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log.
Flavio Lerda9ef78f02011-06-29 10:51:59 +010091 */
92 public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
93 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
94 .build();
95
96 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 * The default sort order for this table
98 */
99 public static final String DEFAULT_SORT_ORDER = "date DESC";
100
101 /**
102 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI}
103 * providing a directory of calls.
104 */
105 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
106
107 /**
108 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
109 * call.
110 */
111 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
112
113 /**
Yusuf T. Mobilef6737d32009-05-15 10:56:36 -0700114 * The type of the call (incoming, outgoing or missed).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 * <P>Type: INTEGER (int)</P>
116 */
117 public static final String TYPE = "type";
118
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100119 /** Call log type for incoming calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 public static final int INCOMING_TYPE = 1;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100121 /** Call log type for outgoing calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 public static final int OUTGOING_TYPE = 2;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100123 /** Call log type for missed calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 public static final int MISSED_TYPE = 3;
Yorke Leea5f6a932013-11-22 18:17:23 -0800125 /** Call log type for voicemails. */
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100126 public static final int VOICEMAIL_TYPE = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127
128 /**
129 * The phone number as the user entered it.
130 * <P>Type: TEXT</P>
131 */
132 public static final String NUMBER = "number";
133
134 /**
Yorke Lee49e1cf92013-09-10 14:39:24 -0700135 * The number presenting rules set by the network.
136 *
137 * <p>
138 * Allowed values:
139 * <ul>
140 * <li>{@link #PRESENTATION_ALLOWED}</li>
141 * <li>{@link #PRESENTATION_RESTRICTED}</li>
142 * <li>{@link #PRESENTATION_UNKNOWN}</li>
143 * <li>{@link #PRESENTATION_PAYPHONE}</li>
144 * </ul>
145 * </p>
146 *
Jay Shraunerd88eb712013-06-10 10:10:11 -0700147 * <P>Type: INTEGER</P>
148 */
149 public static final String NUMBER_PRESENTATION = "presentation";
150
151 /** Number is allowed to display for caller id. */
152 public static final int PRESENTATION_ALLOWED = 1;
153 /** Number is blocked by user. */
154 public static final int PRESENTATION_RESTRICTED = 2;
155 /** Number is not specified or unknown by network. */
156 public static final int PRESENTATION_UNKNOWN = 3;
157 /** Number is a pay phone. */
158 public static final int PRESENTATION_PAYPHONE = 4;
159
160 /**
Bai Tao224744c2010-08-31 09:59:13 +0800161 * The ISO 3166-1 two letters country code of the country where the
162 * user received or made the call.
163 * <P>
164 * Type: TEXT
165 * </P>
Bai Tao224744c2010-08-31 09:59:13 +0800166 */
167 public static final String COUNTRY_ISO = "countryiso";
168
169 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 * The date the call occured, in milliseconds since the epoch
171 * <P>Type: INTEGER (long)</P>
172 */
173 public static final String DATE = "date";
174
175 /**
176 * The duration of the call in seconds
177 * <P>Type: INTEGER (long)</P>
178 */
179 public static final String DURATION = "duration";
180
181 /**
182 * Whether or not the call has been acknowledged
183 * <P>Type: INTEGER (boolean)</P>
184 */
185 public static final String NEW = "new";
186
187 /**
188 * The cached name associated with the phone number, if it exists.
189 * This value is not guaranteed to be current, if the contact information
190 * associated with this number has changed.
191 * <P>Type: TEXT</P>
192 */
193 public static final String CACHED_NAME = "name";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 /**
196 * The cached number type (Home, Work, etc) associated with the
197 * phone number, if it exists.
198 * This value is not guaranteed to be current, if the contact information
199 * associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800200 * <P>Type: INTEGER</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 */
202 public static final String CACHED_NUMBER_TYPE = "numbertype";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 /**
205 * The cached number label, for a custom number type, associated with the
206 * phone number, if it exists.
207 * This value is not guaranteed to be current, if the contact information
208 * associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800209 * <P>Type: TEXT</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 */
211 public static final String CACHED_NUMBER_LABEL = "numberlabel";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 /**
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100214 * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}.
215 * <P>Type: TEXT</P>
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100216 */
217 public static final String VOICEMAIL_URI = "voicemail_uri";
218
219 /**
Flavio Lerda651212d2011-07-21 16:53:59 +0100220 * Whether this item has been read or otherwise consumed by the user.
221 * <p>
222 * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
223 * existence of the entry, this implies the user has interacted with the entry.
224 * <P>Type: INTEGER (boolean)</P>
Flavio Lerda651212d2011-07-21 16:53:59 +0100225 */
226 public static final String IS_READ = "is_read";
227
228 /**
Flavio Lerda270f9302011-08-09 12:01:13 +0100229 * A geocoded location for the number associated with this call.
230 * <p>
231 * The string represents a city, state, or country associated with the number.
232 * <P>Type: TEXT</P>
Flavio Lerda270f9302011-08-09 12:01:13 +0100233 */
234 public static final String GEOCODED_LOCATION = "geocoded_location";
235
236 /**
Flavio Lerda2d538d42011-08-16 08:29:06 +0100237 * The cached URI to look up the contact associated with the phone number, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800238 * This value may not be current if the contact information associated with this number
239 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100240 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100241 */
242 public static final String CACHED_LOOKUP_URI = "lookup_uri";
243
244 /**
245 * The cached phone number of the contact which matches this entry, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800246 * This value may not be current if the contact information associated with this number
247 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100248 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100249 */
250 public static final String CACHED_MATCHED_NUMBER = "matched_number";
251
252 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800253 * The cached normalized(E164) version of the phone number, if it exists.
254 * This value may not be current if the contact information associated with this number
255 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100256 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100257 */
258 public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
259
260 /**
261 * The cached photo id of the picture associated with the phone number, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800262 * This value may not be current if the contact information associated with this number
263 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100264 * <P>Type: INTEGER (long)</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100265 */
266 public static final String CACHED_PHOTO_ID = "photo_id";
267
268 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800269 * The cached phone number, formatted with formatting rules based on the country the
270 * user was in when the call was made or received.
271 * This value is not guaranteed to be present, and may not be current if the contact
272 * information associated with this number
273 * has changed.
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100274 * <P>Type: TEXT</P>
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100275 */
276 public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
277
278 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 * Adds a call to the call log.
280 *
281 * @param ci the CallerInfo object to get the target contact from. Can be null
282 * if the contact is unknown.
283 * @param context the context used to get the ContentResolver
284 * @param number the phone number to be added to the calls db
Jay Shraunerd88eb712013-06-10 10:10:11 -0700285 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
286 * is set by the network and denotes the number presenting rules for
The Android Open Source Project10592532009-03-18 17:39:46 -0700287 * "allowed", "payphone", "restricted" or "unknown"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 * @param callType enumerated values for "incoming", "outgoing", or "missed"
289 * @param start time stamp for the call in milliseconds
290 * @param duration call duration in seconds
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800291 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 * {@hide}
293 */
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800294 public static Uri addCall(CallerInfo ci, Context context, String number,
The Android Open Source Project10592532009-03-18 17:39:46 -0700295 int presentation, int callType, long start, int duration) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 final ContentResolver resolver = context.getContentResolver();
Jay Shraunerd88eb712013-06-10 10:10:11 -0700297 int numberPresentation = PRESENTATION_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298
Jay Shraunerd88eb712013-06-10 10:10:11 -0700299 // Remap network specified number presentation types
300 // PhoneConstants.PRESENTATION_xxx to calllog number presentation types
301 // Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
302 // from any future radio changes.
303 // If the number field is empty set the presentation type to Unknown.
Wink Savillea639b312012-07-10 12:37:54 -0700304 if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700305 numberPresentation = PRESENTATION_RESTRICTED;
Wink Savillea639b312012-07-10 12:37:54 -0700306 } else if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700307 numberPresentation = PRESENTATION_PAYPHONE;
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400308 } else if (TextUtils.isEmpty(number)
Wink Savillea639b312012-07-10 12:37:54 -0700309 || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700310 numberPresentation = PRESENTATION_UNKNOWN;
311 }
312 if (numberPresentation != PRESENTATION_ALLOWED) {
313 number = "";
314 if (ci != null) {
315 ci.name = "";
316 }
Wink Savilledda53912009-05-28 17:32:34 -0700317 }
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400318
Jay Shraunerd88eb712013-06-10 10:10:11 -0700319 ContentValues values = new ContentValues(6);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320
321 values.put(NUMBER, number);
Jay Shraunerd88eb712013-06-10 10:10:11 -0700322 values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 values.put(TYPE, Integer.valueOf(callType));
324 values.put(DATE, Long.valueOf(start));
325 values.put(DURATION, Long.valueOf(duration));
326 values.put(NEW, Integer.valueOf(1));
Debashish Chatterjee4efaf4b2011-08-11 16:47:16 +0100327 if (callType == MISSED_TYPE) {
328 values.put(IS_READ, Integer.valueOf(0));
329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 if (ci != null) {
331 values.put(CACHED_NAME, ci.name);
332 values.put(CACHED_NUMBER_TYPE, ci.numberType);
333 values.put(CACHED_NUMBER_LABEL, ci.numberLabel);
334 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 if ((ci != null) && (ci.person_id > 0)) {
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700337 // Update usage information for the number associated with the contact ID.
338 // We need to use both the number and the ID for obtaining a data ID since other
339 // contacts may have the same number.
340
341 final Cursor cursor;
342
343 // We should prefer normalized one (probably coming from
344 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
345 if (ci.normalizedNumber != null) {
346 final String normalizedPhoneNumber = ci.normalizedNumber;
347 cursor = resolver.query(Phone.CONTENT_URI,
348 new String[] { Phone._ID },
349 Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
350 new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber},
351 null);
352 } else {
353 final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700354 cursor = resolver.query(
355 Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
356 Uri.encode(phoneNumber)),
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700357 new String[] { Phone._ID },
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700358 Phone.CONTACT_ID + " =?",
359 new String[] { String.valueOf(ci.person_id) },
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700360 null);
361 }
362
363 if (cursor != null) {
364 try {
365 if (cursor.getCount() > 0 && cursor.moveToFirst()) {
366 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
367 .appendPath(cursor.getString(0))
368 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
369 DataUsageFeedback.USAGE_TYPE_CALL)
370 .build();
371 resolver.update(feedbackUri, new ContentValues(), null, null);
372 }
373 } finally {
374 cursor.close();
375 }
376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 Uri result = resolver.insert(CONTENT_URI, values);
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 removeExpiredEntries(context);
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 return result;
384 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800385
386 /**
387 * Query the call log database for the last dialed number.
388 * @param context Used to get the content resolver.
389 * @return The last phone number dialed (outgoing) or an empty
390 * string if none exist yet.
391 */
392 public static String getLastOutgoingCall(Context context) {
393 final ContentResolver resolver = context.getContentResolver();
394 Cursor c = null;
395 try {
396 c = resolver.query(
397 CONTENT_URI,
398 new String[] {NUMBER},
399 TYPE + " = " + OUTGOING_TYPE,
400 null,
401 DEFAULT_SORT_ORDER + " LIMIT 1");
402 if (c == null || !c.moveToFirst()) {
403 return "";
404 }
405 return c.getString(0);
406 } finally {
407 if (c != null) c.close();
408 }
409 }
410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 private static void removeExpiredEntries(Context context) {
412 final ContentResolver resolver = context.getContentResolver();
413 resolver.delete(CONTENT_URI, "_id IN " +
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800414 "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 + " LIMIT -1 OFFSET 500)", null);
416 }
417 }
418}