blob: 0202f91fbded0a1ce3d8973f616ef83500bae7f2 [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 Lee158c5e42014-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 Lee158c5e42014-07-16 15:31:25 -070025import android.content.pm.UserInfo;
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -080026import android.database.Cursor;
Yorke Lee3dbc1182014-08-21 09:37:22 -070027import android.location.Country;
28import android.location.CountryDetector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.net.Uri;
Yorke Lee158c5e42014-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;
Yorke Lee3dbc1182014-08-21 09:37:22 -070034import android.provider.ContactsContract.Data;
Daisuke Miyakawaf4685912011-06-25 12:31:13 -070035import android.provider.ContactsContract.DataUsageFeedback;
Evan Charlton6eb262c2014-07-19 18:18:19 -070036import android.telecomm.PhoneAccountHandle;
Yorke Lee3dbc1182014-08-21 09:37:22 -070037import android.telephony.PhoneNumberUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
Chiao Cheng509e1f12012-08-01 15:40:55 -070040import com.android.internal.telephony.CallerInfo;
41import com.android.internal.telephony.PhoneConstants;
42
Yorke Lee158c5e42014-07-16 15:31:25 -070043import java.util.List;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045/**
46 * The CallLog provider contains information about placed and received calls.
47 */
48public class CallLog {
49 public static final String AUTHORITY = "call_log";
50
51 /**
52 * The content:// style URL for this provider
53 */
54 public static final Uri CONTENT_URI =
55 Uri.parse("content://" + AUTHORITY);
56
57 /**
58 * Contains the recent calls.
59 */
60 public static class Calls implements BaseColumns {
61 /**
62 * The content:// style URL for this table
63 */
64 public static final Uri CONTENT_URI =
65 Uri.parse("content://call_log/calls");
66
67 /**
68 * The content:// style URL for filtering this table on phone numbers
69 */
70 public static final Uri CONTENT_FILTER_URI =
71 Uri.parse("content://call_log/calls/filter");
72
73 /**
Chiao Cheng509e1f12012-08-01 15:40:55 -070074 * Query parameter used to limit the number of call logs returned.
75 * <p>
76 * TYPE: integer
77 */
78 public static final String LIMIT_PARAM_KEY = "limit";
79
80 /**
81 * Query parameter used to specify the starting record to return.
82 * <p>
83 * TYPE: integer
84 */
85 public static final String OFFSET_PARAM_KEY = "offset";
86
87 /**
Flavio Lerda9ef78f02011-06-29 10:51:59 +010088 * An optional URI parameter which instructs the provider to allow the operation to be
89 * applied to voicemail records as well.
90 * <p>
91 * TYPE: Boolean
92 * <p>
93 * Using this parameter with a value of {@code true} will result in a security error if the
94 * calling package does not have appropriate permissions to access voicemails.
95 *
96 * @hide
97 */
98 public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
99
100 /**
Yorke Lee1854a602014-07-09 14:11:46 -0700101 * An optional extra used with {@link #CONTENT_TYPE Calls.CONTENT_TYPE} and
102 * {@link Intent#ACTION_VIEW} to specify that the presented list of calls should be
103 * filtered for a particular call type.
104 *
105 * Applications implementing a call log UI should check for this extra, and display a
106 * filtered list of calls based on the specified call type. If not applicable within the
107 * application's UI, it should be silently ignored.
108 *
109 * <p>
110 * The following example brings up the call log, showing only missed calls.
111 * <pre>
112 * Intent intent = new Intent(Intent.ACTION_VIEW);
113 * intent.setType(CallLog.Calls.CONTENT_TYPE);
114 * intent.putExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, CallLog.Calls.MISSED_TYPE);
115 * startActivity(intent);
116 * </pre>
117 * </p>
118 */
Yorke Lee52e77502014-08-27 16:28:12 -0700119 public static final String EXTRA_CALL_TYPE_FILTER
120 = "android.provider.extra.call_type_filter";
Yorke Lee1854a602014-07-09 14:11:46 -0700121
122 /**
Yorke Lee0a173932013-12-12 17:29:03 -0800123 * Content uri used to access call log entries, including voicemail records. You must have
Yorke Lee624d0d62014-07-23 15:23:47 -0700124 * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log, as
125 * well as READ_VOICEMAIL and WRITE_VOICEMAIL permissions to read and write voicemails.
Flavio Lerda9ef78f02011-06-29 10:51:59 +0100126 */
127 public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
128 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
129 .build();
130
131 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 * The default sort order for this table
133 */
134 public static final String DEFAULT_SORT_ORDER = "date DESC";
135
136 /**
137 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI}
138 * providing a directory of calls.
139 */
140 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
141
142 /**
143 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
144 * call.
145 */
146 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
147
148 /**
Yusuf T. Mobilef6737d32009-05-15 10:56:36 -0700149 * The type of the call (incoming, outgoing or missed).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 * <P>Type: INTEGER (int)</P>
151 */
152 public static final String TYPE = "type";
153
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100154 /** Call log type for incoming calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 public static final int INCOMING_TYPE = 1;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100156 /** Call log type for outgoing calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 public static final int OUTGOING_TYPE = 2;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100158 /** Call log type for missed calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 public static final int MISSED_TYPE = 3;
Yorke Leea5f6a932013-11-22 18:17:23 -0800160 /** Call log type for voicemails. */
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100161 public static final int VOICEMAIL_TYPE = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162
163 /**
Tyler Gunne5daf912014-07-08 15:22:55 -0700164 * Bit-mask describing features of the call (e.g. video).
165 *
166 * <P>Type: INTEGER (int)</P>
167 */
168 public static final String FEATURES = "features";
169
170 /** Call had no associated features (e.g. voice-only). */
171 public static final int FEATURES_NONE = 0x0;
172 /** Call had video. */
173 public static final int FEATURES_VIDEO = 0x1;
174
175 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 * The phone number as the user entered it.
177 * <P>Type: TEXT</P>
178 */
179 public static final String NUMBER = "number";
180
181 /**
Yorke Lee49e1cf92013-09-10 14:39:24 -0700182 * The number presenting rules set by the network.
183 *
184 * <p>
185 * Allowed values:
186 * <ul>
187 * <li>{@link #PRESENTATION_ALLOWED}</li>
188 * <li>{@link #PRESENTATION_RESTRICTED}</li>
189 * <li>{@link #PRESENTATION_UNKNOWN}</li>
190 * <li>{@link #PRESENTATION_PAYPHONE}</li>
191 * </ul>
192 * </p>
193 *
Jay Shraunerd88eb712013-06-10 10:10:11 -0700194 * <P>Type: INTEGER</P>
195 */
196 public static final String NUMBER_PRESENTATION = "presentation";
197
198 /** Number is allowed to display for caller id. */
199 public static final int PRESENTATION_ALLOWED = 1;
200 /** Number is blocked by user. */
201 public static final int PRESENTATION_RESTRICTED = 2;
202 /** Number is not specified or unknown by network. */
203 public static final int PRESENTATION_UNKNOWN = 3;
204 /** Number is a pay phone. */
205 public static final int PRESENTATION_PAYPHONE = 4;
206
207 /**
Bai Tao224744c2010-08-31 09:59:13 +0800208 * The ISO 3166-1 two letters country code of the country where the
209 * user received or made the call.
210 * <P>
211 * Type: TEXT
212 * </P>
Bai Tao224744c2010-08-31 09:59:13 +0800213 */
214 public static final String COUNTRY_ISO = "countryiso";
215
216 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 * The date the call occured, in milliseconds since the epoch
218 * <P>Type: INTEGER (long)</P>
219 */
220 public static final String DATE = "date";
221
222 /**
223 * The duration of the call in seconds
224 * <P>Type: INTEGER (long)</P>
225 */
226 public static final String DURATION = "duration";
227
228 /**
Tyler Gunne5daf912014-07-08 15:22:55 -0700229 * The data usage of the call in bytes.
230 * <P>Type: INTEGER (long)</P>
231 */
232 public static final String DATA_USAGE = "data_usage";
233
234 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 * Whether or not the call has been acknowledged
236 * <P>Type: INTEGER (boolean)</P>
237 */
238 public static final String NEW = "new";
239
240 /**
241 * The cached name associated with the phone number, if it exists.
242 * This value is not guaranteed to be current, if the contact information
243 * associated with this number has changed.
244 * <P>Type: TEXT</P>
245 */
246 public static final String CACHED_NAME = "name";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 /**
249 * The cached number type (Home, Work, etc) associated with the
250 * phone number, if it exists.
251 * This value is not guaranteed to be current, if the contact information
252 * associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800253 * <P>Type: INTEGER</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 */
255 public static final String CACHED_NUMBER_TYPE = "numbertype";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 /**
258 * The cached number label, for a custom number type, associated with the
259 * 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.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800262 * <P>Type: TEXT</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 */
264 public static final String CACHED_NUMBER_LABEL = "numberlabel";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 /**
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100267 * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}.
268 * <P>Type: TEXT</P>
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100269 */
270 public static final String VOICEMAIL_URI = "voicemail_uri";
271
272 /**
Yorke Lee7a5e5722014-07-23 19:43:39 -0700273 * Transcription of the call or voicemail entry. This will only be populated for call log
274 * entries of type {@link #VOICEMAIL_TYPE} that have valid transcriptions.
275 */
276 public static final String TRANSCRIPTION = "transcription";
277
278 /**
Flavio Lerda651212d2011-07-21 16:53:59 +0100279 * Whether this item has been read or otherwise consumed by the user.
280 * <p>
281 * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
282 * existence of the entry, this implies the user has interacted with the entry.
283 * <P>Type: INTEGER (boolean)</P>
Flavio Lerda651212d2011-07-21 16:53:59 +0100284 */
285 public static final String IS_READ = "is_read";
286
287 /**
Flavio Lerda270f9302011-08-09 12:01:13 +0100288 * A geocoded location for the number associated with this call.
289 * <p>
290 * The string represents a city, state, or country associated with the number.
291 * <P>Type: TEXT</P>
Flavio Lerda270f9302011-08-09 12:01:13 +0100292 */
293 public static final String GEOCODED_LOCATION = "geocoded_location";
294
295 /**
Flavio Lerda2d538d42011-08-16 08:29:06 +0100296 * The cached URI to look up the contact associated with the phone number, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800297 * This value may not be current if the contact information associated with this number
298 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100299 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100300 */
301 public static final String CACHED_LOOKUP_URI = "lookup_uri";
302
303 /**
304 * The cached phone number of the contact which matches this entry, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800305 * This value may not be current if the contact information associated with this number
306 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100307 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100308 */
309 public static final String CACHED_MATCHED_NUMBER = "matched_number";
310
311 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800312 * The cached normalized(E164) version of the phone number, if it exists.
313 * This value may not be current if the contact information associated with this number
314 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100315 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100316 */
317 public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
318
319 /**
320 * The cached photo id of the picture associated with the phone number, if it exists.
Yorke Leea5f6a932013-11-22 18:17:23 -0800321 * This value may not be current if the contact information associated with this number
322 * has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100323 * <P>Type: INTEGER (long)</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100324 */
325 public static final String CACHED_PHOTO_ID = "photo_id";
326
327 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800328 * The cached phone number, formatted with formatting rules based on the country the
329 * user was in when the call was made or received.
330 * This value is not guaranteed to be present, and may not be current if the contact
331 * information associated with this number
332 * has changed.
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100333 * <P>Type: TEXT</P>
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100334 */
335 public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
336
Ihab Awad9c3f1882014-06-30 21:17:13 -0700337 // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
338 // that was encoded into call log databases.
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700339
340 /**
Ihab Awad9c3f1882014-06-30 21:17:13 -0700341 * The component name of the account in string form.
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700342 * <P>Type: TEXT</P>
343 */
Ihab Awad9c3f1882014-06-30 21:17:13 -0700344 public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
345
346 /**
347 * The identifier of a account that is unique to a specified component.
348 * <P>Type: TEXT</P>
349 */
350 public static final String PHONE_ACCOUNT_ID = "subscription_id";
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700351
352 /**
Nancy Chen3a780922014-08-27 18:29:59 -0700353 * The identifier of a account that is unique to a specified component. Equivalent value
354 * to {@link #PHONE_ACCOUNT_ID}. For ContactsProvider internal use only.
355 * <P>Type: INTEGER</P>
356 *
357 * @hide
358 */
359 public static final String SUB_ID = "sub_id";
360
361 /**
Yorke Lee3dbc1182014-08-21 09:37:22 -0700362 * If a successful call is made that is longer than this duration, update the phone number
363 * in the ContactsProvider with the normalized version of the number, based on the user's
364 * current country code.
365 */
366 private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
367
368 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 * Adds a call to the call log.
370 *
371 * @param ci the CallerInfo object to get the target contact from. Can be null
372 * if the contact is unknown.
373 * @param context the context used to get the ContentResolver
374 * @param number the phone number to be added to the calls db
Jay Shraunerd88eb712013-06-10 10:10:11 -0700375 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
376 * is set by the network and denotes the number presenting rules for
The Android Open Source Project10592532009-03-18 17:39:46 -0700377 * "allowed", "payphone", "restricted" or "unknown"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 * @param callType enumerated values for "incoming", "outgoing", or "missed"
Tyler Gunne5daf912014-07-08 15:22:55 -0700379 * @param features features of the call (e.g. Video).
Evan Charlton8c8a0622014-07-20 12:31:00 -0700380 * @param accountHandle The accountHandle object identifying the provider of the call
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 * @param start time stamp for the call in milliseconds
382 * @param duration call duration in seconds
Tyler Gunne5daf912014-07-08 15:22:55 -0700383 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
384 * the call.
Yorke Lee158c5e42014-07-16 15:31:25 -0700385 * @result The URI of the call log entry belonging to the user that made or received this
386 * call.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 * {@hide}
388 */
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800389 public static Uri addCall(CallerInfo ci, Context context, String number,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700390 int presentation, int callType, int features, PhoneAccountHandle accountHandle,
Evan Charlton6eb262c2014-07-19 18:18:19 -0700391 long start, int duration, Long dataUsage) {
Yorke Lee158c5e42014-07-16 15:31:25 -0700392 return addCall(ci, context, number, presentation, callType, features, accountHandle,
393 start, duration, dataUsage, false);
394 }
395
396 /**
397 * Adds a call to the call log.
398 *
399 * @param ci the CallerInfo object to get the target contact from. Can be null
400 * if the contact is unknown.
401 * @param context the context used to get the ContentResolver
402 * @param number the phone number to be added to the calls db
403 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
404 * is set by the network and denotes the number presenting rules for
405 * "allowed", "payphone", "restricted" or "unknown"
406 * @param callType enumerated values for "incoming", "outgoing", or "missed"
407 * @param features features of the call (e.g. Video).
408 * @param accountHandle The accountHandle object identifying the provider of the call
409 * @param start time stamp for the call in milliseconds
410 * @param duration call duration in seconds
411 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
412 * the call.
413 * @param addForAllUsers If true, the call is added to the call log of all currently
414 * running users. The caller must have the MANAGE_USERS permission if this is true.
415 *
416 * @result The URI of the call log entry belonging to the user that made or received this
417 * call.
418 * {@hide}
419 */
420 public static Uri addCall(CallerInfo ci, Context context, String number,
421 int presentation, int callType, int features, PhoneAccountHandle accountHandle,
422 long start, int duration, Long dataUsage, boolean addForAllUsers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 final ContentResolver resolver = context.getContentResolver();
Jay Shraunerd88eb712013-06-10 10:10:11 -0700424 int numberPresentation = PRESENTATION_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425
Jay Shraunerd88eb712013-06-10 10:10:11 -0700426 // Remap network specified number presentation types
427 // PhoneConstants.PRESENTATION_xxx to calllog number presentation types
428 // Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
429 // from any future radio changes.
430 // If the number field is empty set the presentation type to Unknown.
Wink Savillea639b312012-07-10 12:37:54 -0700431 if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700432 numberPresentation = PRESENTATION_RESTRICTED;
Wink Savillea639b312012-07-10 12:37:54 -0700433 } else if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700434 numberPresentation = PRESENTATION_PAYPHONE;
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400435 } else if (TextUtils.isEmpty(number)
Wink Savillea639b312012-07-10 12:37:54 -0700436 || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700437 numberPresentation = PRESENTATION_UNKNOWN;
438 }
439 if (numberPresentation != PRESENTATION_ALLOWED) {
440 number = "";
441 if (ci != null) {
442 ci.name = "";
443 }
Wink Savilledda53912009-05-28 17:32:34 -0700444 }
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400445
Evan Charlton8c8a0622014-07-20 12:31:00 -0700446 // accountHandle information
Ihab Awad9c3f1882014-06-30 21:17:13 -0700447 String accountComponentString = null;
448 String accountId = null;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700449 if (accountHandle != null) {
450 accountComponentString = accountHandle.getComponentName().flattenToString();
451 accountId = accountHandle.getId();
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700452 }
453
Jay Shraunerd88eb712013-06-10 10:10:11 -0700454 ContentValues values = new ContentValues(6);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455
456 values.put(NUMBER, number);
Jay Shraunerd88eb712013-06-10 10:10:11 -0700457 values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 values.put(TYPE, Integer.valueOf(callType));
Tyler Gunne5daf912014-07-08 15:22:55 -0700459 values.put(FEATURES, features);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 values.put(DATE, Long.valueOf(start));
461 values.put(DURATION, Long.valueOf(duration));
Tyler Gunne5daf912014-07-08 15:22:55 -0700462 if (dataUsage != null) {
463 values.put(DATA_USAGE, dataUsage);
464 }
Ihab Awad9c3f1882014-06-30 21:17:13 -0700465 values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
466 values.put(PHONE_ACCOUNT_ID, accountId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 values.put(NEW, Integer.valueOf(1));
Debashish Chatterjee4efaf4b2011-08-11 16:47:16 +0100468 if (callType == MISSED_TYPE) {
469 values.put(IS_READ, Integer.valueOf(0));
470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 if (ci != null) {
472 values.put(CACHED_NAME, ci.name);
473 values.put(CACHED_NUMBER_TYPE, ci.numberType);
474 values.put(CACHED_NUMBER_LABEL, ci.numberLabel);
475 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800476
Makoto Onukia2295e62014-07-10 15:32:16 -0700477 if ((ci != null) && (ci.contactIdOrZero > 0)) {
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700478 // Update usage information for the number associated with the contact ID.
479 // We need to use both the number and the ID for obtaining a data ID since other
480 // contacts may have the same number.
481
482 final Cursor cursor;
483
484 // We should prefer normalized one (probably coming from
485 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
486 if (ci.normalizedNumber != null) {
487 final String normalizedPhoneNumber = ci.normalizedNumber;
488 cursor = resolver.query(Phone.CONTENT_URI,
489 new String[] { Phone._ID },
490 Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
Makoto Onukia2295e62014-07-10 15:32:16 -0700491 new String[] { String.valueOf(ci.contactIdOrZero),
492 normalizedPhoneNumber},
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700493 null);
494 } else {
495 final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700496 cursor = resolver.query(
497 Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
498 Uri.encode(phoneNumber)),
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700499 new String[] { Phone._ID },
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700500 Phone.CONTACT_ID + " =?",
Makoto Onukia2295e62014-07-10 15:32:16 -0700501 new String[] { String.valueOf(ci.contactIdOrZero) },
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700502 null);
503 }
504
505 if (cursor != null) {
506 try {
507 if (cursor.getCount() > 0 && cursor.moveToFirst()) {
Yorke Lee3dbc1182014-08-21 09:37:22 -0700508 final String dataId = cursor.getString(0);
509 updateDataUsageStatForData(resolver, dataId);
510 if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS
511 && callType == Calls.OUTGOING_TYPE
512 && TextUtils.isEmpty(ci.normalizedNumber)) {
513 updateNormalizedNumber(context, resolver, dataId, number);
514 }
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700515 }
516 } finally {
517 cursor.close();
518 }
519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800521
Yorke Lee158c5e42014-07-16 15:31:25 -0700522 Uri result = null;
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800523
Yorke Lee158c5e42014-07-16 15:31:25 -0700524 if (addForAllUsers) {
525 // Insert the entry for all currently running users, in order to trigger any
526 // ContentObservers currently set on the call log.
527 final UserManager userManager = (UserManager) context.getSystemService(
528 Context.USER_SERVICE);
529 List<UserInfo> users = userManager.getUsers(true);
530 final int currentUserId = userManager.getUserHandle();
531 final int count = users.size();
532 for (int i = 0; i < count; i++) {
533 final UserInfo user = users.get(i);
534 final UserHandle userHandle = user.getUserHandle();
Yorke Leea79e2be2014-08-10 13:52:21 -0700535 if (userManager.isUserRunning(userHandle)
536 && !userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
537 userHandle)
538 && !user.isManagedProfile()) {
Yorke Lee158c5e42014-07-16 15:31:25 -0700539 Uri uri = addEntryAndRemoveExpiredEntries(context,
540 ContentProvider.maybeAddUserId(CONTENT_URI, user.id), values);
541 if (user.id == currentUserId) {
542 result = uri;
543 }
544 }
545 }
546 } else {
547 result = addEntryAndRemoveExpiredEntries(context, CONTENT_URI, values);
548 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 return result;
551 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800552
553 /**
554 * Query the call log database for the last dialed number.
555 * @param context Used to get the content resolver.
556 * @return The last phone number dialed (outgoing) or an empty
557 * string if none exist yet.
558 */
559 public static String getLastOutgoingCall(Context context) {
560 final ContentResolver resolver = context.getContentResolver();
561 Cursor c = null;
562 try {
563 c = resolver.query(
564 CONTENT_URI,
565 new String[] {NUMBER},
566 TYPE + " = " + OUTGOING_TYPE,
567 null,
568 DEFAULT_SORT_ORDER + " LIMIT 1");
569 if (c == null || !c.moveToFirst()) {
570 return "";
571 }
572 return c.getString(0);
573 } finally {
574 if (c != null) c.close();
575 }
576 }
577
Yorke Lee158c5e42014-07-16 15:31:25 -0700578 private static Uri addEntryAndRemoveExpiredEntries(Context context, Uri uri,
579 ContentValues values) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 final ContentResolver resolver = context.getContentResolver();
Yorke Lee158c5e42014-07-16 15:31:25 -0700581 Uri result = resolver.insert(uri, values);
582 resolver.delete(uri, "_id IN " +
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800583 "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 + " LIMIT -1 OFFSET 500)", null);
Yorke Lee158c5e42014-07-16 15:31:25 -0700585 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 }
Yorke Lee3dbc1182014-08-21 09:37:22 -0700587
588 private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) {
589 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
590 .appendPath(dataId)
591 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
592 DataUsageFeedback.USAGE_TYPE_CALL)
593 .build();
594 resolver.update(feedbackUri, new ContentValues(), null, null);
595 }
596
597 /**
598 * Update the normalized phone number for the given dataId in the ContactsProvider, based
599 * on the user's current country.
600 */
601 private static void updateNormalizedNumber(Context context, ContentResolver resolver,
602 String dataId, String number) {
603 if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) {
604 return;
605 }
606
607 final String countryIso = getCurrentCountryIso(context);
608 if (TextUtils.isEmpty(countryIso)) {
609 return;
610 }
611
612 final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number,
613 getCurrentCountryIso(context));
614 if (TextUtils.isEmpty(normalizedNumber)) {
615 return;
616 }
617
618 final ContentValues values = new ContentValues();
619 values.put(Phone.NORMALIZED_NUMBER, normalizedNumber);
620 resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId});
621 }
622
623 private static String getCurrentCountryIso(Context context) {
624 String countryIso = null;
625 final CountryDetector detector = (CountryDetector) context.getSystemService(
626 Context.COUNTRY_DETECTOR);
627 if (detector != null) {
628 final Country country = detector.detectCountry();
629 if (country != null) {
630 countryIso = country.getCountryIso();
631 }
632 }
633 return countryIso;
634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 }
636}