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
18package android.provider;
19
20import android.content.ContentProvider;
21import android.content.ContentResolver;
22import android.content.ContentValues;
23import android.content.Context;
24import android.content.Intent;
25import android.content.pm.UserInfo;
26import android.database.Cursor;
27import android.location.Country;
28import android.location.CountryDetector;
29import android.net.Uri;
30import android.os.UserHandle;
31import android.os.UserManager;
32import android.provider.ContactsContract.CommonDataKinds.Callable;
33import android.provider.ContactsContract.CommonDataKinds.Phone;
34import android.provider.ContactsContract.Data;
35import android.provider.ContactsContract.DataUsageFeedback;
36import android.telecom.PhoneAccount;
37import android.telecom.PhoneAccountHandle;
38import android.telecom.TelecomManager;
39import android.telephony.PhoneNumberUtils;
40import android.text.TextUtils;
41import android.util.Log;
42
43import com.android.internal.telephony.CallerInfo;
44import com.android.internal.telephony.PhoneConstants;
45
46import java.util.List;
47
48/**
49 * The CallLog provider contains information about placed and received calls.
50 */
51public class CallLog {
52    private static final String LOG_TAG = "CallLog";
53    private static final boolean VERBOSE_LOG = false; // DON'T SUBMIT WITH TRUE.
54
55    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
63
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
74    /**
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
84        /** @hide */
85        public static final Uri SHADOW_CONTENT_URI =
86                Uri.parse("content://call_log_shadow/calls");
87
88        /**
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        /**
95         * 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        /**
109         * 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        /**
122         * 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         */
140        public static final String EXTRA_CALL_TYPE_FILTER =
141                "android.provider.extra.CALL_TYPE_FILTER";
142
143        /**
144         * Content uri used to access call log entries, including voicemail records. You must have
145         * 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.
147         */
148        public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
149                .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
150                .build();
151
152        /**
153         * 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        /**
170         * The type of the call (incoming, outgoing or missed).
171         * <P>Type: INTEGER (int)</P>
172         *
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>
182         * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li>
183         * </ul>
184         * </p>
185         */
186        public static final String TYPE = "type";
187
188        /** Call log type for incoming calls. */
189        public static final int INCOMING_TYPE = 1;
190        /** Call log type for outgoing calls. */
191        public static final int OUTGOING_TYPE = 2;
192        /** Call log type for missed calls. */
193        public static final int MISSED_TYPE = 3;
194        /** Call log type for voicemails. */
195        public static final int VOICEMAIL_TYPE = 4;
196        /** 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;
200        /**
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;
206
207        /**
208         * 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
214        /** Call had video. */
215        public static final int FEATURES_VIDEO = 1 << 0;
216
217        /** Call was pulled externally. */
218        public static final int FEATURES_PULLED_EXTERNALLY = 1 << 1;
219
220        /** Call was HD. */
221        public static final int FEATURES_HD_CALL = 1 << 2;
222
223        /** Call was WIFI call. */
224        public static final int FEATURES_WIFI = 1 << 3;
225
226        /**
227         * Indicates the call underwent Assisted Dialing.
228         * @hide
229         */
230        public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4;
231
232        /** Call was on RTT at some point */
233        public static final int FEATURES_RTT = 1 << 5;
234
235        /**
236         * The phone number as the user entered it.
237         * <P>Type: TEXT</P>
238         */
239        public static final String NUMBER = "number";
240
241        /**
242         * 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         *
254         * <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        /**
268         * 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>
273         */
274        public static final String COUNTRY_ISO = "countryiso";
275
276        /**
277         * 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        /**
289         * 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        /**
295         * 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.
302         *
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.
306         * <P>Type: TEXT</P>
307         */
308        public static final String CACHED_NAME = "name";
309
310        /**
311         * The cached number type (Home, Work, etc) associated with the
312         * phone number, if it exists.
313         *
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.
317         * <P>Type: INTEGER</P>
318         */
319        public static final String CACHED_NUMBER_TYPE = "numbertype";
320
321        /**
322         * The cached number label, for a custom number type, associated with the
323         * phone number, if it exists.
324         *
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.
328         * <P>Type: TEXT</P>
329         */
330        public static final String CACHED_NUMBER_LABEL = "numberlabel";
331
332        /**
333         * URI of the voicemail entry. Populated only for {@link #VOICEMAIL_TYPE}.
334         * <P>Type: TEXT</P>
335         */
336        public static final String VOICEMAIL_URI = "voicemail_uri";
337
338        /**
339         * 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        /**
345         * 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        /**
352         * 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>
357         */
358        public static final String IS_READ = "is_read";
359
360        /**
361         * 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>
365         */
366        public static final String GEOCODED_LOCATION = "geocoded_location";
367
368        /**
369         * The cached URI to look up the contact associated with the phone number, if it exists.
370         *
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.
374         * <P>Type: TEXT</P>
375         */
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.
380         *
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.
384         * <P>Type: TEXT</P>
385         */
386        public static final String CACHED_MATCHED_NUMBER = "matched_number";
387
388        /**
389         * The cached normalized(E164) version of the phone number, if it exists.
390         *
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.
394         * <P>Type: TEXT</P>
395         */
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.
400         *
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.
404         * <P>Type: INTEGER (long)</P>
405         */
406        public static final String CACHED_PHOTO_ID = "photo_id";
407
408        /**
409         * The cached photo URI of the picture associated with the phone number, if it exists.
410         *
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.
414         * <P>Type: TEXT (URI)</P>
415         */
416        public static final String CACHED_PHOTO_URI = "photo_uri";
417
418        /**
419         * The cached phone number, formatted with formatting rules based on the country the
420         * user was in when the call was made or received.
421         *
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.
425         * <P>Type: TEXT</P>
426         */
427        public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
428
429        // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
430        // that was encoded into call log databases.
431
432        /**
433         * The component name of the account used to place or receive the call; in string form.
434         * <P>Type: TEXT</P>
435         */
436        public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
437
438        /**
439         * The identifier for the account used to place or receive the call.
440         * <P>Type: TEXT</P>
441         */
442        public static final String PHONE_ACCOUNT_ID = "subscription_id";
443
444        /**
445         * 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        /**
454         * 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        /**
463         * 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.
466         * <P>Type: INTEGER</P>
467         *
468         * @Deprecated
469         * @hide
470         */
471        public static final String SUB_ID = "sub_id";
472
473        /**
474         * 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        /**
482         * 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        /**
489         * 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        /**
497         * 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        /**
504         * 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        /**
511         * 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
517         * @param presentation enum value from PhoneConstants.PRESENTATION_xxx, which
518         *        is set by the network and denotes the number presenting rules for
519         *        "allowed", "payphone", "restricted" or "unknown"
520         * @param callType enumerated values for "incoming", "outgoing", or "missed"
521         * @param features features of the call (e.g. Video).
522         * @param accountHandle The accountHandle object identifying the provider of the call
523         * @param start time stamp for the call in milliseconds
524         * @param duration call duration in seconds
525         * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for
526         *                  the call.
527         * @result The URI of the call log entry belonging to the user that made or received this
528         *        call.
529         * {@hide}
530         */
531        public static Uri addCall(CallerInfo ci, Context context, String number,
532                int presentation, int callType, int features, PhoneAccountHandle accountHandle,
533                long start, int duration, Long dataUsage) {
534            return addCall(ci, context, number, /* postDialDigits =*/ "", /* viaNumber =*/ "",
535                    presentation, callType, features, accountHandle, start, duration,
536                    dataUsage, /* addForAllUsers =*/ false, /* userToBeInsertedTo =*/ null,
537                    /* is_read =*/ false);
538        }
539
540
541        /**
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
548         * @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 ''.
550         * @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.
562         * @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.
565         * @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,
570                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);
576        }
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
585         * @param postDialDigits the post-dial digits that were dialed after the number,
586         *        if it was outgoing. Otherwise it is ''.
587         * @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 ''.
589         * @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.
601         * @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.
604         * @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
608         *        call.  This could be of the shadow provider.  Do not return it to non-system apps,
609         *        as they don't have permissions.
610         * {@hide}
611         */
612        public static Uri addCall(CallerInfo ci, Context context, String number,
613                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) {
617            if (VERBOSE_LOG) {
618                Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
619                        number, userToBeInsertedTo, addForAllUsers));
620            }
621            final ContentResolver resolver = context.getContentResolver();
622            int numberPresentation = PRESENTATION_ALLOWED;
623
624            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) {
633                    Uri address = account.getSubscriptionAddress();
634                    if (address != null) {
635                        accountAddress = address.getSchemeSpecificPart();
636                    }
637                }
638            }
639
640            // 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.
645            if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
646                numberPresentation = PRESENTATION_RESTRICTED;
647            } else if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
648                numberPresentation = PRESENTATION_PAYPHONE;
649            } else if (TextUtils.isEmpty(number)
650                    || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
651                numberPresentation = PRESENTATION_UNKNOWN;
652            }
653            if (numberPresentation != PRESENTATION_ALLOWED) {
654                number = "";
655                if (ci != null) {
656                    ci.name = "";
657                }
658            }
659
660            // accountHandle information
661            String accountComponentString = null;
662            String accountId = null;
663            if (accountHandle != null) {
664                accountComponentString = accountHandle.getComponentName().flattenToString();
665                accountId = accountHandle.getId();
666            }
667
668            ContentValues values = new ContentValues(6);
669
670            values.put(NUMBER, number);
671            values.put(POST_DIAL_DIGITS, postDialDigits);
672            values.put(VIA_NUMBER, viaNumber);
673            values.put(NUMBER_PRESENTATION, Integer.valueOf(numberPresentation));
674            values.put(TYPE, Integer.valueOf(callType));
675            values.put(FEATURES, features);
676            values.put(DATE, Long.valueOf(start));
677            values.put(DURATION, Long.valueOf(duration));
678            if (dataUsage != null) {
679                values.put(DATA_USAGE, dataUsage);
680            }
681            values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
682            values.put(PHONE_ACCOUNT_ID, accountId);
683            values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
684            values.put(NEW, Integer.valueOf(1));
685            values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
686
687            if (callType == MISSED_TYPE) {
688                values.put(IS_READ, Integer.valueOf(is_read ? 1 : 0));
689            }
690
691            if ((ci != null) && (ci.contactIdOrZero > 0)) {
692                // 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 + " =?",
705                            new String[] { String.valueOf(ci.contactIdOrZero),
706                                    normalizedPhoneNumber},
707                            null);
708                } else {
709                    final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
710                    cursor = resolver.query(
711                            Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
712                                    Uri.encode(phoneNumber)),
713                            new String[] { Phone._ID },
714                            Phone.CONTACT_ID + " =?",
715                            new String[] { String.valueOf(ci.contactIdOrZero) },
716                            null);
717                }
718
719                if (cursor != null) {
720                    try {
721                        if (cursor.getCount() > 0 && cursor.moveToFirst()) {
722                            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                            }
729                        }
730                    } finally {
731                        cursor.close();
732                    }
733                }
734            }
735
736            /*
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
758            Uri result = null;
759
760            final UserManager userManager = context.getSystemService(UserManager.class);
761            final int currentUserId = userManager.getUserHandle();
762
763            if (addForAllUsers) {
764                // 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
782                final int count = users.size();
783                for (int i = 0; i < count; i++) {
784                    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.
801                    if (userManager.isUserRunning(userHandle)
802                            && userManager.isUserUnlocked(userHandle)) {
803                        final Uri uri = addEntryAndRemoveExpiredEntries(context, userManager,
804                                userHandle, values);
805                        if (userId == currentUserId) {
806                            result = uri;
807                        }
808                    }
809                }
810            } else {
811                // 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);
819            }
820            return result;
821        }
822
823        /** @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
834        /**
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
859        private static Uri addEntryAndRemoveExpiredEntries(Context context, UserManager userManager,
860                UserHandle user, ContentValues values) {
861            final ContentResolver resolver = context.getContentResolver();
862
863            // Since we're doing this operation on behalf of an app, we only
864            // want to use the actual "unlocked" state.
865            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 {
874                // 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.
880                final Uri result = resolver.insert(uri, values);
881                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
902                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            }
910        }
911
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        }
956    }
957}
958