blob: 6a5d857c4a37ed55cb1019b1fe3d1692b784bff0 [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
Yorke Lee158c5e412014-07-16 15:31:25 -070020import android.content.ContentProvider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.content.ContentResolver;
22import android.content.ContentValues;
23import android.content.Context;
Yorke Lee1854a602014-07-09 14:11:46 -070024import android.content.Intent;
Yorke Lee158c5e412014-07-16 15:31:25 -070025import android.content.pm.UserInfo;
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -080026import android.database.Cursor;
Shishir Agrawal1ae88e32014-10-27 12:28:52 -070027import android.location.Country;
28import android.location.CountryDetector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.net.Uri;
Yorke Lee158c5e412014-07-16 15:31:25 -070030import android.os.UserHandle;
31import android.os.UserManager;
Daisuke Miyakawae23362a2012-05-06 16:54:25 -070032import android.provider.ContactsContract.CommonDataKinds.Callable;
Daisuke Miyakawaf4685912011-06-25 12:31:13 -070033import android.provider.ContactsContract.CommonDataKinds.Phone;
Shishir Agrawal1ae88e32014-10-27 12:28:52 -070034import android.provider.ContactsContract.Data;
Daisuke Miyakawaf4685912011-06-25 12:31:13 -070035import android.provider.ContactsContract.DataUsageFeedback;
Santos Cordon204f80e2015-02-11 22:57:14 -080036import android.telecom.PhoneAccount;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070037import android.telecom.PhoneAccountHandle;
Santos Cordon204f80e2015-02-11 22:57:14 -080038import android.telecom.TelecomManager;
Shishir Agrawal1ae88e32014-10-27 12:28:52 -070039import android.telephony.PhoneNumberUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041
Chiao Cheng509e1f12012-08-01 15:40:55 -070042import com.android.internal.telephony.CallerInfo;
43import com.android.internal.telephony.PhoneConstants;
44
Yorke Lee158c5e412014-07-16 15:31:25 -070045import java.util.List;
46
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047/**
48 * The CallLog provider contains information about placed and received calls.
49 */
50public class CallLog {
Santos Cordonc66f3ba2015-02-27 15:22:07 -080051 private static final String LOG_TAG = "CallLog";
52
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 public static final String AUTHORITY = "call_log";
54
55 /**
56 * The content:// style URL for this provider
57 */
58 public static final Uri CONTENT_URI =
59 Uri.parse("content://" + AUTHORITY);
60
61 /**
62 * Contains the recent calls.
63 */
64 public static class Calls implements BaseColumns {
65 /**
66 * The content:// style URL for this table
67 */
68 public static final Uri CONTENT_URI =
69 Uri.parse("content://call_log/calls");
70
71 /**
72 * The content:// style URL for filtering this table on phone numbers
73 */
74 public static final Uri CONTENT_FILTER_URI =
75 Uri.parse("content://call_log/calls/filter");
76
77 /**
Chiao Cheng509e1f12012-08-01 15:40:55 -070078 * Query parameter used to limit the number of call logs returned.
79 * <p>
80 * TYPE: integer
81 */
82 public static final String LIMIT_PARAM_KEY = "limit";
83
84 /**
85 * Query parameter used to specify the starting record to return.
86 * <p>
87 * TYPE: integer
88 */
89 public static final String OFFSET_PARAM_KEY = "offset";
90
91 /**
Flavio Lerda9ef78f02011-06-29 10:51:59 +010092 * An optional URI parameter which instructs the provider to allow the operation to be
93 * applied to voicemail records as well.
94 * <p>
95 * TYPE: Boolean
96 * <p>
97 * Using this parameter with a value of {@code true} will result in a security error if the
98 * calling package does not have appropriate permissions to access voicemails.
99 *
100 * @hide
101 */
102 public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
103
104 /**
Yorke Lee1854a602014-07-09 14:11:46 -0700105 * An optional extra used with {@link #CONTENT_TYPE Calls.CONTENT_TYPE} and
106 * {@link Intent#ACTION_VIEW} to specify that the presented list of calls should be
107 * filtered for a particular call type.
108 *
109 * Applications implementing a call log UI should check for this extra, and display a
110 * filtered list of calls based on the specified call type. If not applicable within the
111 * application's UI, it should be silently ignored.
112 *
113 * <p>
114 * The following example brings up the call log, showing only missed calls.
115 * <pre>
116 * Intent intent = new Intent(Intent.ACTION_VIEW);
117 * intent.setType(CallLog.Calls.CONTENT_TYPE);
118 * intent.putExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, CallLog.Calls.MISSED_TYPE);
119 * startActivity(intent);
120 * </pre>
121 * </p>
122 */
Yorke Lee78814622014-09-04 16:07:50 -0700123 public static final String EXTRA_CALL_TYPE_FILTER =
124 "android.provider.extra.CALL_TYPE_FILTER";
Yorke Lee1854a602014-07-09 14:11:46 -0700125
126 /**
Yorke Lee0a173932013-12-12 17:29:03 -0800127 * Content uri used to access call log entries, including voicemail records. You must have
Yorke Lee624d0d62014-07-23 15:23:47 -0700128 * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log, as
129 * well as READ_VOICEMAIL and WRITE_VOICEMAIL permissions to read and write voicemails.
Flavio Lerda9ef78f02011-06-29 10:51:59 +0100130 */
131 public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
132 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
133 .build();
134
135 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 * The default sort order for this table
137 */
138 public static final String DEFAULT_SORT_ORDER = "date DESC";
139
140 /**
141 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI}
142 * providing a directory of calls.
143 */
144 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
145
146 /**
147 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
148 * call.
149 */
150 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
151
152 /**
Yusuf T. Mobilef6737d32009-05-15 10:56:36 -0700153 * The type of the call (incoming, outgoing or missed).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 * <P>Type: INTEGER (int)</P>
Andrew Leef61b1fc2015-09-25 21:11:19 -0700155 *
156 * <p>
157 * Allowed values:
158 * <ul>
159 * <li>{@link #INCOMING_TYPE}</li>
160 * <li>{@link #OUTGOING_TYPE}</li>
161 * <li>{@link #MISSED_TYPE}</li>
162 * <li>{@link #VOICEMAIL_TYPE}</li>
163 * <li>{@link #REJECTED_TYPE}</li>
164 * <li>{@link #BLOCKED_TYPE}</li>
165 * </ul>
166 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 */
168 public static final String TYPE = "type";
169
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100170 /** Call log type for incoming calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 public static final int INCOMING_TYPE = 1;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100172 /** Call log type for outgoing calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 public static final int OUTGOING_TYPE = 2;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100174 /** Call log type for missed calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 public static final int MISSED_TYPE = 3;
Yorke Leea5f6a932013-11-22 18:17:23 -0800176 /** Call log type for voicemails. */
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100177 public static final int VOICEMAIL_TYPE = 4;
Andrew Leef61b1fc2015-09-25 21:11:19 -0700178 /** Call log type for calls rejected by direct user action. */
179 public static final int REJECTED_TYPE = 5;
180 /** Call log type for calls blocked automatically. */
181 public static final int BLOCKED_TYPE = 6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182
183 /**
Tyler Gunne5daf912014-07-08 15:22:55 -0700184 * Bit-mask describing features of the call (e.g. video).
185 *
186 * <P>Type: INTEGER (int)</P>
187 */
188 public static final String FEATURES = "features";
189
Tyler Gunne5daf912014-07-08 15:22:55 -0700190 /** Call had video. */
191 public static final int FEATURES_VIDEO = 0x1;
192
193 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 * The phone number as the user entered it.
195 * <P>Type: TEXT</P>
196 */
197 public static final String NUMBER = "number";
198
199 /**
Yorke Lee49e1cf92013-09-10 14:39:24 -0700200 * The number presenting rules set by the network.
201 *
202 * <p>
203 * Allowed values:
204 * <ul>
205 * <li>{@link #PRESENTATION_ALLOWED}</li>
206 * <li>{@link #PRESENTATION_RESTRICTED}</li>
207 * <li>{@link #PRESENTATION_UNKNOWN}</li>
208 * <li>{@link #PRESENTATION_PAYPHONE}</li>
209 * </ul>
210 * </p>
211 *
Jay Shraunerd88eb712013-06-10 10:10:11 -0700212 * <P>Type: INTEGER</P>
213 */
214 public static final String NUMBER_PRESENTATION = "presentation";
215
216 /** Number is allowed to display for caller id. */
217 public static final int PRESENTATION_ALLOWED = 1;
218 /** Number is blocked by user. */
219 public static final int PRESENTATION_RESTRICTED = 2;
220 /** Number is not specified or unknown by network. */
221 public static final int PRESENTATION_UNKNOWN = 3;
222 /** Number is a pay phone. */
223 public static final int PRESENTATION_PAYPHONE = 4;
224
225 /**
Bai Tao224744c2010-08-31 09:59:13 +0800226 * The ISO 3166-1 two letters country code of the country where the
227 * user received or made the call.
228 * <P>
229 * Type: TEXT
230 * </P>
Bai Tao224744c2010-08-31 09:59:13 +0800231 */
232 public static final String COUNTRY_ISO = "countryiso";
233
234 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 * The date the call occured, in milliseconds since the epoch
236 * <P>Type: INTEGER (long)</P>
237 */
238 public static final String DATE = "date";
239
240 /**
241 * The duration of the call in seconds
242 * <P>Type: INTEGER (long)</P>
243 */
244 public static final String DURATION = "duration";
245
246 /**
Tyler Gunne5daf912014-07-08 15:22:55 -0700247 * The data usage of the call in bytes.
248 * <P>Type: INTEGER (long)</P>
249 */
250 public static final String DATA_USAGE = "data_usage";
251
252 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 * Whether or not the call has been acknowledged
254 * <P>Type: INTEGER (boolean)</P>
255 */
256 public static final String NEW = "new";
257
258 /**
259 * The cached name associated with the phone number, if it exists.
260 * This value is not guaranteed to be current, if the contact information
261 * associated with this number has changed.
262 * <P>Type: TEXT</P>
263 */
264 public static final String CACHED_NAME = "name";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 /**
267 * The cached number type (Home, Work, etc) associated with the
268 * phone number, if it exists.
269 * This value is not guaranteed to be current, if the contact information
270 * associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800271 * <P>Type: INTEGER</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 */
273 public static final String CACHED_NUMBER_TYPE = "numbertype";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 /**
276 * The cached number label, for a custom number type, associated with the
277 * phone number, if it exists.
278 * This value is not guaranteed to be current, if the contact information
279 * associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800280 * <P>Type: TEXT</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 */
282 public static final String CACHED_NUMBER_LABEL = "numberlabel";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 /**
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100285 * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}.
286 * <P>Type: TEXT</P>
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100287 */
288 public static final String VOICEMAIL_URI = "voicemail_uri";
289
290 /**
Yorke Lee7a5e5722014-07-23 19:43:39 -0700291 * Transcription of the call or voicemail entry. This will only be populated for call log
292 * entries of type {@link #VOICEMAIL_TYPE} that have valid transcriptions.
293 */
294 public static final String TRANSCRIPTION = "transcription";
295
296 /**
Flavio Lerda651212d2011-07-21 16:53:59 +0100297 * Whether this item has been read or otherwise consumed by the user.
298 * <p>
299 * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
300 * existence of the entry, this implies the user has interacted with the entry.
301 * <P>Type: INTEGER (boolean)</P>
Flavio Lerda651212d2011-07-21 16:53:59 +0100302 */
303 public static final String IS_READ = "is_read";
304
305 /**
Flavio Lerda270f9302011-08-09 12:01:13 +0100306 * A geocoded location for the number associated with this call.
307 * <p>
308 * The string represents a city, state, or country associated with the number.
309 * <P>Type: TEXT</P>
Flavio Lerda270f9302011-08-09 12:01:13 +0100310 */
311 public static final String GEOCODED_LOCATION = "geocoded_location";
312
313 /**
Flavio Lerda2d538d42011-08-16 08:29:06 +0100314 * The cached URI to look up the contact associated with the phone number, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800315 * This value may not be current if the contact information associated with this number
316 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100317 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100318 */
319 public static final String CACHED_LOOKUP_URI = "lookup_uri";
320
321 /**
322 * The cached phone number of the contact which matches this entry, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800323 * This value may not be current if the contact information associated with this number
324 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100325 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100326 */
327 public static final String CACHED_MATCHED_NUMBER = "matched_number";
328
329 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800330 * The cached normalized(E164) version of the phone number, if it exists.
331 * This value may not be current if the contact information associated with this number
332 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100333 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100334 */
335 public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
336
337 /**
338 * The cached photo id of the picture associated with the phone number, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800339 * This value may not be current if the contact information associated with this number
340 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100341 * <P>Type: INTEGER (long)</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100342 */
343 public static final String CACHED_PHOTO_ID = "photo_id";
344
345 /**
Makoto Onukiedb84502015-03-09 13:57:02 -0700346 * The cached photo URI of the picture associated with the phone number, if it exists.
347 * This value may not be current if the contact information associated with this number
348 * has changed.
349 * <P>Type: TEXT (URI)</P>
350 */
351 public static final String CACHED_PHOTO_URI = "photo_uri";
352
353 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800354 * The cached phone number, formatted with formatting rules based on the country the
355 * user was in when the call was made or received.
356 * This value is not guaranteed to be present, and may not be current if the contact
357 * information associated with this number
358 * has changed.
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100359 * <P>Type: TEXT</P>
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100360 */
361 public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
362
Ihab Awad9c3f1882014-06-30 21:17:13 -0700363 // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
364 // that was encoded into call log databases.
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700365
366 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800367 * The component name of the account used to place or receive the call; in string form.
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700368 * <P>Type: TEXT</P>
369 */
Ihab Awad9c3f1882014-06-30 21:17:13 -0700370 public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
371
372 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800373 * The identifier for the account used to place or receive the call.
Ihab Awad9c3f1882014-06-30 21:17:13 -0700374 * <P>Type: TEXT</P>
375 */
376 public static final String PHONE_ACCOUNT_ID = "subscription_id";
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700377
378 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800379 * The address associated with the account used to place or receive the call; in string
380 * form. For SIM-based calls, this is the user's own phone number.
381 * <P>Type: TEXT</P>
382 *
383 * @hide
384 */
385 public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
386
387 /**
Santos Cordon2d2bc162015-02-27 15:22:07 -0800388 * Indicates that the entry will be hidden from all queries until the associated
389 * {@link android.telecom.PhoneAccount} is registered with the system.
390 * <P>Type: INTEGER</P>
391 *
392 * @hide
393 */
394 public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden";
395
396 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800397 * The subscription ID used to place this call. This is no longer used and has been
398 * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
399 * For ContactsProvider internal use only.
Nancy Chen3a780922014-08-27 18:29:59 -0700400 * <P>Type: INTEGER</P>
401 *
Santos Cordon204f80e2015-02-11 22:57:14 -0800402 * @Deprecated
Nancy Chen3a780922014-08-27 18:29:59 -0700403 * @hide
404 */
405 public static final String SUB_ID = "sub_id";
406
407 /**
Hall Liu594c7912015-10-14 15:13:51 -0700408 * The post-dial portion of a dialed number, including any digits dialed after a
409 * {@link TelecomManager#DTMF_CHARACTER_PAUSE} or a {@link
410 * TelecomManager#DTMF_CHARACTER_WAIT} and these characters themselves.
411 * <P>Type: TEXT</P>
412 */
413 public static final String POST_DIAL_DIGITS = "post_dial_digits";
414
415 /**
Tony Makce759a12015-11-25 21:55:52 +0000416 * Indicates that the entry will be copied from primary user to other users.
417 * <P>Type: INTEGER</P>
418 *
419 * @hide
420 */
421 public static final String ADD_FOR_ALL_USERS = "add_for_all_users";
422
423 /**
Ta-wei Yena07707a2015-12-11 11:46:58 -0800424 * The date the row is last inserted, updated, or marked as deleted, in milliseconds
425 * since the epoch. Read only.
426 * <P>Type: INTEGER (long)</P>
427 */
428 public static final String LAST_MODIFIED = "last_modified";
429
430 /**
Yorke Lee3dbc1182014-08-21 09:37:22 -0700431 * If a successful call is made that is longer than this duration, update the phone number
432 * in the ContactsProvider with the normalized version of the number, based on the user's
433 * current country code.
434 */
435 private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * Adds a call to the call log.
439 *
440 * @param ci the CallerInfo object to get the target contact from. Can be null
441 * if the contact is unknown.
442 * @param context the context used to get the ContentResolver
443 * @param number the phone number to be added to the calls db
Jay Shraunerd88eb712013-06-10 10:10:11 -0700444 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
445 * is set by the network and denotes the number presenting rules for
The Android Open Source Project10592532009-03-18 17:39:46 -0700446 * "allowed", "payphone", "restricted" or "unknown"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * @param callType enumerated values for "incoming", "outgoing", or "missed"
Tyler Gunne5daf912014-07-08 15:22:55 -0700448 * @param features features of the call (e.g. Video).
Evan Charlton8c8a0622014-07-20 12:31:00 -0700449 * @param accountHandle The accountHandle object identifying the provider of the call
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 * @param start time stamp for the call in milliseconds
451 * @param duration call duration in seconds
Tyler Gunne5daf912014-07-08 15:22:55 -0700452 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
453 * the call.
Yorke Lee158c5e412014-07-16 15:31:25 -0700454 * @result The URI of the call log entry belonging to the user that made or received this
455 * call.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 * {@hide}
457 */
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800458 public static Uri addCall(CallerInfo ci, Context context, String number,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700459 int presentation, int callType, int features, PhoneAccountHandle accountHandle,
Evan Charlton6eb262c2014-07-19 18:18:19 -0700460 long start, int duration, Long dataUsage) {
Hall Liu594c7912015-10-14 15:13:51 -0700461 return addCall(ci, context, number, "", presentation, callType, features, accountHandle,
Tony Makce759a12015-11-25 21:55:52 +0000462 start, duration, dataUsage, false, null, false);
Yorke Lee158c5e412014-07-16 15:31:25 -0700463 }
464
Wink Saville05e6dde2014-08-31 19:24:10 -0700465
Yorke Lee158c5e412014-07-16 15:31:25 -0700466 /**
467 * Adds a call to the call log.
468 *
469 * @param ci the CallerInfo object to get the target contact from. Can be null
470 * if the contact is unknown.
471 * @param context the context used to get the ContentResolver
472 * @param number the phone number to be added to the calls db
473 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
474 * is set by the network and denotes the number presenting rules for
475 * "allowed", "payphone", "restricted" or "unknown"
476 * @param callType enumerated values for "incoming", "outgoing", or "missed"
477 * @param features features of the call (e.g. Video).
478 * @param accountHandle The accountHandle object identifying the provider of the call
479 * @param start time stamp for the call in milliseconds
480 * @param duration call duration in seconds
481 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
482 * the call.
483 * @param addForAllUsers If true, the call is added to the call log of all currently
484 * running users. The caller must have the MANAGE_USERS permission if this is true.
Tony Makce759a12015-11-25 21:55:52 +0000485 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
486 * inserted to. null if it is inserted to the current user. The
487 * value is ignored if @{link addForAllUsers} is true.
Yorke Lee158c5e412014-07-16 15:31:25 -0700488 * @result The URI of the call log entry belonging to the user that made or received this
489 * call.
490 * {@hide}
491 */
492 public static Uri addCall(CallerInfo ci, Context context, String number,
Hall Liu594c7912015-10-14 15:13:51 -0700493 String postDialDigits, int presentation, int callType, int features,
494 PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage,
Tony Makce759a12015-11-25 21:55:52 +0000495 boolean addForAllUsers, UserHandle userToBeInsertedTo) {
Hall Liu594c7912015-10-14 15:13:51 -0700496 return addCall(ci, context, number, postDialDigits, presentation, callType, features,
Tony Makce759a12015-11-25 21:55:52 +0000497 accountHandle, start, duration, dataUsage, addForAllUsers, userToBeInsertedTo,
498 false);
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700499 }
500
501 /**
502 * Adds a call to the call log.
503 *
504 * @param ci the CallerInfo object to get the target contact from. Can be null
505 * if the contact is unknown.
506 * @param context the context used to get the ContentResolver
507 * @param number the phone number to be added to the calls db
Hall Liu594c7912015-10-14 15:13:51 -0700508 * @param postDialDigits the post-dial digits that were dialed after the number,
509 * if it was outgoing. Otherwise it is ''.
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700510 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
511 * is set by the network and denotes the number presenting rules for
512 * "allowed", "payphone", "restricted" or "unknown"
513 * @param callType enumerated values for "incoming", "outgoing", or "missed"
514 * @param features features of the call (e.g. Video).
515 * @param accountHandle The accountHandle object identifying the provider of the call
516 * @param start time stamp for the call in milliseconds
517 * @param duration call duration in seconds
518 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
519 * the call.
520 * @param addForAllUsers If true, the call is added to the call log of all currently
521 * running users. The caller must have the MANAGE_USERS permission if this is true.
Tony Makce759a12015-11-25 21:55:52 +0000522 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
523 * inserted to. null if it is inserted to the current user. The
524 * value is ignored if @{link addForAllUsers} is true.
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700525 * @param is_read Flag to show if the missed call log has been read by the user or not.
526 * Used for call log restore of missed calls.
527 *
528 * @result The URI of the call log entry belonging to the user that made or received this
529 * call.
530 * {@hide}
531 */
532 public static Uri addCall(CallerInfo ci, Context context, String number,
Hall Liu594c7912015-10-14 15:13:51 -0700533 String postDialDigits, int presentation, int callType, int features,
534 PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage,
Tony Makce759a12015-11-25 21:55:52 +0000535 boolean addForAllUsers, UserHandle userToBeInsertedTo, boolean is_read) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 final ContentResolver resolver = context.getContentResolver();
Jay Shraunerd88eb712013-06-10 10:10:11 -0700537 int numberPresentation = PRESENTATION_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538
Santos Cordon204f80e2015-02-11 22:57:14 -0800539 TelecomManager tm = null;
540 try {
541 tm = TelecomManager.from(context);
542 } catch (UnsupportedOperationException e) {}
543
544 String accountAddress = null;
545 if (tm != null && accountHandle != null) {
546 PhoneAccount account = tm.getPhoneAccount(accountHandle);
547 if (account != null) {
Santos Cordon2d2bc162015-02-27 15:22:07 -0800548 Uri address = account.getSubscriptionAddress();
549 if (address != null) {
550 accountAddress = address.getSchemeSpecificPart();
551 }
Santos Cordon204f80e2015-02-11 22:57:14 -0800552 }
553 }
554
Jay Shraunerd88eb712013-06-10 10:10:11 -0700555 // Remap network specified number presentation types
556 // PhoneConstants.PRESENTATION_xxx to calllog number presentation types
557 // Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
558 // from any future radio changes.
559 // If the number field is empty set the presentation type to Unknown.
Wink Savillea639b312012-07-10 12:37:54 -0700560 if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700561 numberPresentation = PRESENTATION_RESTRICTED;
Wink Savillea639b312012-07-10 12:37:54 -0700562 } else if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700563 numberPresentation = PRESENTATION_PAYPHONE;
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400564 } else if (TextUtils.isEmpty(number)
Wink Savillea639b312012-07-10 12:37:54 -0700565 || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700566 numberPresentation = PRESENTATION_UNKNOWN;
567 }
568 if (numberPresentation != PRESENTATION_ALLOWED) {
569 number = "";
570 if (ci != null) {
571 ci.name = "";
572 }
Wink Savilledda53912009-05-28 17:32:34 -0700573 }
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400574
Evan Charlton8c8a0622014-07-20 12:31:00 -0700575 // accountHandle information
Ihab Awad9c3f1882014-06-30 21:17:13 -0700576 String accountComponentString = null;
577 String accountId = null;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700578 if (accountHandle != null) {
579 accountComponentString = accountHandle.getComponentName().flattenToString();
580 accountId = accountHandle.getId();
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700581 }
582
Jay Shraunerd88eb712013-06-10 10:10:11 -0700583 ContentValues values = new ContentValues(6);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584
585 values.put(NUMBER, number);
Hall Liu594c7912015-10-14 15:13:51 -0700586 values.put(POST_DIAL_DIGITS, postDialDigits);
Jay Shraunerd88eb712013-06-10 10:10:11 -0700587 values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 values.put(TYPE, Integer.valueOf(callType));
Tyler Gunne5daf912014-07-08 15:22:55 -0700589 values.put(FEATURES, features);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 values.put(DATE, Long.valueOf(start));
591 values.put(DURATION, Long.valueOf(duration));
Tyler Gunne5daf912014-07-08 15:22:55 -0700592 if (dataUsage != null) {
593 values.put(DATA_USAGE, dataUsage);
594 }
Ihab Awad9c3f1882014-06-30 21:17:13 -0700595 values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
596 values.put(PHONE_ACCOUNT_ID, accountId);
Santos Cordon204f80e2015-02-11 22:57:14 -0800597 values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 values.put(NEW, Integer.valueOf(1));
Tony Makce759a12015-11-25 21:55:52 +0000599 values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
Wink Saville05e6dde2014-08-31 19:24:10 -0700600
Debashish Chatterjee4efaf4b2011-08-11 16:47:16 +0100601 if (callType == MISSED_TYPE) {
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700602 values.put(IS_READ, Integer.valueOf(is_read ? 1 : 0));
Debashish Chatterjee4efaf4b2011-08-11 16:47:16 +0100603 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800604
Makoto Onukia2295e62014-07-10 15:32:16 -0700605 if ((ci != null) && (ci.contactIdOrZero > 0)) {
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700606 // Update usage information for the number associated with the contact ID.
607 // We need to use both the number and the ID for obtaining a data ID since other
608 // contacts may have the same number.
609
610 final Cursor cursor;
611
612 // We should prefer normalized one (probably coming from
613 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
614 if (ci.normalizedNumber != null) {
615 final String normalizedPhoneNumber = ci.normalizedNumber;
616 cursor = resolver.query(Phone.CONTENT_URI,
617 new String[] { Phone._ID },
618 Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
Makoto Onukia2295e62014-07-10 15:32:16 -0700619 new String[] { String.valueOf(ci.contactIdOrZero),
620 normalizedPhoneNumber},
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700621 null);
622 } else {
623 final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700624 cursor = resolver.query(
625 Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
626 Uri.encode(phoneNumber)),
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700627 new String[] { Phone._ID },
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700628 Phone.CONTACT_ID + " =?",
Makoto Onukia2295e62014-07-10 15:32:16 -0700629 new String[] { String.valueOf(ci.contactIdOrZero) },
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700630 null);
631 }
632
633 if (cursor != null) {
634 try {
635 if (cursor.getCount() > 0 && cursor.moveToFirst()) {
Shishir Agrawal1ae88e32014-10-27 12:28:52 -0700636 final String dataId = cursor.getString(0);
637 updateDataUsageStatForData(resolver, dataId);
638 if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS
639 && callType == Calls.OUTGOING_TYPE
640 && TextUtils.isEmpty(ci.normalizedNumber)) {
641 updateNormalizedNumber(context, resolver, dataId, number);
642 }
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700643 }
644 } finally {
645 cursor.close();
646 }
647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800649
Yorke Lee158c5e412014-07-16 15:31:25 -0700650 Uri result = null;
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800651
Yorke Lee158c5e412014-07-16 15:31:25 -0700652 if (addForAllUsers) {
653 // Insert the entry for all currently running users, in order to trigger any
654 // ContentObservers currently set on the call log.
655 final UserManager userManager = (UserManager) context.getSystemService(
656 Context.USER_SERVICE);
657 List<UserInfo> users = userManager.getUsers(true);
658 final int currentUserId = userManager.getUserHandle();
659 final int count = users.size();
660 for (int i = 0; i < count; i++) {
661 final UserInfo user = users.get(i);
662 final UserHandle userHandle = user.getUserHandle();
Yorke Leea79e2be2014-08-10 13:52:21 -0700663 if (userManager.isUserRunning(userHandle)
664 && !userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
665 userHandle)
666 && !user.isManagedProfile()) {
Yorke Lee158c5e412014-07-16 15:31:25 -0700667 Uri uri = addEntryAndRemoveExpiredEntries(context,
668 ContentProvider.maybeAddUserId(CONTENT_URI, user.id), values);
669 if (user.id == currentUserId) {
670 result = uri;
671 }
672 }
673 }
674 } else {
Tony Makce759a12015-11-25 21:55:52 +0000675 Uri uri = CONTENT_URI;
676 if (userToBeInsertedTo != null) {
677 uri = ContentProvider
678 .maybeAddUserId(CONTENT_URI, userToBeInsertedTo.getIdentifier());
679 }
680 result = addEntryAndRemoveExpiredEntries(context, uri, values);
Yorke Lee158c5e412014-07-16 15:31:25 -0700681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 return result;
683 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800684
685 /**
686 * Query the call log database for the last dialed number.
687 * @param context Used to get the content resolver.
688 * @return The last phone number dialed (outgoing) or an empty
689 * string if none exist yet.
690 */
691 public static String getLastOutgoingCall(Context context) {
692 final ContentResolver resolver = context.getContentResolver();
693 Cursor c = null;
694 try {
695 c = resolver.query(
696 CONTENT_URI,
697 new String[] {NUMBER},
698 TYPE + " = " + OUTGOING_TYPE,
699 null,
700 DEFAULT_SORT_ORDER + " LIMIT 1");
701 if (c == null || !c.moveToFirst()) {
702 return "";
703 }
704 return c.getString(0);
705 } finally {
706 if (c != null) c.close();
707 }
708 }
709
Yorke Lee158c5e412014-07-16 15:31:25 -0700710 private static Uri addEntryAndRemoveExpiredEntries(Context context, Uri uri,
711 ContentValues values) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 final ContentResolver resolver = context.getContentResolver();
Yorke Lee158c5e412014-07-16 15:31:25 -0700713 Uri result = resolver.insert(uri, values);
714 resolver.delete(uri, "_id IN " +
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800715 "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 + " LIMIT -1 OFFSET 500)", null);
Yorke Lee158c5e412014-07-16 15:31:25 -0700717 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 }
Shishir Agrawal1ae88e32014-10-27 12:28:52 -0700719
720 private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) {
721 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
722 .appendPath(dataId)
723 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
724 DataUsageFeedback.USAGE_TYPE_CALL)
725 .build();
726 resolver.update(feedbackUri, new ContentValues(), null, null);
727 }
728
729 /*
730 * Update the normalized phone number for the given dataId in the ContactsProvider, based
731 * on the user's current country.
732 */
733 private static void updateNormalizedNumber(Context context, ContentResolver resolver,
734 String dataId, String number) {
735 if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) {
736 return;
737 }
738 final String countryIso = getCurrentCountryIso(context);
739 if (TextUtils.isEmpty(countryIso)) {
740 return;
741 }
742 final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number,
743 getCurrentCountryIso(context));
744 if (TextUtils.isEmpty(normalizedNumber)) {
745 return;
746 }
747 final ContentValues values = new ContentValues();
748 values.put(Phone.NORMALIZED_NUMBER, normalizedNumber);
749 resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId});
750 }
751
752 private static String getCurrentCountryIso(Context context) {
753 String countryIso = null;
754 final CountryDetector detector = (CountryDetector) context.getSystemService(
755 Context.COUNTRY_DETECTOR);
756 if (detector != null) {
757 final Country country = detector.detectCountry();
758 if (country != null) {
759 countryIso = country.getCountryIso();
760 }
761 }
762 return countryIso;
763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 }
765}