blob: 60df467bc20fc0a0063a3871324605609538fbb0 [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;
Makoto Onukib5247412016-01-12 12:57:25 -080041import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042
Chiao Cheng509e1f12012-08-01 15:40:55 -070043import com.android.internal.telephony.CallerInfo;
44import com.android.internal.telephony.PhoneConstants;
45
Yorke Lee158c5e412014-07-16 15:31:25 -070046import java.util.List;
47
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048/**
49 * The CallLog provider contains information about placed and received calls.
50 */
51public class CallLog {
Santos Cordonc66f3ba2015-02-27 15:22:07 -080052 private static final String LOG_TAG = "CallLog";
Makoto Onukib5247412016-01-12 12:57:25 -080053 private static final boolean VERBOSE_LOG = false; // DON'T SUBMIT WITH TRUE.
Santos Cordonc66f3ba2015-02-27 15:22:07 -080054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 public static final String AUTHORITY = "call_log";
56
57 /**
58 * The content:// style URL for this provider
59 */
60 public static final Uri CONTENT_URI =
61 Uri.parse("content://" + AUTHORITY);
62
Makoto Onukib5247412016-01-12 12:57:25 -080063
64 /**
65 * The "shadow" provider stores calllog when the real calllog provider is encrypted. The
66 * real provider will alter copy from it when it starts, and remove the entries in the shadow.
67 *
68 * <p>See the comment in {@link Calls#addCall} for the details.
69 *
70 * @hide
71 */
72 public static final String SHADOW_AUTHORITY = "call_log_shadow";
73
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 /**
75 * Contains the recent calls.
76 */
77 public static class Calls implements BaseColumns {
78 /**
79 * The content:// style URL for this table
80 */
81 public static final Uri CONTENT_URI =
82 Uri.parse("content://call_log/calls");
83
Makoto Onukib5247412016-01-12 12:57:25 -080084 /** @hide */
85 public static final Uri SHADOW_CONTENT_URI =
86 Uri.parse("content://call_log_shadow/calls");
87
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 /**
89 * The content:// style URL for filtering this table on phone numbers
90 */
91 public static final Uri CONTENT_FILTER_URI =
92 Uri.parse("content://call_log/calls/filter");
93
94 /**
Chiao Cheng509e1f12012-08-01 15:40:55 -070095 * Query parameter used to limit the number of call logs returned.
96 * <p>
97 * TYPE: integer
98 */
99 public static final String LIMIT_PARAM_KEY = "limit";
100
101 /**
102 * Query parameter used to specify the starting record to return.
103 * <p>
104 * TYPE: integer
105 */
106 public static final String OFFSET_PARAM_KEY = "offset";
107
108 /**
Flavio Lerda9ef78f02011-06-29 10:51:59 +0100109 * An optional URI parameter which instructs the provider to allow the operation to be
110 * applied to voicemail records as well.
111 * <p>
112 * TYPE: Boolean
113 * <p>
114 * Using this parameter with a value of {@code true} will result in a security error if the
115 * calling package does not have appropriate permissions to access voicemails.
116 *
117 * @hide
118 */
119 public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
120
121 /**
Yorke Lee1854a602014-07-09 14:11:46 -0700122 * An optional extra used with {@link #CONTENT_TYPE Calls.CONTENT_TYPE} and
123 * {@link Intent#ACTION_VIEW} to specify that the presented list of calls should be
124 * filtered for a particular call type.
125 *
126 * Applications implementing a call log UI should check for this extra, and display a
127 * filtered list of calls based on the specified call type. If not applicable within the
128 * application's UI, it should be silently ignored.
129 *
130 * <p>
131 * The following example brings up the call log, showing only missed calls.
132 * <pre>
133 * Intent intent = new Intent(Intent.ACTION_VIEW);
134 * intent.setType(CallLog.Calls.CONTENT_TYPE);
135 * intent.putExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, CallLog.Calls.MISSED_TYPE);
136 * startActivity(intent);
137 * </pre>
138 * </p>
139 */
Yorke Lee78814622014-09-04 16:07:50 -0700140 public static final String EXTRA_CALL_TYPE_FILTER =
141 "android.provider.extra.CALL_TYPE_FILTER";
Yorke Lee1854a602014-07-09 14:11:46 -0700142
143 /**
Yorke Lee0a173932013-12-12 17:29:03 -0800144 * Content uri used to access call log entries, including voicemail records. You must have
Yorke Lee624d0d62014-07-23 15:23:47 -0700145 * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log, as
146 * well as READ_VOICEMAIL and WRITE_VOICEMAIL permissions to read and write voicemails.
Flavio Lerda9ef78f02011-06-29 10:51:59 +0100147 */
148 public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
149 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
150 .build();
151
152 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 * The default sort order for this table
154 */
155 public static final String DEFAULT_SORT_ORDER = "date DESC";
156
157 /**
158 * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI}
159 * providing a directory of calls.
160 */
161 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
162
163 /**
164 * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
165 * call.
166 */
167 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
168
169 /**
Yusuf T. Mobilef6737d32009-05-15 10:56:36 -0700170 * The type of the call (incoming, outgoing or missed).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 * <P>Type: INTEGER (int)</P>
Andrew Leef61b1fc2015-09-25 21:11:19 -0700172 *
173 * <p>
174 * Allowed values:
175 * <ul>
176 * <li>{@link #INCOMING_TYPE}</li>
177 * <li>{@link #OUTGOING_TYPE}</li>
178 * <li>{@link #MISSED_TYPE}</li>
179 * <li>{@link #VOICEMAIL_TYPE}</li>
180 * <li>{@link #REJECTED_TYPE}</li>
181 * <li>{@link #BLOCKED_TYPE}</li>
Tyler Gunn2cbe2b52016-05-04 15:48:10 +0000182 * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li>
Andrew Leef61b1fc2015-09-25 21:11:19 -0700183 * </ul>
184 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 */
186 public static final String TYPE = "type";
187
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100188 /** Call log type for incoming calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 public static final int INCOMING_TYPE = 1;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100190 /** Call log type for outgoing calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 public static final int OUTGOING_TYPE = 2;
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100192 /** Call log type for missed calls. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 public static final int MISSED_TYPE = 3;
Yorke Leea5f6a932013-11-22 18:17:23 -0800194 /** Call log type for voicemails. */
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100195 public static final int VOICEMAIL_TYPE = 4;
Andrew Leef61b1fc2015-09-25 21:11:19 -0700196 /** Call log type for calls rejected by direct user action. */
197 public static final int REJECTED_TYPE = 5;
198 /** Call log type for calls blocked automatically. */
199 public static final int BLOCKED_TYPE = 6;
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700200 /**
201 * Call log type for a call which was answered on another device. Used in situations where
202 * a call rings on multiple devices simultaneously and it ended up being answered on a
203 * device other than the current one.
204 */
205 public static final int ANSWERED_EXTERNALLY_TYPE = 7;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 /**
Tyler Gunne5daf912014-07-08 15:22:55 -0700208 * Bit-mask describing features of the call (e.g. video).
209 *
210 * <P>Type: INTEGER (int)</P>
211 */
212 public static final String FEATURES = "features";
213
Tyler Gunne5daf912014-07-08 15:22:55 -0700214 /** Call had video. */
Hall Liu4d31ab22017-11-20 17:44:38 -0800215 public static final int FEATURES_VIDEO = 1 << 0;
Tyler Gunne5daf912014-07-08 15:22:55 -0700216
Tyler Gunn2cbe2b52016-05-04 15:48:10 +0000217 /** Call was pulled externally. */
Hall Liu4d31ab22017-11-20 17:44:38 -0800218 public static final int FEATURES_PULLED_EXTERNALLY = 1 << 1;
Tyler Gunn876dbfb2016-03-14 15:18:07 -0700219
BIN ZHOUb4df7b22017-03-31 11:54:04 -0500220 /** Call was HD. */
Hall Liu4d31ab22017-11-20 17:44:38 -0800221 public static final int FEATURES_HD_CALL = 1 << 2;
BIN ZHOUb4df7b22017-03-31 11:54:04 -0500222
223 /** Call was WIFI call. */
Hall Liu4d31ab22017-11-20 17:44:38 -0800224 public static final int FEATURES_WIFI = 1 << 3;
225
226 /** Call was on RTT at some point */
227 public static final int FEATURES_RTT = 1 << 4;
BIN ZHOUb4df7b22017-03-31 11:54:04 -0500228
Tyler Gunne5daf912014-07-08 15:22:55 -0700229 /**
Eric Erfanianec881872017-12-06 16:27:53 -0800230 * Indicates the call underwent Assisted Dialing.
231 * @hide
232 */
233 public static final Integer FEATURES_ASSISTED_DIALING_USED = 0x10;
234
235 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 * The phone number as the user entered it.
237 * <P>Type: TEXT</P>
238 */
239 public static final String NUMBER = "number";
240
241 /**
Yorke Lee49e1cf92013-09-10 14:39:24 -0700242 * The number presenting rules set by the network.
243 *
244 * <p>
245 * Allowed values:
246 * <ul>
247 * <li>{@link #PRESENTATION_ALLOWED}</li>
248 * <li>{@link #PRESENTATION_RESTRICTED}</li>
249 * <li>{@link #PRESENTATION_UNKNOWN}</li>
250 * <li>{@link #PRESENTATION_PAYPHONE}</li>
251 * </ul>
252 * </p>
253 *
Jay Shraunerd88eb712013-06-10 10:10:11 -0700254 * <P>Type: INTEGER</P>
255 */
256 public static final String NUMBER_PRESENTATION = "presentation";
257
258 /** Number is allowed to display for caller id. */
259 public static final int PRESENTATION_ALLOWED = 1;
260 /** Number is blocked by user. */
261 public static final int PRESENTATION_RESTRICTED = 2;
262 /** Number is not specified or unknown by network. */
263 public static final int PRESENTATION_UNKNOWN = 3;
264 /** Number is a pay phone. */
265 public static final int PRESENTATION_PAYPHONE = 4;
266
267 /**
Bai Tao224744c2010-08-31 09:59:13 +0800268 * The ISO 3166-1 two letters country code of the country where the
269 * user received or made the call.
270 * <P>
271 * Type: TEXT
272 * </P>
Bai Tao224744c2010-08-31 09:59:13 +0800273 */
274 public static final String COUNTRY_ISO = "countryiso";
275
276 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 * The date the call occured, in milliseconds since the epoch
278 * <P>Type: INTEGER (long)</P>
279 */
280 public static final String DATE = "date";
281
282 /**
283 * The duration of the call in seconds
284 * <P>Type: INTEGER (long)</P>
285 */
286 public static final String DURATION = "duration";
287
288 /**
Tyler Gunne5daf912014-07-08 15:22:55 -0700289 * The data usage of the call in bytes.
290 * <P>Type: INTEGER (long)</P>
291 */
292 public static final String DATA_USAGE = "data_usage";
293
294 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 * Whether or not the call has been acknowledged
296 * <P>Type: INTEGER (boolean)</P>
297 */
298 public static final String NEW = "new";
299
300 /**
301 * The cached name associated with the phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700302 *
303 * <p>This value is typically filled in by the dialer app for the caching purpose,
304 * so it's not guaranteed to be present, and may not be current if the contact
305 * information associated with this number has changed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 * <P>Type: TEXT</P>
307 */
308 public static final String CACHED_NAME = "name";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 /**
311 * The cached number type (Home, Work, etc) associated with the
312 * phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700313 *
314 * <p>This value is typically filled in by the dialer app for the caching purpose,
315 * so it's not guaranteed to be present, and may not be current if the contact
316 * information associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800317 * <P>Type: INTEGER</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 */
319 public static final String CACHED_NUMBER_TYPE = "numbertype";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 /**
322 * The cached number label, for a custom number type, associated with the
323 * phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700324 *
325 * <p>This value is typically filled in by the dialer app for the caching purpose,
326 * so it's not guaranteed to be present, and may not be current if the contact
327 * information associated with this number has changed.
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800328 * <P>Type: TEXT</P>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 */
330 public static final String CACHED_NUMBER_LABEL = "numberlabel";
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 /**
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100333 * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}.
334 * <P>Type: TEXT</P>
Debashish Chatterjee412359f2011-06-06 17:35:59 +0100335 */
336 public static final String VOICEMAIL_URI = "voicemail_uri";
337
338 /**
Yorke Lee7a5e5722014-07-23 19:43:39 -0700339 * Transcription of the call or voicemail entry. This will only be populated for call log
340 * entries of type {@link #VOICEMAIL_TYPE} that have valid transcriptions.
341 */
342 public static final String TRANSCRIPTION = "transcription";
343
344 /**
mike dooley47ed9b02017-04-18 14:16:48 -0700345 * State of voicemail transcription entry. This will only be populated for call log
346 * entries of type {@link #VOICEMAIL_TYPE}.
347 * @hide
348 */
349 public static final String TRANSCRIPTION_STATE = "transcription_state";
350
351 /**
Flavio Lerda651212d2011-07-21 16:53:59 +0100352 * Whether this item has been read or otherwise consumed by the user.
353 * <p>
354 * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
355 * existence of the entry, this implies the user has interacted with the entry.
356 * <P>Type: INTEGER (boolean)</P>
Flavio Lerda651212d2011-07-21 16:53:59 +0100357 */
358 public static final String IS_READ = "is_read";
359
360 /**
Flavio Lerda270f9302011-08-09 12:01:13 +0100361 * A geocoded location for the number associated with this call.
362 * <p>
363 * The string represents a city, state, or country associated with the number.
364 * <P>Type: TEXT</P>
Flavio Lerda270f9302011-08-09 12:01:13 +0100365 */
366 public static final String GEOCODED_LOCATION = "geocoded_location";
367
368 /**
Flavio Lerda2d538d42011-08-16 08:29:06 +0100369 * The cached URI to look up the contact associated with the phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700370 *
371 * <p>This value is typically filled in by the dialer app for the caching purpose,
372 * so it's not guaranteed to be present, and may not be current if the contact
373 * information associated with this number has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100374 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100375 */
376 public static final String CACHED_LOOKUP_URI = "lookup_uri";
377
378 /**
379 * The cached phone number of the contact which matches this entry, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700380 *
381 * <p>This value is typically filled in by the dialer app for the caching purpose,
382 * so it's not guaranteed to be present, and may not be current if the contact
383 * information associated with this number has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100384 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100385 */
386 public static final String CACHED_MATCHED_NUMBER = "matched_number";
387
388 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800389 * The cached normalized(E164) version of the phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700390 *
391 * <p>This value is typically filled in by the dialer app for the caching purpose,
392 * so it's not guaranteed to be present, and may not be current if the contact
393 * information associated with this number has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100394 * <P>Type: TEXT</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100395 */
396 public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
397
398 /**
399 * The cached photo id of the picture associated with the phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700400 *
401 * <p>This value is typically filled in by the dialer app for the caching purpose,
402 * so it's not guaranteed to be present, and may not be current if the contact
403 * information associated with this number has changed.
Flavio Lerda2d538d42011-08-16 08:29:06 +0100404 * <P>Type: INTEGER (long)</P>
Flavio Lerda2d538d42011-08-16 08:29:06 +0100405 */
406 public static final String CACHED_PHOTO_ID = "photo_id";
407
408 /**
Makoto Onukiedb84502015-03-09 13:57:02 -0700409 * The cached photo URI of the picture associated with the phone number, if it exists.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700410 *
411 * <p>This value is typically filled in by the dialer app for the caching purpose,
412 * so it's not guaranteed to be present, and may not be current if the contact
413 * information associated with this number has changed.
Makoto Onukiedb84502015-03-09 13:57:02 -0700414 * <P>Type: TEXT (URI)</P>
415 */
416 public static final String CACHED_PHOTO_URI = "photo_uri";
417
418 /**
Yorke Leea5f6a932013-11-22 18:17:23 -0800419 * The cached phone number, formatted with formatting rules based on the country the
420 * user was in when the call was made or received.
Makoto Onuki93d94eb2016-08-25 14:24:03 -0700421 *
422 * <p>This value is typically filled in by the dialer app for the caching purpose,
423 * so it's not guaranteed to be present, and may not be current if the contact
424 * information associated with this number has changed.
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100425 * <P>Type: TEXT</P>
Flavio Lerda0fce15b2011-10-01 18:55:33 +0100426 */
427 public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
428
Ihab Awad9c3f1882014-06-30 21:17:13 -0700429 // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
430 // that was encoded into call log databases.
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700431
432 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800433 * The component name of the account used to place or receive the call; in string form.
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700434 * <P>Type: TEXT</P>
435 */
Ihab Awad9c3f1882014-06-30 21:17:13 -0700436 public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
437
438 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800439 * The identifier for the account used to place or receive the call.
Ihab Awad9c3f1882014-06-30 21:17:13 -0700440 * <P>Type: TEXT</P>
441 */
442 public static final String PHONE_ACCOUNT_ID = "subscription_id";
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700443
444 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800445 * The address associated with the account used to place or receive the call; in string
446 * form. For SIM-based calls, this is the user's own phone number.
447 * <P>Type: TEXT</P>
448 *
449 * @hide
450 */
451 public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
452
453 /**
Santos Cordon2d2bc162015-02-27 15:22:07 -0800454 * Indicates that the entry will be hidden from all queries until the associated
455 * {@link android.telecom.PhoneAccount} is registered with the system.
456 * <P>Type: INTEGER</P>
457 *
458 * @hide
459 */
460 public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden";
461
462 /**
Santos Cordon204f80e2015-02-11 22:57:14 -0800463 * The subscription ID used to place this call. This is no longer used and has been
464 * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
465 * For ContactsProvider internal use only.
Nancy Chen3a780922014-08-27 18:29:59 -0700466 * <P>Type: INTEGER</P>
467 *
Santos Cordon204f80e2015-02-11 22:57:14 -0800468 * @Deprecated
Nancy Chen3a780922014-08-27 18:29:59 -0700469 * @hide
470 */
471 public static final String SUB_ID = "sub_id";
472
473 /**
Hall Liu594c7912015-10-14 15:13:51 -0700474 * The post-dial portion of a dialed number, including any digits dialed after a
475 * {@link TelecomManager#DTMF_CHARACTER_PAUSE} or a {@link
476 * TelecomManager#DTMF_CHARACTER_WAIT} and these characters themselves.
477 * <P>Type: TEXT</P>
478 */
479 public static final String POST_DIAL_DIGITS = "post_dial_digits";
480
481 /**
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700482 * For an incoming call, the secondary line number the call was received via.
483 * When a SIM card has multiple phone numbers associated with it, the via number indicates
484 * which of the numbers associated with the SIM was called.
485 */
486 public static final String VIA_NUMBER = "via_number";
487
488 /**
Tony Makce759a12015-11-25 21:55:52 +0000489 * Indicates that the entry will be copied from primary user to other users.
490 * <P>Type: INTEGER</P>
491 *
492 * @hide
493 */
494 public static final String ADD_FOR_ALL_USERS = "add_for_all_users";
495
496 /**
Ta-wei Yena07707a2015-12-11 11:46:58 -0800497 * The date the row is last inserted, updated, or marked as deleted, in milliseconds
498 * since the epoch. Read only.
499 * <P>Type: INTEGER (long)</P>
500 */
501 public static final String LAST_MODIFIED = "last_modified";
502
503 /**
Yorke Lee3dbc1182014-08-21 09:37:22 -0700504 * If a successful call is made that is longer than this duration, update the phone number
505 * in the ContactsProvider with the normalized version of the number, based on the user's
506 * current country code.
507 */
508 private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
509
510 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 * Adds a call to the call log.
512 *
513 * @param ci the CallerInfo object to get the target contact from. Can be null
514 * if the contact is unknown.
515 * @param context the context used to get the ContentResolver
516 * @param number the phone number to be added to the calls db
Jay Shraunerd88eb712013-06-10 10:10:11 -0700517 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
518 * is set by the network and denotes the number presenting rules for
The Android Open Source Project10592532009-03-18 17:39:46 -0700519 * "allowed", "payphone", "restricted" or "unknown"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 * @param callType enumerated values for "incoming", "outgoing", or "missed"
Tyler Gunne5daf912014-07-08 15:22:55 -0700521 * @param features features of the call (e.g. Video).
Evan Charlton8c8a0622014-07-20 12:31:00 -0700522 * @param accountHandle The accountHandle object identifying the provider of the call
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 * @param start time stamp for the call in milliseconds
524 * @param duration call duration in seconds
Tyler Gunne5daf912014-07-08 15:22:55 -0700525 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
526 * the call.
Yorke Lee158c5e412014-07-16 15:31:25 -0700527 * @result The URI of the call log entry belonging to the user that made or received this
528 * call.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 * {@hide}
530 */
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800531 public static Uri addCall(CallerInfo ci, Context context, String number,
Evan Charlton8c8a0622014-07-20 12:31:00 -0700532 int presentation, int callType, int features, PhoneAccountHandle accountHandle,
Evan Charlton6eb262c2014-07-19 18:18:19 -0700533 long start, int duration, Long dataUsage) {
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700534 return addCall(ci, context, number, /* postDialDigits =*/ "", /* viaNumber =*/ "",
535 presentation, callType, features, accountHandle, start, duration,
536 dataUsage, /* addForAllUsers =*/ false, /* userToBeInsertedTo =*/ null,
537 /* is_read =*/ false);
Yorke Lee158c5e412014-07-16 15:31:25 -0700538 }
539
Wink Saville05e6dde2014-08-31 19:24:10 -0700540
Yorke Lee158c5e412014-07-16 15:31:25 -0700541 /**
542 * Adds a call to the call log.
543 *
544 * @param ci the CallerInfo object to get the target contact from. Can be null
545 * if the contact is unknown.
546 * @param context the context used to get the ContentResolver
547 * @param number the phone number to be added to the calls db
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700548 * @param viaNumber the secondary number that the incoming call received with. If the
549 * call was received with the SIM assigned number, then this field must be ''.
Yorke Lee158c5e412014-07-16 15:31:25 -0700550 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
551 * is set by the network and denotes the number presenting rules for
552 * "allowed", "payphone", "restricted" or "unknown"
553 * @param callType enumerated values for "incoming", "outgoing", or "missed"
554 * @param features features of the call (e.g. Video).
555 * @param accountHandle The accountHandle object identifying the provider of the call
556 * @param start time stamp for the call in milliseconds
557 * @param duration call duration in seconds
558 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
559 * the call.
560 * @param addForAllUsers If true, the call is added to the call log of all currently
561 * running users. The caller must have the MANAGE_USERS permission if this is true.
Tony Makce759a12015-11-25 21:55:52 +0000562 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
563 * inserted to. null if it is inserted to the current user. The
564 * value is ignored if @{link addForAllUsers} is true.
Yorke Lee158c5e412014-07-16 15:31:25 -0700565 * @result The URI of the call log entry belonging to the user that made or received this
566 * call.
567 * {@hide}
568 */
569 public static Uri addCall(CallerInfo ci, Context context, String number,
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700570 String postDialDigits, String viaNumber, int presentation, int callType,
571 int features, PhoneAccountHandle accountHandle, long start, int duration,
572 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo) {
573 return addCall(ci, context, number, postDialDigits, viaNumber, presentation, callType,
574 features, accountHandle, start, duration, dataUsage, addForAllUsers,
575 userToBeInsertedTo, /* is_read =*/ false);
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700576 }
577
578 /**
579 * Adds a call to the call log.
580 *
581 * @param ci the CallerInfo object to get the target contact from. Can be null
582 * if the contact is unknown.
583 * @param context the context used to get the ContentResolver
584 * @param number the phone number to be added to the calls db
Hall Liu594c7912015-10-14 15:13:51 -0700585 * @param postDialDigits the post-dial digits that were dialed after the number,
586 * if it was outgoing. Otherwise it is ''.
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700587 * @param viaNumber the secondary number that the incoming call received with. If the
588 * call was received with the SIM assigned number, then this field must be ''.
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700589 * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
590 * is set by the network and denotes the number presenting rules for
591 * "allowed", "payphone", "restricted" or "unknown"
592 * @param callType enumerated values for "incoming", "outgoing", or "missed"
593 * @param features features of the call (e.g. Video).
594 * @param accountHandle The accountHandle object identifying the provider of the call
595 * @param start time stamp for the call in milliseconds
596 * @param duration call duration in seconds
597 * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
598 * the call.
599 * @param addForAllUsers If true, the call is added to the call log of all currently
600 * running users. The caller must have the MANAGE_USERS permission if this is true.
Tony Makce759a12015-11-25 21:55:52 +0000601 * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
602 * inserted to. null if it is inserted to the current user. The
603 * value is ignored if @{link addForAllUsers} is true.
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700604 * @param is_read Flag to show if the missed call log has been read by the user or not.
605 * Used for call log restore of missed calls.
606 *
607 * @result The URI of the call log entry belonging to the user that made or received this
Makoto Onukib5247412016-01-12 12:57:25 -0800608 * call. This could be of the shadow provider. Do not return it to non-system apps,
609 * as they don't have permissions.
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700610 * {@hide}
611 */
612 public static Uri addCall(CallerInfo ci, Context context, String number,
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700613 String postDialDigits, String viaNumber, int presentation, int callType,
614 int features, PhoneAccountHandle accountHandle, long start, int duration,
615 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo,
616 boolean is_read) {
Makoto Onukib5247412016-01-12 12:57:25 -0800617 if (VERBOSE_LOG) {
618 Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
619 number, userToBeInsertedTo, addForAllUsers));
620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 final ContentResolver resolver = context.getContentResolver();
Jay Shraunerd88eb712013-06-10 10:10:11 -0700622 int numberPresentation = PRESENTATION_ALLOWED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623
Santos Cordon204f80e2015-02-11 22:57:14 -0800624 TelecomManager tm = null;
625 try {
626 tm = TelecomManager.from(context);
627 } catch (UnsupportedOperationException e) {}
628
629 String accountAddress = null;
630 if (tm != null && accountHandle != null) {
631 PhoneAccount account = tm.getPhoneAccount(accountHandle);
632 if (account != null) {
Santos Cordon2d2bc162015-02-27 15:22:07 -0800633 Uri address = account.getSubscriptionAddress();
634 if (address != null) {
635 accountAddress = address.getSchemeSpecificPart();
636 }
Santos Cordon204f80e2015-02-11 22:57:14 -0800637 }
638 }
639
Jay Shraunerd88eb712013-06-10 10:10:11 -0700640 // Remap network specified number presentation types
641 // PhoneConstants.PRESENTATION_xxx to calllog number presentation types
642 // Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
643 // from any future radio changes.
644 // If the number field is empty set the presentation type to Unknown.
Wink Savillea639b312012-07-10 12:37:54 -0700645 if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700646 numberPresentation = PRESENTATION_RESTRICTED;
Wink Savillea639b312012-07-10 12:37:54 -0700647 } else if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700648 numberPresentation = PRESENTATION_PAYPHONE;
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400649 } else if (TextUtils.isEmpty(number)
Wink Savillea639b312012-07-10 12:37:54 -0700650 || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
Jay Shraunerd88eb712013-06-10 10:10:11 -0700651 numberPresentation = PRESENTATION_UNKNOWN;
652 }
653 if (numberPresentation != PRESENTATION_ALLOWED) {
654 number = "";
655 if (ci != null) {
656 ci.name = "";
657 }
Wink Savilledda53912009-05-28 17:32:34 -0700658 }
Pauyl l Bermane1dc2ba2009-07-10 18:27:36 -0400659
Evan Charlton8c8a0622014-07-20 12:31:00 -0700660 // accountHandle information
Ihab Awad9c3f1882014-06-30 21:17:13 -0700661 String accountComponentString = null;
662 String accountId = null;
Evan Charlton8c8a0622014-07-20 12:31:00 -0700663 if (accountHandle != null) {
664 accountComponentString = accountHandle.getComponentName().flattenToString();
665 accountId = accountHandle.getId();
Nancy Chen5ffbfcc2014-06-25 14:22:55 -0700666 }
667
Jay Shraunerd88eb712013-06-10 10:10:11 -0700668 ContentValues values = new ContentValues(6);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669
670 values.put(NUMBER, number);
Hall Liu594c7912015-10-14 15:13:51 -0700671 values.put(POST_DIAL_DIGITS, postDialDigits);
Brad Ebingerb3e934b2016-03-21 15:00:54 -0700672 values.put(VIA_NUMBER, viaNumber);
Jay Shraunerd88eb712013-06-10 10:10:11 -0700673 values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 values.put(TYPE, Integer.valueOf(callType));
Tyler Gunne5daf912014-07-08 15:22:55 -0700675 values.put(FEATURES, features);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 values.put(DATE, Long.valueOf(start));
677 values.put(DURATION, Long.valueOf(duration));
Tyler Gunne5daf912014-07-08 15:22:55 -0700678 if (dataUsage != null) {
679 values.put(DATA_USAGE, dataUsage);
680 }
Ihab Awad9c3f1882014-06-30 21:17:13 -0700681 values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
682 values.put(PHONE_ACCOUNT_ID, accountId);
Santos Cordon204f80e2015-02-11 22:57:14 -0800683 values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 values.put(NEW, Integer.valueOf(1));
Tony Makce759a12015-11-25 21:55:52 +0000685 values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
Wink Saville05e6dde2014-08-31 19:24:10 -0700686
Debashish Chatterjee4efaf4b2011-08-11 16:47:16 +0100687 if (callType == MISSED_TYPE) {
Roshan Pius78b8d4a2015-08-04 13:23:03 -0700688 values.put(IS_READ, Integer.valueOf(is_read ? 1 : 0));
Debashish Chatterjee4efaf4b2011-08-11 16:47:16 +0100689 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800690
Makoto Onukia2295e62014-07-10 15:32:16 -0700691 if ((ci != null) && (ci.contactIdOrZero > 0)) {
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700692 // Update usage information for the number associated with the contact ID.
693 // We need to use both the number and the ID for obtaining a data ID since other
694 // contacts may have the same number.
695
696 final Cursor cursor;
697
698 // We should prefer normalized one (probably coming from
699 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
700 if (ci.normalizedNumber != null) {
701 final String normalizedPhoneNumber = ci.normalizedNumber;
702 cursor = resolver.query(Phone.CONTENT_URI,
703 new String[] { Phone._ID },
704 Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
Makoto Onukia2295e62014-07-10 15:32:16 -0700705 new String[] { String.valueOf(ci.contactIdOrZero),
706 normalizedPhoneNumber},
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700707 null);
708 } else {
709 final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700710 cursor = resolver.query(
711 Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
712 Uri.encode(phoneNumber)),
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700713 new String[] { Phone._ID },
Daisuke Miyakawae23362a2012-05-06 16:54:25 -0700714 Phone.CONTACT_ID + " =?",
Makoto Onukia2295e62014-07-10 15:32:16 -0700715 new String[] { String.valueOf(ci.contactIdOrZero) },
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700716 null);
717 }
718
719 if (cursor != null) {
720 try {
721 if (cursor.getCount() > 0 && cursor.moveToFirst()) {
Shishir Agrawal1ae88e32014-10-27 12:28:52 -0700722 final String dataId = cursor.getString(0);
723 updateDataUsageStatForData(resolver, dataId);
724 if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS
725 && callType == Calls.OUTGOING_TYPE
726 && TextUtils.isEmpty(ci.normalizedNumber)) {
727 updateNormalizedNumber(context, resolver, dataId, number);
728 }
Daisuke Miyakawaf4685912011-06-25 12:31:13 -0700729 }
730 } finally {
731 cursor.close();
732 }
733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800735
Makoto Onukib5247412016-01-12 12:57:25 -0800736 /*
737 Writing the calllog works in the following way:
738 - All user entries
739 - if user-0 is encrypted, insert to user-0's shadow only.
740 (other users should also be encrypted, so nothing to do for other users.)
741 - if user-0 is decrypted, insert to user-0's real provider, as well as
742 all other users that are running and decrypted and should have calllog.
743
744 - Single user entry.
745 - If the target user is encryted, insert to its shadow.
746 - Otherwise insert to its real provider.
747
748 When the (real) calllog provider starts, it copies entries that it missed from
749 elsewhere.
750 - When user-0's (real) provider starts, it copies from user-0's shadow, and clears
751 the shadow.
752
753 - When other users (real) providers start, unless it shouldn't have calllog entries,
754 - Copy from the user's shadow, and clears the shadow.
755 - Copy from user-0's entries that are FOR_ALL_USERS = 1. (and don't clear it.)
756 */
757
Yorke Lee158c5e412014-07-16 15:31:25 -0700758 Uri result = null;
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800759
Makoto Onukib5247412016-01-12 12:57:25 -0800760 final UserManager userManager = context.getSystemService(UserManager.class);
761 final int currentUserId = userManager.getUserHandle();
762
Yorke Lee158c5e412014-07-16 15:31:25 -0700763 if (addForAllUsers) {
Makoto Onukib5247412016-01-12 12:57:25 -0800764 // First, insert to the system user.
765 final Uri uriForSystem = addEntryAndRemoveExpiredEntries(
766 context, userManager, UserHandle.SYSTEM, values);
767 if (uriForSystem == null
768 || SHADOW_AUTHORITY.equals(uriForSystem.getAuthority())) {
769 // This means the system user is still encrypted and the entry has inserted
770 // into the shadow. This means other users are still all encrypted.
771 // Nothing further to do; just return null.
772 return null;
773 }
774 if (UserHandle.USER_SYSTEM == currentUserId) {
775 result = uriForSystem;
776 }
777
778 // Otherwise, insert to all other users that are running and unlocked.
779
780 final List<UserInfo> users = userManager.getUsers(true);
781
Yorke Lee158c5e412014-07-16 15:31:25 -0700782 final int count = users.size();
783 for (int i = 0; i < count; i++) {
Makoto Onukib5247412016-01-12 12:57:25 -0800784 final UserInfo userInfo = users.get(i);
785 final UserHandle userHandle = userInfo.getUserHandle();
786 final int userId = userHandle.getIdentifier();
787
788 if (userHandle.isSystem()) {
789 // Already written.
790 continue;
791 }
792
793 if (!shouldHaveSharedCallLogEntries(context, userManager, userId)) {
794 // Shouldn't have calllog entries.
795 continue;
796 }
797
798 // For other users, we write only when they're running *and* decrypted.
799 // Other providers will copy from the system user's real provider, when they
800 // start.
Yorke Leea79e2be2014-08-10 13:52:21 -0700801 if (userManager.isUserRunning(userHandle)
Makoto Onukib5247412016-01-12 12:57:25 -0800802 && userManager.isUserUnlocked(userHandle)) {
803 final Uri uri = addEntryAndRemoveExpiredEntries(context, userManager,
804 userHandle, values);
805 if (userId == currentUserId) {
Yorke Lee158c5e412014-07-16 15:31:25 -0700806 result = uri;
807 }
808 }
809 }
810 } else {
Makoto Onukib5247412016-01-12 12:57:25 -0800811 // Single-user entry. Just write to that user, assuming it's running. If the
812 // user is encrypted, we write to the shadow calllog.
813
814 final UserHandle targetUserHandle = userToBeInsertedTo != null
815 ? userToBeInsertedTo
816 : UserHandle.of(currentUserId);
817 result = addEntryAndRemoveExpiredEntries(context, userManager, targetUserHandle,
818 values);
Yorke Lee158c5e412014-07-16 15:31:25 -0700819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 return result;
821 }
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800822
Makoto Onukib5247412016-01-12 12:57:25 -0800823 /** @hide */
824 public static boolean shouldHaveSharedCallLogEntries(Context context,
825 UserManager userManager, int userId) {
826 if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
827 UserHandle.of(userId))) {
828 return false;
829 }
830 final UserInfo userInfo = userManager.getUserInfo(userId);
831 return userInfo != null && !userInfo.isManagedProfile();
832 }
833
Nicolas Cataniab8a2aaf2010-01-14 10:44:02 -0800834 /**
835 * Query the call log database for the last dialed number.
836 * @param context Used to get the content resolver.
837 * @return The last phone number dialed (outgoing) or an empty
838 * string if none exist yet.
839 */
840 public static String getLastOutgoingCall(Context context) {
841 final ContentResolver resolver = context.getContentResolver();
842 Cursor c = null;
843 try {
844 c = resolver.query(
845 CONTENT_URI,
846 new String[] {NUMBER},
847 TYPE + " = " + OUTGOING_TYPE,
848 null,
849 DEFAULT_SORT_ORDER + " LIMIT 1");
850 if (c == null || !c.moveToFirst()) {
851 return "";
852 }
853 return c.getString(0);
854 } finally {
855 if (c != null) c.close();
856 }
857 }
858
Makoto Onukib5247412016-01-12 12:57:25 -0800859 private static Uri addEntryAndRemoveExpiredEntries(Context context, UserManager userManager,
860 UserHandle user, ContentValues values) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 final ContentResolver resolver = context.getContentResolver();
Makoto Onukib5247412016-01-12 12:57:25 -0800862
Jeff Sharkeyce18c812016-04-27 16:00:41 -0600863 // Since we're doing this operation on behalf of an app, we only
864 // want to use the actual "unlocked" state.
Makoto Onukib5247412016-01-12 12:57:25 -0800865 final Uri uri = ContentProvider.maybeAddUserId(
866 userManager.isUserUnlocked(user) ? CONTENT_URI : SHADOW_CONTENT_URI,
867 user.getIdentifier());
868
869 if (VERBOSE_LOG) {
870 Log.v(LOG_TAG, String.format("Inserting to %s", uri));
871 }
872
873 try {
Tyler Gunncf264542017-06-01 14:12:54 -0700874 // When cleaning up the call log, try to delete older call long entries on a per
875 // PhoneAccount basis first. There can be multiple ConnectionServices causing
876 // the addition of entries in the call log. With the introduction of Self-Managed
877 // ConnectionServices, we want to ensure that a misbehaving self-managed CS cannot
878 // spam the call log with its own entries, causing entries from Telephony to be
879 // removed.
Makoto Onukib5247412016-01-12 12:57:25 -0800880 final Uri result = resolver.insert(uri, values);
Tyler Gunncf264542017-06-01 14:12:54 -0700881 if (values.containsKey(PHONE_ACCOUNT_ID)
882 && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_ID))
883 && values.containsKey(PHONE_ACCOUNT_COMPONENT_NAME)
884 && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME))) {
885 // Only purge entries for the same phone account.
886 resolver.delete(uri, "_id IN " +
887 "(SELECT _id FROM calls"
888 + " WHERE " + PHONE_ACCOUNT_COMPONENT_NAME + " = ?"
889 + " AND " + PHONE_ACCOUNT_ID + " = ?"
890 + " ORDER BY " + DEFAULT_SORT_ORDER
891 + " LIMIT -1 OFFSET 500)", new String[] {
892 values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME),
893 values.getAsString(PHONE_ACCOUNT_ID)
894 });
895 } else {
896 // No valid phone account specified, so default to the old behavior.
897 resolver.delete(uri, "_id IN " +
898 "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER
899 + " LIMIT -1 OFFSET 500)", null);
900 }
901
Makoto Onukib5247412016-01-12 12:57:25 -0800902 return result;
903 } catch (IllegalArgumentException e) {
904 Log.w(LOG_TAG, "Failed to insert calllog", e);
905 // Even though we make sure the target user is running and decrypted before calling
906 // this method, there's a chance that the user just got shut down, in which case
907 // we'll still get "IllegalArgumentException: Unknown URL content://call_log/calls".
908 return null;
909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 }
Shishir Agrawal1ae88e32014-10-27 12:28:52 -0700911
912 private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) {
913 final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
914 .appendPath(dataId)
915 .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
916 DataUsageFeedback.USAGE_TYPE_CALL)
917 .build();
918 resolver.update(feedbackUri, new ContentValues(), null, null);
919 }
920
921 /*
922 * Update the normalized phone number for the given dataId in the ContactsProvider, based
923 * on the user's current country.
924 */
925 private static void updateNormalizedNumber(Context context, ContentResolver resolver,
926 String dataId, String number) {
927 if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) {
928 return;
929 }
930 final String countryIso = getCurrentCountryIso(context);
931 if (TextUtils.isEmpty(countryIso)) {
932 return;
933 }
934 final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number,
935 getCurrentCountryIso(context));
936 if (TextUtils.isEmpty(normalizedNumber)) {
937 return;
938 }
939 final ContentValues values = new ContentValues();
940 values.put(Phone.NORMALIZED_NUMBER, normalizedNumber);
941 resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId});
942 }
943
944 private static String getCurrentCountryIso(Context context) {
945 String countryIso = null;
946 final CountryDetector detector = (CountryDetector) context.getSystemService(
947 Context.COUNTRY_DETECTOR);
948 if (detector != null) {
949 final Country country = detector.detectCountry();
950 if (country != null) {
951 countryIso = country.getCountryIso();
952 }
953 }
954 return countryIso;
955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 }
957}