• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 package android.provider;
19 
20 import android.annotation.UnsupportedAppUsage;
21 import android.content.ContentProvider;
22 import android.content.ContentResolver;
23 import android.content.ContentValues;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.UserInfo;
27 import android.database.Cursor;
28 import android.location.Country;
29 import android.location.CountryDetector;
30 import android.net.Uri;
31 import android.os.Build;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.provider.ContactsContract.CommonDataKinds.Callable;
35 import android.provider.ContactsContract.CommonDataKinds.Phone;
36 import android.provider.ContactsContract.Data;
37 import android.provider.ContactsContract.DataUsageFeedback;
38 import android.telecom.PhoneAccount;
39 import android.telecom.PhoneAccountHandle;
40 import android.telecom.TelecomManager;
41 import android.telephony.PhoneNumberUtils;
42 import android.text.TextUtils;
43 import android.util.Log;
44 
45 import com.android.internal.telephony.CallerInfo;
46 import com.android.internal.telephony.PhoneConstants;
47 
48 import java.util.List;
49 
50 /**
51  * The CallLog provider contains information about placed and received calls.
52  */
53 public class CallLog {
54     private static final String LOG_TAG = "CallLog";
55     private static final boolean VERBOSE_LOG = false; // DON'T SUBMIT WITH TRUE.
56 
57     public static final String AUTHORITY = "call_log";
58 
59     /**
60      * The content:// style URL for this provider
61      */
62     public static final Uri CONTENT_URI =
63         Uri.parse("content://" + AUTHORITY);
64 
65 
66     /**
67      * The "shadow" provider stores calllog when the real calllog provider is encrypted.  The
68      * real provider will alter copy from it when it starts, and remove the entries in the shadow.
69      *
70      * <p>See the comment in {@link Calls#addCall} for the details.
71      *
72      * @hide
73      */
74     public static final String SHADOW_AUTHORITY = "call_log_shadow";
75 
76     /**
77      * Contains the recent calls.
78      */
79     public static class Calls implements BaseColumns {
80         /**
81          * The content:// style URL for this table
82          */
83         public static final Uri CONTENT_URI =
84                 Uri.parse("content://call_log/calls");
85 
86         /** @hide */
87         public static final Uri SHADOW_CONTENT_URI =
88                 Uri.parse("content://call_log_shadow/calls");
89 
90         /**
91          * The content:// style URL for filtering this table on phone numbers
92          */
93         public static final Uri CONTENT_FILTER_URI =
94                 Uri.parse("content://call_log/calls/filter");
95 
96         /**
97          * Query parameter used to limit the number of call logs returned.
98          * <p>
99          * TYPE: integer
100          */
101         public static final String LIMIT_PARAM_KEY = "limit";
102 
103         /**
104          * Query parameter used to specify the starting record to return.
105          * <p>
106          * TYPE: integer
107          */
108         public static final String OFFSET_PARAM_KEY = "offset";
109 
110         /**
111          * An optional URI parameter which instructs the provider to allow the operation to be
112          * applied to voicemail records as well.
113          * <p>
114          * TYPE: Boolean
115          * <p>
116          * Using this parameter with a value of {@code true} will result in a security error if the
117          * calling package does not have appropriate permissions to access voicemails.
118          *
119          * @hide
120          */
121         public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
122 
123         /**
124          * An optional extra used with {@link #CONTENT_TYPE Calls.CONTENT_TYPE} and
125          * {@link Intent#ACTION_VIEW} to specify that the presented list of calls should be
126          * filtered for a particular call type.
127          *
128          * Applications implementing a call log UI should check for this extra, and display a
129          * filtered list of calls based on the specified call type. If not applicable within the
130          * application's UI, it should be silently ignored.
131          *
132          * <p>
133          * The following example brings up the call log, showing only missed calls.
134          * <pre>
135          * Intent intent = new Intent(Intent.ACTION_VIEW);
136          * intent.setType(CallLog.Calls.CONTENT_TYPE);
137          * intent.putExtra(CallLog.Calls.EXTRA_CALL_TYPE_FILTER, CallLog.Calls.MISSED_TYPE);
138          * startActivity(intent);
139          * </pre>
140          * </p>
141          */
142         public static final String EXTRA_CALL_TYPE_FILTER =
143                 "android.provider.extra.CALL_TYPE_FILTER";
144 
145         /**
146          * Content uri used to access call log entries, including voicemail records. You must have
147          * the READ_CALL_LOG and WRITE_CALL_LOG permissions to read and write to the call log, as
148          * well as READ_VOICEMAIL and WRITE_VOICEMAIL permissions to read and write voicemails.
149          */
150         public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
151                 .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
152                 .build();
153 
154         /**
155          * The default sort order for this table
156          */
157         public static final String DEFAULT_SORT_ORDER = "date DESC";
158 
159         /**
160          * The MIME type of {@link #CONTENT_URI} and {@link #CONTENT_FILTER_URI}
161          * providing a directory of calls.
162          */
163         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
164 
165         /**
166          * The MIME type of a {@link #CONTENT_URI} sub-directory of a single
167          * call.
168          */
169         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
170 
171         /**
172          * The type of the call (incoming, outgoing or missed).
173          * <P>Type: INTEGER (int)</P>
174          *
175          * <p>
176          * Allowed values:
177          * <ul>
178          * <li>{@link #INCOMING_TYPE}</li>
179          * <li>{@link #OUTGOING_TYPE}</li>
180          * <li>{@link #MISSED_TYPE}</li>
181          * <li>{@link #VOICEMAIL_TYPE}</li>
182          * <li>{@link #REJECTED_TYPE}</li>
183          * <li>{@link #BLOCKED_TYPE}</li>
184          * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li>
185          * </ul>
186          * </p>
187          */
188         public static final String TYPE = "type";
189 
190         /** Call log type for incoming calls. */
191         public static final int INCOMING_TYPE = 1;
192         /** Call log type for outgoing calls. */
193         public static final int OUTGOING_TYPE = 2;
194         /** Call log type for missed calls. */
195         public static final int MISSED_TYPE = 3;
196         /** Call log type for voicemails. */
197         public static final int VOICEMAIL_TYPE = 4;
198         /** Call log type for calls rejected by direct user action. */
199         public static final int REJECTED_TYPE = 5;
200         /** Call log type for calls blocked automatically. */
201         public static final int BLOCKED_TYPE = 6;
202         /**
203          * Call log type for a call which was answered on another device.  Used in situations where
204          * a call rings on multiple devices simultaneously and it ended up being answered on a
205          * device other than the current one.
206          */
207         public static final int ANSWERED_EXTERNALLY_TYPE = 7;
208 
209         /**
210          * Bit-mask describing features of the call (e.g. video).
211          *
212          * <P>Type: INTEGER (int)</P>
213          */
214         public static final String FEATURES = "features";
215 
216         /** Call had video. */
217         public static final int FEATURES_VIDEO = 1 << 0;
218 
219         /** Call was pulled externally. */
220         public static final int FEATURES_PULLED_EXTERNALLY = 1 << 1;
221 
222         /** Call was HD. */
223         public static final int FEATURES_HD_CALL = 1 << 2;
224 
225         /** Call was WIFI call. */
226         public static final int FEATURES_WIFI = 1 << 3;
227 
228         /**
229          * Indicates the call underwent Assisted Dialing.
230          * @hide
231          */
232         public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4;
233 
234         /** Call was on RTT at some point */
235         public static final int FEATURES_RTT = 1 << 5;
236 
237         /**
238          * The phone number as the user entered it.
239          * <P>Type: TEXT</P>
240          */
241         public static final String NUMBER = "number";
242 
243         /**
244          * The number presenting rules set by the network.
245          *
246          * <p>
247          * Allowed values:
248          * <ul>
249          * <li>{@link #PRESENTATION_ALLOWED}</li>
250          * <li>{@link #PRESENTATION_RESTRICTED}</li>
251          * <li>{@link #PRESENTATION_UNKNOWN}</li>
252          * <li>{@link #PRESENTATION_PAYPHONE}</li>
253          * </ul>
254          * </p>
255          *
256          * <P>Type: INTEGER</P>
257          */
258         public static final String NUMBER_PRESENTATION = "presentation";
259 
260         /** Number is allowed to display for caller id. */
261         public static final int PRESENTATION_ALLOWED = 1;
262         /** Number is blocked by user. */
263         public static final int PRESENTATION_RESTRICTED = 2;
264         /** Number is not specified or unknown by network. */
265         public static final int PRESENTATION_UNKNOWN = 3;
266         /** Number is a pay phone. */
267         public static final int PRESENTATION_PAYPHONE = 4;
268 
269         /**
270          * The ISO 3166-1 two letters country code of the country where the
271          * user received or made the call.
272          * <P>
273          * Type: TEXT
274          * </P>
275          */
276         public static final String COUNTRY_ISO = "countryiso";
277 
278         /**
279          * The date the call occured, in milliseconds since the epoch
280          * <P>Type: INTEGER (long)</P>
281          */
282         public static final String DATE = "date";
283 
284         /**
285          * The duration of the call in seconds
286          * <P>Type: INTEGER (long)</P>
287          */
288         public static final String DURATION = "duration";
289 
290         /**
291          * The data usage of the call in bytes.
292          * <P>Type: INTEGER (long)</P>
293          */
294         public static final String DATA_USAGE = "data_usage";
295 
296         /**
297          * Whether or not the call has been acknowledged
298          * <P>Type: INTEGER (boolean)</P>
299          */
300         public static final String NEW = "new";
301 
302         /**
303          * The cached name associated with the phone number, if it exists.
304          *
305          * <p>This value is typically filled in by the dialer app for the caching purpose,
306          * so it's not guaranteed to be present, and may not be current if the contact
307          * information associated with this number has changed.
308          * <P>Type: TEXT</P>
309          */
310         public static final String CACHED_NAME = "name";
311 
312         /**
313          * The cached number type (Home, Work, etc) associated with the
314          * phone number, if it exists.
315          *
316          * <p>This value is typically filled in by the dialer app for the caching purpose,
317          * so it's not guaranteed to be present, and may not be current if the contact
318          * information associated with this number has changed.
319          * <P>Type: INTEGER</P>
320          */
321         public static final String CACHED_NUMBER_TYPE = "numbertype";
322 
323         /**
324          * The cached number label, for a custom number type, associated with the
325          * phone number, if it exists.
326          *
327          * <p>This value is typically filled in by the dialer app for the caching purpose,
328          * so it's not guaranteed to be present, and may not be current if the contact
329          * information associated with this number has changed.
330          * <P>Type: TEXT</P>
331          */
332         public static final String CACHED_NUMBER_LABEL = "numberlabel";
333 
334         /**
335          * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}.
336          * <P>Type: TEXT</P>
337          */
338         public static final String VOICEMAIL_URI = "voicemail_uri";
339 
340         /**
341          * Transcription of the call or voicemail entry. This will only be populated for call log
342          * entries of type {@link #VOICEMAIL_TYPE} that have valid transcriptions.
343          */
344         public static final String TRANSCRIPTION = "transcription";
345 
346         /**
347          * State of voicemail transcription entry. This will only be populated for call log
348          * entries of type {@link #VOICEMAIL_TYPE}.
349          * @hide
350          */
351         public static final String TRANSCRIPTION_STATE = "transcription_state";
352 
353         /**
354          * Whether this item has been read or otherwise consumed by the user.
355          * <p>
356          * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
357          * existence of the entry, this implies the user has interacted with the entry.
358          * <P>Type: INTEGER (boolean)</P>
359          */
360         public static final String IS_READ = "is_read";
361 
362         /**
363          * A geocoded location for the number associated with this call.
364          * <p>
365          * The string represents a city, state, or country associated with the number.
366          * <P>Type: TEXT</P>
367          */
368         public static final String GEOCODED_LOCATION = "geocoded_location";
369 
370         /**
371          * The cached URI to look up the contact associated with the phone number, if it exists.
372          *
373          * <p>This value is typically filled in by the dialer app for the caching purpose,
374          * so it's not guaranteed to be present, and may not be current if the contact
375          * information associated with this number has changed.
376          * <P>Type: TEXT</P>
377          */
378         public static final String CACHED_LOOKUP_URI = "lookup_uri";
379 
380         /**
381          * The cached phone number of the contact which matches this entry, if it exists.
382          *
383          * <p>This value is typically filled in by the dialer app for the caching purpose,
384          * so it's not guaranteed to be present, and may not be current if the contact
385          * information associated with this number has changed.
386          * <P>Type: TEXT</P>
387          */
388         public static final String CACHED_MATCHED_NUMBER = "matched_number";
389 
390         /**
391          * The cached normalized(E164) version of the phone number, if it exists.
392          *
393          * <p>This value is typically filled in by the dialer app for the caching purpose,
394          * so it's not guaranteed to be present, and may not be current if the contact
395          * information associated with this number has changed.
396          * <P>Type: TEXT</P>
397          */
398         public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
399 
400         /**
401          * The cached photo id of the picture associated with the phone number, if it exists.
402          *
403          * <p>This value is typically filled in by the dialer app for the caching purpose,
404          * so it's not guaranteed to be present, and may not be current if the contact
405          * information associated with this number has changed.
406          * <P>Type: INTEGER (long)</P>
407          */
408         public static final String CACHED_PHOTO_ID = "photo_id";
409 
410         /**
411          * The cached photo URI of the picture associated with the phone number, if it exists.
412          *
413          * <p>This value is typically filled in by the dialer app for the caching purpose,
414          * so it's not guaranteed to be present, and may not be current if the contact
415          * information associated with this number has changed.
416          * <P>Type: TEXT (URI)</P>
417          */
418         public static final String CACHED_PHOTO_URI = "photo_uri";
419 
420         /**
421          * The cached phone number, formatted with formatting rules based on the country the
422          * user was in when the call was made or received.
423          *
424          * <p>This value is typically filled in by the dialer app for the caching purpose,
425          * so it's not guaranteed to be present, and may not be current if the contact
426          * information associated with this number has changed.
427          * <P>Type: TEXT</P>
428          */
429         public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
430 
431         // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
432         // that was encoded into call log databases.
433 
434         /**
435          * The component name of the account used to place or receive the call; in string form.
436          * <P>Type: TEXT</P>
437          */
438         public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
439 
440         /**
441          * The identifier for the account used to place or receive the call.
442          * <P>Type: TEXT</P>
443          */
444         public static final String PHONE_ACCOUNT_ID = "subscription_id";
445 
446         /**
447          * The address associated with the account used to place or receive the call; in string
448          * form. For SIM-based calls, this is the user's own phone number.
449          * <P>Type: TEXT</P>
450          *
451          * @hide
452          */
453         public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
454 
455         /**
456          * Indicates that the entry will be hidden from all queries until the associated
457          * {@link android.telecom.PhoneAccount} is registered with the system.
458          * <P>Type: INTEGER</P>
459          *
460          * @hide
461          */
462         public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden";
463 
464         /**
465          * The subscription ID used to place this call.  This is no longer used and has been
466          * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
467          * For ContactsProvider internal use only.
468          * <P>Type: INTEGER</P>
469          *
470          * @Deprecated
471          * @hide
472          */
473         public static final String SUB_ID = "sub_id";
474 
475         /**
476          * The post-dial portion of a dialed number, including any digits dialed after a
477          * {@link TelecomManager#DTMF_CHARACTER_PAUSE} or a {@link
478          * TelecomManager#DTMF_CHARACTER_WAIT} and these characters themselves.
479          * <P>Type: TEXT</P>
480          */
481         public static final String POST_DIAL_DIGITS = "post_dial_digits";
482 
483         /**
484          * For an incoming call, the secondary line number the call was received via.
485          * When a SIM card has multiple phone numbers associated with it, the via number indicates
486          * which of the numbers associated with the SIM was called.
487          */
488         public static final String VIA_NUMBER = "via_number";
489 
490         /**
491          * Indicates that the entry will be copied from primary user to other users.
492          * <P>Type: INTEGER</P>
493          *
494          * @hide
495          */
496         public static final String ADD_FOR_ALL_USERS = "add_for_all_users";
497 
498         /**
499          * The date the row is last inserted, updated, or marked as deleted, in milliseconds
500          * since the epoch. Read only.
501          * <P>Type: INTEGER (long)</P>
502          */
503         public static final String LAST_MODIFIED = "last_modified";
504 
505         /**
506          * If a successful call is made that is longer than this duration, update the phone number
507          * in the ContactsProvider with the normalized version of the number, based on the user's
508          * current country code.
509          */
510         private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
511 
512         /**
513          * Value for {@link CallLog.Calls#BLOCK_REASON}, set as the default value when a call was
514          * not blocked by a CallScreeningService or any other system call blocking method.
515          */
516         public static final int BLOCK_REASON_NOT_BLOCKED = 0;
517 
518         /**
519          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
520          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked by a
521          * CallScreeningService. The {@link CallLog.Calls#CALL_SCREENING_COMPONENT_NAME} and
522          * {@link CallLog.Calls#CALL_SCREENING_APP_NAME} columns will indicate which call screening
523          * service was responsible for blocking the call.
524          */
525         public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1;
526 
527         /**
528          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
529          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
530          * configured a contact to be sent directly to voicemail.
531          */
532         public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2;
533 
534         /**
535          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
536          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because it is
537          * in the BlockedNumbers provider.
538          */
539         public static final int BLOCK_REASON_BLOCKED_NUMBER = 3;
540 
541         /**
542          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
543          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
544          * has chosen to block all calls from unknown numbers.
545          */
546         public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4;
547 
548         /**
549          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
550          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
551          * has chosen to block all calls from restricted numbers.
552          */
553         public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5;
554 
555         /**
556          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
557          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
558          * has chosen to block all calls from pay phones.
559          */
560         public static final int BLOCK_REASON_PAY_PHONE = 6;
561 
562         /**
563          * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
564          * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
565          * has chosen to block all calls from numbers not in their contacts.
566          */
567         public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7;
568 
569         /**
570          * The ComponentName of the CallScreeningService which blocked this call. Will be
571          * populated when the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}.
572          * <P>Type: TEXT</P>
573          */
574         public static final String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name";
575 
576         /**
577          * The name of the app which blocked a call. Will be populated when the
578          * {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. Provided as a
579          * convenience so that the call log can still indicate which app blocked a call, even if
580          * that app is no longer installed.
581          * <P>Type: TEXT</P>
582          */
583         public static final String CALL_SCREENING_APP_NAME = "call_screening_app_name";
584 
585         /**
586          * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE},
587          * indicates the reason why a call is blocked.
588          * <P>Type: INTEGER</P>
589          *
590          * <p>
591          * Allowed values:
592          * <ul>
593          * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_BLOCKED}</li>
594          * <li>{@link CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE}</li>
595          * <li>{@link CallLog.Calls#BLOCK_REASON_DIRECT_TO_VOICEMAIL}</li>
596          * <li>{@link CallLog.Calls#BLOCK_REASON_BLOCKED_NUMBER}</li>
597          * <li>{@link CallLog.Calls#BLOCK_REASON_UNKNOWN_NUMBER}</li>
598          * <li>{@link CallLog.Calls#BLOCK_REASON_RESTRICTED_NUMBER}</li>
599          * <li>{@link CallLog.Calls#BLOCK_REASON_PAY_PHONE}</li>
600          * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_IN_CONTACTS}</li>
601          * </ul>
602          * </p>
603          */
604         public static final String BLOCK_REASON = "block_reason";
605 
606         /**
607          * Adds a call to the call log.
608          *
609          * @param ci the CallerInfo object to get the target contact from.  Can be null
610          * if the contact is unknown.
611          * @param context the context used to get the ContentResolver
612          * @param number the phone number to be added to the calls db
613          * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
614          *        is set by the network and denotes the number presenting rules for
615          *        "allowed", "payphone", "restricted" or "unknown"
616          * @param callType enumerated values for "incoming", "outgoing", or "missed"
617          * @param features features of the call (e.g. Video).
618          * @param accountHandle The accountHandle object identifying the provider of the call
619          * @param start time stamp for the call in milliseconds
620          * @param duration call duration in seconds
621          * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
622          *                  the call.
623          * @result The URI of the call log entry belonging to the user that made or received this
624          *        call.
625          * {@hide}
626          */
addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage)627         public static Uri addCall(CallerInfo ci, Context context, String number,
628                 int presentation, int callType, int features,
629                 PhoneAccountHandle accountHandle,
630                 long start, int duration, Long dataUsage) {
631             return addCall(ci, context, number, "" /* postDialDigits */, "" /* viaNumber */,
632                 presentation, callType, features, accountHandle, start, duration,
633                 dataUsage, false /* addForAllUsers */, null /* userToBeInsertedTo */,
634                 false /* isRead */, Calls.BLOCK_REASON_NOT_BLOCKED /* callBlockReason */,
635                 null /* callScreeningAppName */, null /* callScreeningComponentName */);
636         }
637 
638 
639         /**
640          * Adds a call to the call log.
641          *
642          * @param ci the CallerInfo object to get the target contact from.  Can be null
643          * if the contact is unknown.
644          * @param context the context used to get the ContentResolver
645          * @param number the phone number to be added to the calls db
646          * @param viaNumber the secondary number that the incoming call received with. If the
647          *       call was received with the SIM assigned number, then this field must be ''.
648          * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
649          *        is set by the network and denotes the number presenting rules for
650          *        "allowed", "payphone", "restricted" or "unknown"
651          * @param callType enumerated values for "incoming", "outgoing", or "missed"
652          * @param features features of the call (e.g. Video).
653          * @param accountHandle The accountHandle object identifying the provider of the call
654          * @param start time stamp for the call in milliseconds
655          * @param duration call duration in seconds
656          * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
657          *                  the call.
658          * @param addForAllUsers If true, the call is added to the call log of all currently
659          *        running users. The caller must have the MANAGE_USERS permission if this is true.
660          * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
661          *                           inserted to. null if it is inserted to the current user. The
662          *                           value is ignored if @{link addForAllUsers} is true.
663          * @result The URI of the call log entry belonging to the user that made or received this
664          *        call.
665          * {@hide}
666          */
addCall(CallerInfo ci, Context context, String number, String postDialDigits, String viaNumber, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo)667         public static Uri addCall(CallerInfo ci, Context context, String number,
668                 String postDialDigits, String viaNumber, int presentation, int callType,
669                 int features, PhoneAccountHandle accountHandle, long start, int duration,
670                 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo) {
671             return addCall(ci, context, number, postDialDigits, viaNumber, presentation, callType,
672                 features, accountHandle, start, duration, dataUsage, addForAllUsers,
673                 userToBeInsertedTo, false /* isRead */ , Calls.BLOCK_REASON_NOT_BLOCKED
674                 /* callBlockReason */, null /* callScreeningAppName */,
675                 null /* callScreeningComponentName */);
676         }
677 
678         /**
679          * Adds a call to the call log.
680          *
681          * @param ci the CallerInfo object to get the target contact from.  Can be null
682          * if the contact is unknown.
683          * @param context the context used to get the ContentResolver
684          * @param number the phone number to be added to the calls db
685          * @param postDialDigits the post-dial digits that were dialed after the number,
686          *        if it was outgoing. Otherwise it is ''.
687          * @param viaNumber the secondary number that the incoming call received with. If the
688          *        call was received with the SIM assigned number, then this field must be ''.
689          * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
690          *        is set by the network and denotes the number presenting rules for
691          *        "allowed", "payphone", "restricted" or "unknown"
692          * @param callType enumerated values for "incoming", "outgoing", or "missed"
693          * @param features features of the call (e.g. Video).
694          * @param accountHandle The accountHandle object identifying the provider of the call
695          * @param start time stamp for the call in milliseconds
696          * @param duration call duration in seconds
697          * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
698          *                  the call.
699          * @param addForAllUsers If true, the call is added to the call log of all currently
700          *        running users. The caller must have the MANAGE_USERS permission if this is true.
701          * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
702          *                           inserted to. null if it is inserted to the current user. The
703          *                           value is ignored if @{link addForAllUsers} is true.
704          * @param isRead Flag to show if the missed call log has been read by the user or not.
705          *                Used for call log restore of missed calls.
706          * @param callBlockReason The reason why the call is blocked.
707          * @param callScreeningAppName The call screening application name which block the call.
708          * @param callScreeningComponentName The call screening component name which block the call.
709          *
710          * @result The URI of the call log entry belonging to the user that made or received this
711          *        call.  This could be of the shadow provider.  Do not return it to non-system apps,
712          *        as they don't have permissions.
713          * {@hide}
714          */
715         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
addCall(CallerInfo ci, Context context, String number, String postDialDigits, String viaNumber, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo, boolean isRead, int callBlockReason, CharSequence callScreeningAppName, String callScreeningComponentName)716         public static Uri addCall(CallerInfo ci, Context context, String number,
717                 String postDialDigits, String viaNumber, int presentation, int callType,
718                 int features, PhoneAccountHandle accountHandle, long start, int duration,
719                 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo,
720                 boolean isRead, int callBlockReason, CharSequence callScreeningAppName,
721                 String callScreeningComponentName) {
722             if (VERBOSE_LOG) {
723                 Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
724                         number, userToBeInsertedTo, addForAllUsers));
725             }
726             final ContentResolver resolver = context.getContentResolver();
727 
728             String accountAddress = getLogAccountAddress(context, accountHandle);
729 
730             int numberPresentation = getLogNumberPresentation(number, presentation);
731             if (numberPresentation != PRESENTATION_ALLOWED) {
732                 number = "";
733                 if (ci != null) {
734                     ci.name = "";
735                 }
736             }
737 
738             // accountHandle information
739             String accountComponentString = null;
740             String accountId = null;
741             if (accountHandle != null) {
742                 accountComponentString = accountHandle.getComponentName().flattenToString();
743                 accountId = accountHandle.getId();
744             }
745 
746             ContentValues values = new ContentValues(6);
747 
748             values.put(NUMBER, number);
749             values.put(POST_DIAL_DIGITS, postDialDigits);
750             values.put(VIA_NUMBER, viaNumber);
751             values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation));
752             values.put(TYPE, Integer.valueOf(callType));
753             values.put(FEATURES, features);
754             values.put(DATE, Long.valueOf(start));
755             values.put(DURATION, Long.valueOf(duration));
756             if (dataUsage != null) {
757                 values.put(DATA_USAGE, dataUsage);
758             }
759             values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
760             values.put(PHONE_ACCOUNT_ID, accountId);
761             values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
762             values.put(NEW, Integer.valueOf(1));
763             if ((ci != null) && (ci.name != null)) {
764                 values.put(CACHED_NAME, ci.name);
765             }
766             values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
767 
768             if (callType == MISSED_TYPE) {
769                 values.put(IS_READ, Integer.valueOf(isRead ? 1 : 0));
770             }
771 
772             values.put(BLOCK_REASON, callBlockReason);
773             values.put(CALL_SCREENING_APP_NAME, charSequenceToString(callScreeningAppName));
774             values.put(CALL_SCREENING_COMPONENT_NAME, callScreeningComponentName);
775 
776             if ((ci != null) && (ci.contactIdOrZero > 0)) {
777                 // Update usage information for the number associated with the contact ID.
778                 // We need to use both the number and the ID for obtaining a data ID since other
779                 // contacts may have the same number.
780 
781                 final Cursor cursor;
782 
783                 // We should prefer normalized one (probably coming from
784                 // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
785                 if (ci.normalizedNumber != null) {
786                     final String normalizedPhoneNumber = ci.normalizedNumber;
787                     cursor = resolver.query(Phone.CONTENT_URI,
788                             new String[] { Phone._ID },
789                             Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
790                             new String[] { String.valueOf(ci.contactIdOrZero),
791                                     normalizedPhoneNumber},
792                             null);
793                 } else {
794                     final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
795                     cursor = resolver.query(
796                             Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
797                                     Uri.encode(phoneNumber)),
798                             new String[] { Phone._ID },
799                             Phone.CONTACT_ID + " =?",
800                             new String[] { String.valueOf(ci.contactIdOrZero) },
801                             null);
802                 }
803 
804                 if (cursor != null) {
805                     try {
806                         if (cursor.getCount() > 0 && cursor.moveToFirst()) {
807                             final String dataId = cursor.getString(0);
808                             updateDataUsageStatForData(resolver, dataId);
809                             if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS
810                                     && callType == Calls.OUTGOING_TYPE
811                                     && TextUtils.isEmpty(ci.normalizedNumber)) {
812                                 updateNormalizedNumber(context, resolver, dataId, number);
813                             }
814                         }
815                     } finally {
816                         cursor.close();
817                     }
818                 }
819             }
820 
821             /*
822                 Writing the calllog works in the following way:
823                 - All user entries
824                     - if user-0 is encrypted, insert to user-0's shadow only.
825                       (other users should also be encrypted, so nothing to do for other users.)
826                     - if user-0 is decrypted, insert to user-0's real provider, as well as
827                       all other users that are running and decrypted and should have calllog.
828 
829                 - Single user entry.
830                     - If the target user is encryted, insert to its shadow.
831                     - Otherwise insert to its real provider.
832 
833                 When the (real) calllog provider starts, it copies entries that it missed from
834                 elsewhere.
835                 - When user-0's (real) provider starts, it copies from user-0's shadow, and clears
836                   the shadow.
837 
838                 - When other users (real) providers start, unless it shouldn't have calllog entries,
839                      - Copy from the user's shadow, and clears the shadow.
840                      - Copy from user-0's entries that are FOR_ALL_USERS = 1.  (and don't clear it.)
841              */
842 
843             Uri result = null;
844 
845             final UserManager userManager = context.getSystemService(UserManager.class);
846             final int currentUserId = userManager.getUserHandle();
847 
848             if (addForAllUsers) {
849                 // First, insert to the system user.
850                 final Uri uriForSystem = addEntryAndRemoveExpiredEntries(
851                         context, userManager, UserHandle.SYSTEM, values);
852                 if (uriForSystem == null
853                         || SHADOW_AUTHORITY.equals(uriForSystem.getAuthority())) {
854                     // This means the system user is still encrypted and the entry has inserted
855                     // into the shadow.  This means other users are still all encrypted.
856                     // Nothing further to do; just return null.
857                     return null;
858                 }
859                 if (UserHandle.USER_SYSTEM == currentUserId) {
860                     result = uriForSystem;
861                 }
862 
863                 // Otherwise, insert to all other users that are running and unlocked.
864 
865                 final List<UserInfo> users = userManager.getUsers(true);
866 
867                 final int count = users.size();
868                 for (int i = 0; i < count; i++) {
869                     final UserInfo userInfo = users.get(i);
870                     final UserHandle userHandle = userInfo.getUserHandle();
871                     final int userId = userHandle.getIdentifier();
872 
873                     if (userHandle.isSystem()) {
874                         // Already written.
875                         continue;
876                     }
877 
878                     if (!shouldHaveSharedCallLogEntries(context, userManager, userId)) {
879                         // Shouldn't have calllog entries.
880                         continue;
881                     }
882 
883                     // For other users, we write only when they're running *and* decrypted.
884                     // Other providers will copy from the system user's real provider, when they
885                     // start.
886                     if (userManager.isUserRunning(userHandle)
887                             && userManager.isUserUnlocked(userHandle)) {
888                         final Uri uri = addEntryAndRemoveExpiredEntries(context, userManager,
889                                 userHandle, values);
890                         if (userId == currentUserId) {
891                             result = uri;
892                         }
893                     }
894                 }
895             } else {
896                 // Single-user entry. Just write to that user, assuming it's running.  If the
897                 // user is encrypted, we write to the shadow calllog.
898 
899                 final UserHandle targetUserHandle = userToBeInsertedTo != null
900                         ? userToBeInsertedTo
901                         : UserHandle.of(currentUserId);
902                 result = addEntryAndRemoveExpiredEntries(context, userManager, targetUserHandle,
903                         values);
904             }
905             return result;
906         }
907 
charSequenceToString(CharSequence sequence)908         private static String charSequenceToString(CharSequence sequence) {
909             return sequence == null ? null : sequence.toString();
910         }
911 
912         /** @hide */
shouldHaveSharedCallLogEntries(Context context, UserManager userManager, int userId)913         public static boolean shouldHaveSharedCallLogEntries(Context context,
914                 UserManager userManager, int userId) {
915             if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
916                     UserHandle.of(userId))) {
917                 return false;
918             }
919             final UserInfo userInfo = userManager.getUserInfo(userId);
920             return userInfo != null && !userInfo.isManagedProfile();
921         }
922 
923         /**
924          * Query the call log database for the last dialed number.
925          * @param context Used to get the content resolver.
926          * @return The last phone number dialed (outgoing) or an empty
927          * string if none exist yet.
928          */
getLastOutgoingCall(Context context)929         public static String getLastOutgoingCall(Context context) {
930             final ContentResolver resolver = context.getContentResolver();
931             Cursor c = null;
932             try {
933                 c = resolver.query(
934                     CONTENT_URI,
935                     new String[] {NUMBER},
936                     TYPE + " = " + OUTGOING_TYPE,
937                     null,
938                     DEFAULT_SORT_ORDER + " LIMIT 1");
939                 if (c == null || !c.moveToFirst()) {
940                     return "";
941                 }
942                 return c.getString(0);
943             } finally {
944                 if (c != null) c.close();
945             }
946         }
947 
addEntryAndRemoveExpiredEntries(Context context, UserManager userManager, UserHandle user, ContentValues values)948         private static Uri addEntryAndRemoveExpiredEntries(Context context, UserManager userManager,
949                 UserHandle user, ContentValues values) {
950             final ContentResolver resolver = context.getContentResolver();
951 
952             // Since we're doing this operation on behalf of an app, we only
953             // want to use the actual "unlocked" state.
954             final Uri uri = ContentProvider.maybeAddUserId(
955                     userManager.isUserUnlocked(user) ? CONTENT_URI : SHADOW_CONTENT_URI,
956                     user.getIdentifier());
957 
958             if (VERBOSE_LOG) {
959                 Log.v(LOG_TAG, String.format("Inserting to %s", uri));
960             }
961 
962             try {
963                 // When cleaning up the call log, try to delete older call long entries on a per
964                 // PhoneAccount basis first.  There can be multiple ConnectionServices causing
965                 // the addition of entries in the call log.  With the introduction of Self-Managed
966                 // ConnectionServices, we want to ensure that a misbehaving self-managed CS cannot
967                 // spam the call log with its own entries, causing entries from Telephony to be
968                 // removed.
969                 final Uri result = resolver.insert(uri, values);
970                 if (values.containsKey(PHONE_ACCOUNT_ID)
971                         && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_ID))
972                         && values.containsKey(PHONE_ACCOUNT_COMPONENT_NAME)
973                         && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME))) {
974                     // Only purge entries for the same phone account.
975                     resolver.delete(uri, "_id IN " +
976                             "(SELECT _id FROM calls"
977                             + " WHERE " + PHONE_ACCOUNT_COMPONENT_NAME + " = ?"
978                             + " AND " + PHONE_ACCOUNT_ID + " = ?"
979                             + " ORDER BY " + DEFAULT_SORT_ORDER
980                             + " LIMIT -1 OFFSET 500)", new String[] {
981                             values.getAsString(PHONE_ACCOUNT_COMPONENT_NAME),
982                             values.getAsString(PHONE_ACCOUNT_ID)
983                     });
984                 } else {
985                     // No valid phone account specified, so default to the old behavior.
986                     resolver.delete(uri, "_id IN " +
987                             "(SELECT _id FROM calls ORDER BY " + DEFAULT_SORT_ORDER
988                             + " LIMIT -1 OFFSET 500)", null);
989                 }
990 
991                 return result;
992             } catch (IllegalArgumentException e) {
993                 Log.w(LOG_TAG, "Failed to insert calllog", e);
994                 // Even though we make sure the target user is running and decrypted before calling
995                 // this method, there's a chance that the user just got shut down, in which case
996                 // we'll still get "IllegalArgumentException: Unknown URL content://call_log/calls".
997                 return null;
998             }
999         }
1000 
updateDataUsageStatForData(ContentResolver resolver, String dataId)1001         private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) {
1002             final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
1003                     .appendPath(dataId)
1004                     .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
1005                                 DataUsageFeedback.USAGE_TYPE_CALL)
1006                     .build();
1007             resolver.update(feedbackUri, new ContentValues(), null, null);
1008         }
1009 
1010         /*
1011          * Update the normalized phone number for the given dataId in the ContactsProvider, based
1012          * on the user's current country.
1013          */
updateNormalizedNumber(Context context, ContentResolver resolver, String dataId, String number)1014         private static void updateNormalizedNumber(Context context, ContentResolver resolver,
1015                 String dataId, String number) {
1016             if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) {
1017                 return;
1018             }
1019             final String countryIso = getCurrentCountryIso(context);
1020             if (TextUtils.isEmpty(countryIso)) {
1021                 return;
1022             }
1023             final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
1024             if (TextUtils.isEmpty(normalizedNumber)) {
1025                 return;
1026             }
1027             final ContentValues values = new ContentValues();
1028             values.put(Phone.NORMALIZED_NUMBER, normalizedNumber);
1029             resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId});
1030         }
1031 
1032         /**
1033          * Remap network specified number presentation types
1034          * PhoneConstants.PRESENTATION_xxx to calllog number presentation types
1035          * Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
1036          * from any future radio changes.
1037          * If the number field is empty set the presentation type to Unknown.
1038          */
getLogNumberPresentation(String number, int presentation)1039         private static int getLogNumberPresentation(String number, int presentation) {
1040             if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
1041                 return presentation;
1042             }
1043 
1044             if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
1045                 return presentation;
1046             }
1047 
1048             if (TextUtils.isEmpty(number)
1049                     || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
1050                 return PRESENTATION_UNKNOWN;
1051             }
1052 
1053             return PRESENTATION_ALLOWED;
1054         }
1055 
getLogAccountAddress(Context context, PhoneAccountHandle accountHandle)1056         private static String getLogAccountAddress(Context context,
1057                 PhoneAccountHandle accountHandle) {
1058             TelecomManager tm = null;
1059             try {
1060                 tm = TelecomManager.from(context);
1061             } catch (UnsupportedOperationException e) {
1062                 if (VERBOSE_LOG) {
1063                     Log.v(LOG_TAG, "No TelecomManager found to get account address.");
1064                 }
1065             }
1066 
1067             String accountAddress = null;
1068             if (tm != null && accountHandle != null) {
1069                 PhoneAccount account = tm.getPhoneAccount(accountHandle);
1070                 if (account != null) {
1071                     Uri address = account.getSubscriptionAddress();
1072                     if (address != null) {
1073                         accountAddress = address.getSchemeSpecificPart();
1074                     }
1075                 }
1076             }
1077             return accountAddress;
1078         }
1079 
getCurrentCountryIso(Context context)1080         private static String getCurrentCountryIso(Context context) {
1081             String countryIso = null;
1082             final CountryDetector detector = (CountryDetector) context.getSystemService(
1083                     Context.COUNTRY_DETECTOR);
1084             if (detector != null) {
1085                 final Country country = detector.detectCountry();
1086                 if (country != null) {
1087                     countryIso = country.getCountryIso();
1088                 }
1089             }
1090             return countryIso;
1091         }
1092     }
1093 }
1094