1f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee/*
2f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * Copyright 2014, The Android Open Source Project
3f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee *
4f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * Licensed under the Apache License, Version 2.0 (the "License");
5f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * you may not use this file except in compliance with the License.
6f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * You may obtain a copy of the License at
7f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee *
8f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee *     http://www.apache.org/licenses/LICENSE-2.0
9f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee *
10f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * Unless required by applicable law or agreed to in writing, software
11f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * distributed under the License is distributed on an "AS IS" BASIS,
12f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * See the License for the specific language governing permissions and
14f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * limitations under the License.
15f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee */
16f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
189f2bed31374a56487f370be01224baf6ce97e8adBen Gilad
19982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yenimport android.annotation.Nullable;
20f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.content.Context;
21271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiangimport android.content.Intent;
22c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebingerimport android.location.Country;
23c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebingerimport android.location.CountryDetector;
24c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebingerimport android.location.CountryListener;
25f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.net.Uri;
26f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.os.AsyncTask;
27c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebingerimport android.os.Looper;
2898e6bdc795585b0d332a7eb86245926c8d80609aTony Makimport android.os.UserHandle;
29a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawalimport android.os.PersistableBundle;
30f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.provider.CallLog.Calls;
31701dc006ac11625b55d872f1639107b028933895Andrew Leeimport android.telecom.DisconnectCause;
3298e6bdc795585b0d332a7eb86245926c8d80609aTony Makimport android.telecom.PhoneAccount;
337cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle;
347cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.VideoProfile;
35a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawalimport android.telephony.CarrierConfigManager;
36f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.telephony.PhoneNumberUtils;
37f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
3891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R;
39ada0301a8190568d90adba04bd1f555b7894a0e1Hall Liuimport com.android.internal.annotations.VisibleForTesting;
406f3f7affb13e93cb70868d3114f02f1ed593194eYorke Leeimport com.android.internal.telephony.CallerInfo;
41f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
42c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebingerimport java.util.Locale;
43c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
44f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee/**
45f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * Helper class that provides functionality to write information about calls and their associated
46f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * caller details to the call log. All logging activity will be performed asynchronously in a
47f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * background thread to avoid blocking on the main thread.
48f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee */
49ada0301a8190568d90adba04bd1f555b7894a0e1Hall Liu@VisibleForTesting
50ada0301a8190568d90adba04bd1f555b7894a0e1Hall Liupublic final class CallLogManager extends CallsManagerListenerBase {
51982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
52982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    public interface LogCallCompletedListener {
53982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        void onLogCompleted(@Nullable Uri uri);
54982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    }
55982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
56f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
57f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Parameter object to hold the arguments to add a call in the call log DB.
58f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
59f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private static class AddCallArgs {
60f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        /**
6189176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton         * @param callerInfo Caller details.
62f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param number The phone number to be logged.
63f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param presentation Number presentation of the phone number to be logged.
64f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param callType The type of call (e.g INCOMING_TYPE). @see
65f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         *     {@link android.provider.CallLog} for the list of values.
66765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn         * @param features The features of the call (e.g. FEATURES_VIDEO). @see
67765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn         *     {@link android.provider.CallLog} for the list of values.
68f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param creationDate Time when the call was created (milliseconds since epoch).
69f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param durationInMillis Duration of the call (milliseconds).
70765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn         * @param dataUsage Data usage in bytes, or null if not applicable.
71982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen         * @param logCallCompletedListener optional callback called after the call is logged.
72f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         */
73baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger        public AddCallArgs(Context context, CallerInfo callerInfo, String number,
74baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                String postDialDigits, String viaNumber, int presentation, int callType,
75baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                int features, PhoneAccountHandle accountHandle, long creationDate,
76982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                long durationInMillis, Long dataUsage, UserHandle initiatingUser,
77982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                @Nullable LogCallCompletedListener logCallCompletedListener) {
78f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.context = context;
796f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee            this.callerInfo = callerInfo;
80f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.number = number;
81b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu            this.postDialDigits = postDialDigits;
82baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger            this.viaNumber = viaNumber;
83f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.presentation = presentation;
84f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.callType = callType;
85765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            this.features = features;
8689176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton            this.accountHandle = accountHandle;
87f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.timestamp = creationDate;
88f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.durationInSec = (int)(durationInMillis / 1000);
89765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            this.dataUsage = dataUsage;
9098e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            this.initiatingUser = initiatingUser;
91982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            this.logCallCompletedListener = logCallCompletedListener;
92f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
93f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // Since the members are accessed directly, we don't use the
94f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // mXxxx notation.
95f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final Context context;
966f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee        public final CallerInfo callerInfo;
97f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final String number;
98b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu        public final String postDialDigits;
99baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger        public final String viaNumber;
100f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final int presentation;
101f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final int callType;
102765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn        public final int features;
10389176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton        public final PhoneAccountHandle accountHandle;
104f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final long timestamp;
105f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final int durationInSec;
106765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn        public final Long dataUsage;
10798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        public final UserHandle initiatingUser;
108982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
109982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        @Nullable
110982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        public final LogCallCompletedListener logCallCompletedListener;
111f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
112f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
113f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private static final String TAG = CallLogManager.class.getSimpleName();
114f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
115f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private final Context mContext;
11698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
117982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    private final MissedCallNotifier mMissedCallNotifier;
118271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String ACTION_CALLS_TABLE_ADD_ENTRY =
119271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang                "com.android.server.telecom.intent.action.CALLS_ADD_ENTRY";
120271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String PERMISSION_PROCESS_CALLLOG_INFO =
121271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang                "android.permission.PROCESS_CALLLOG_INFO";
122271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String CALL_TYPE = "callType";
123271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String CALL_DURATION = "duration";
124f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
125c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    private Object mLock;
126c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    private String mCurrentCountryIso;
127c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
128982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    public CallLogManager(Context context, PhoneAccountRegistrar phoneAccountRegistrar,
129982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            MissedCallNotifier missedCallNotifier) {
130f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        mContext = context;
13198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        mPhoneAccountRegistrar = phoneAccountRegistrar;
132982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        mMissedCallNotifier = missedCallNotifier;
133c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        mLock = new Object();
134f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
135f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
136810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    @Override
1376fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    public void onCallStateChanged(Call call, int oldState, int newState) {
138ac19f3d150f22be843be4d9f75cb7b5c26e77914Nancy Chen        int disconnectCause = call.getDisconnectCause().getCode();
139672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        boolean isNewlyDisconnected =
140672321e603555849831dd88d5c9f93d88143ee48Santos Cordon                newState == CallState.DISCONNECTED || newState == CallState.ABORTED;
141ac19f3d150f22be843be4d9f75cb7b5c26e77914Nancy Chen        boolean isCallCanceled = isNewlyDisconnected && disconnectCause == DisconnectCause.CANCELED;
142672321e603555849831dd88d5c9f93d88143ee48Santos Cordon
143672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // Log newly disconnected calls only if:
144672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // 1) It was not in the "choose account" phase when disconnected
145672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // 2) It is a conference call
146672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // 3) Call was not explicitly canceled
147d1660282032b8145a9d24f6ce80ab60ac29a9217Tyler Gunn        // 4) Call is not an external call
148672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        if (isNewlyDisconnected &&
14992694519535c54f542b4ef3973e9c1934f2feeffSantos Cordon                (oldState != CallState.SELECT_PHONE_ACCOUNT &&
150672321e603555849831dd88d5c9f93d88143ee48Santos Cordon                 !call.isConference() &&
151d1660282032b8145a9d24f6ce80ab60ac29a9217Tyler Gunn                 !isCallCanceled) &&
152d1660282032b8145a9d24f6ce80ab60ac29a9217Tyler Gunn                !call.isExternalCall()) {
153810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            int type;
154810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            if (!call.isIncoming()) {
155810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal                type = Calls.OUTGOING_TYPE;
156ac19f3d150f22be843be4d9f75cb7b5c26e77914Nancy Chen            } else if (disconnectCause == DisconnectCause.MISSED) {
157810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal                type = Calls.MISSED_TYPE;
15881c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn            } else if (disconnectCause == DisconnectCause.ANSWERED_ELSEWHERE) {
15981c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn                type = Calls.ANSWERED_EXTERNALLY_TYPE;
16021991a7e6452a15e4f02a645b8333d5376d0a8e9Tyler Gunn            } else if (disconnectCause == DisconnectCause.REJECTED) {
16121991a7e6452a15e4f02a645b8333d5376d0a8e9Tyler Gunn                type = Calls.REJECTED_TYPE;
162810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            } else {
163810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal                type = Calls.INCOMING_TYPE;
164810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            }
165982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            logCall(call, type, true /*showNotificationForMissedCall*/);
166982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        }
167982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    }
168982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
169982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    void logCall(Call call, int type, boolean showNotificationForMissedCall) {
170982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        if (type == Calls.MISSED_TYPE && showNotificationForMissedCall) {
171982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            logCall(call, Calls.MISSED_TYPE,
172982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                    new LogCallCompletedListener() {
173982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                        @Override
174982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                        public void onLogCompleted(@Nullable Uri uri) {
175982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                            mMissedCallNotifier.showMissedCallNotification(call);
176982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                        }
177982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                    });
178982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        } else {
179982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            logCall(call, type, null);
180810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        }
181f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
182f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
183f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
184f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Logs a call to the call log based on the {@link Call} object passed in.
185f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
186f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param call The call object being logged
187f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param callLogType The type of call log entry to log this call as. See:
188f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     {@link android.provider.CallLog.Calls#INCOMING_TYPE}
189f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     {@link android.provider.CallLog.Calls#OUTGOING_TYPE}
190f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     {@link android.provider.CallLog.Calls#MISSED_TYPE}
191982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen     * @param logCallCompletedListener optional callback called after the call is logged.
192f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
193982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen    void logCall(Call call, int callLogType,
194982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        @Nullable LogCallCompletedListener logCallCompletedListener) {
1958c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        final long creationTime = call.getCreationTimeMillis();
1968c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        final long age = call.getAgeMillis();
197f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
198f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        final String logNumber = getLogNumber(call);
199f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
20033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        Log.d(TAG, "logNumber set to: %s", Log.pii(logNumber));
201f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
2022c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        final PhoneAccountHandle emergencyAccountHandle =
2032c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon                TelephonyUtil.getDefaultEmergencyPhoneAccount().getAccountHandle();
2042c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon
205c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        String formattedViaNumber = PhoneNumberUtils.formatNumber(call.getViaNumber(),
206c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                getCountryIso());
207c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        formattedViaNumber = (formattedViaNumber != null) ?
208c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                formattedViaNumber : call.getViaNumber();
209c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
2102c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        PhoneAccountHandle accountHandle = call.getTargetPhoneAccount();
2112c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        if (emergencyAccountHandle.equals(accountHandle)) {
2122c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon            accountHandle = null;
2132c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        }
214f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
2157a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn        Long callDataUsage = call.getCallDataUsage() == Call.DATA_USAGE_NOT_SET ? null :
2167a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn                call.getCallDataUsage();
2177a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn
21881c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn        int callFeatures = getCallFeatures(call.getVideoStateHistory(),
21981c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn                call.getDisconnectCause().getCode() == DisconnectCause.CALL_PULLED);
220c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,
221b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu                call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
222982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(),
223982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                logCallCompletedListener);
224f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
225f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
226f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
227f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Inserts a call into the call log, based on the parameters passed in.
228f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
2296f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee     * @param callerInfo Caller details.
230f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param number The number the call was made to or from.
231b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu     * @param postDialDigits The post-dial digits that were dialed after the number,
232b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu     *                       if it was an outgoing call. Otherwise ''.
233f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param presentation
234f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param callType The type of call.
235765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn     * @param features The features of the call.
236f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param start The start time of the call, in milliseconds.
237f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param duration The duration of the call, in milliseconds.
238765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn     * @param dataUsage The data usage for the call, null if not applicable.
2396ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn     * @param isEmergency {@code true} if this is an emergency call, {@code false} otherwise.
240982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen     * @param logCallCompletedListener optional callback called after the call is logged.
241f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
242f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private void logCall(
2436f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee            CallerInfo callerInfo,
244f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            String number,
245b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu            String postDialDigits,
246baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger            String viaNumber,
247f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            int presentation,
248f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            int callType,
249765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            int features,
25089176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton            PhoneAccountHandle accountHandle,
251f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            long start,
252765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            long duration,
2536ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn            Long dataUsage,
25498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            boolean isEmergency,
255982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            UserHandle initiatingUser,
256982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            @Nullable LogCallCompletedListener logCallCompletedListener) {
257f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
258f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // On some devices, to avoid accidental redialing of emergency numbers, we *never* log
259f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // emergency calls to the Call Log.  (This behavior is set on a per-product basis, based
260f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // on carrier requirements.)
261a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        boolean okToLogEmergencyNumber = false;
262a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
263a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal                Context.CARRIER_CONFIG_SERVICE);
264a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        PersistableBundle configBundle = configManager.getConfig();
265a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        if (configBundle != null) {
266a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal            okToLogEmergencyNumber = configBundle.getBoolean(
267a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal                    CarrierConfigManager.KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL);
268a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        }
269f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
270f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // Don't log emergency numbers if the device doesn't allow it.
2716ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn        final boolean isOkToLogThisCall = !isEmergency || okToLogEmergencyNumber;
272f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
273271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        sendAddCallBroadcast(callType, duration);
274271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang
275f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        if (isOkToLogThisCall) {
2766f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee            Log.d(TAG, "Logging Calllog entry: " + callerInfo + ", "
277f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    + Log.pii(number) + "," + presentation + ", " + callType
278f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    + ", " + start + ", " + duration);
279b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu            AddCallArgs args = new AddCallArgs(mContext, callerInfo, number, postDialDigits,
280baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                    viaNumber, presentation, callType, features, accountHandle, start, duration,
281982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                    dataUsage, initiatingUser, logCallCompletedListener);
282f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            logCallAsync(args);
283f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        } else {
284f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee          Log.d(TAG, "Not adding emergency call to call log.");
285f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
286f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
287f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
288f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
2890a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Based on the video state of the call, determines the call features applicable for the call.
2900a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     *
2910a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @param videoState The video state.
29281c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn     * @param isPulledCall {@code true} if this call was pulled to another device.
2930a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @return The call features.
2940a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     */
29581c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn    private static int getCallFeatures(int videoState, boolean isPulledCall) {
29681c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn        int features = 0;
2975b8824979e929250a46791c785b8459512236585Tyler Gunn        if (VideoProfile.isVideo(videoState)) {
29881c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn            features |= Calls.FEATURES_VIDEO;
2990a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        }
30081c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn        if (isPulledCall) {
30181c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn            features |= Calls.FEATURES_PULLED_EXTERNALLY;
30281c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn        }
30381c7afe28708141ff51abe88d8e8bf9195746613Tyler Gunn        return features;
3040a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    }
3050a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
3060a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    /**
307f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Retrieve the phone number from the call, and then process it before returning the
308f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * actual number that is to be logged.
309f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
310f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param call The phone connection.
311f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return the phone number to be logged.
312f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
313f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private String getLogNumber(Call call) {
31433501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        Uri handle = call.getOriginalHandle();
315f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
316f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        if (handle == null) {
317f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            return null;
318f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
319f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
320060d1d60f308bb903f7cd699747d014fab1ce70cYorke Lee        String handleString = handle.getSchemeSpecificPart();
321ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal        if (!PhoneNumberUtils.isUriNumber(handleString)) {
322ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal            handleString = PhoneNumberUtils.stripSeparators(handleString);
323f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
324ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal        return handleString;
325f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
326f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
327f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
328f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Adds the call defined by the parameters in the provided AddCallArgs to the CallLogProvider
329f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * using an AsyncTask to avoid blocking the main thread.
330f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
331f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param args Prepopulated call details.
332f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return A handle to the AsyncTask that will add the call to the call log asynchronously.
333f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
334f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    public AsyncTask<AddCallArgs, Void, Uri[]> logCallAsync(AddCallArgs args) {
335f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        return new LogCallAsyncTask().execute(args);
336f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
337f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
338f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
339f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Helper AsyncTask to access the call logs database asynchronously since database operations
340f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * can take a long time depending on the system's load. Since it extends AsyncTask, it uses
341f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * its own thread pool.
342f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
343f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private class LogCallAsyncTask extends AsyncTask<AddCallArgs, Void, Uri[]> {
344982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
345982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen        private LogCallCompletedListener[] mListeners;
346982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
347f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        @Override
348f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        protected Uri[] doInBackground(AddCallArgs... callList) {
349f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            int count = callList.length;
350f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            Uri[] result = new Uri[count];
351982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            mListeners = new LogCallCompletedListener[count];
352f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            for (int i = 0; i < count; i++) {
353f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                AddCallArgs c = callList[i];
354982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                mListeners[i] = c.logCallCompletedListener;
355f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                try {
356f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // May block.
35798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    result[i] = addCall(c);
358f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                } catch (Exception e) {
359f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // This is very rare but may happen in legitimate cases.
360f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // E.g. If the phone is encrypted and thus write request fails, it may cause
361f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // some kind of Exception (right now it is IllegalArgumentException, but this
362f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // might change).
363f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    //
364f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // We don't want to crash the whole process just because of that, so just log
365f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // it instead.
366f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    Log.e(TAG, e, "Exception raised during adding CallLog entry.");
367f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    result[i] = null;
368f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                }
369f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            }
370f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            return result;
371f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
372f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
37398e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        private Uri addCall(AddCallArgs c) {
37498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            PhoneAccount phoneAccount = mPhoneAccountRegistrar
37598e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    .getPhoneAccountUnchecked(c.accountHandle);
37671280ff9e02e476fe4a86170ffe6c769e0e6c27cHall Liu            if (phoneAccount != null &&
37771280ff9e02e476fe4a86170ffe6c769e0e6c27cHall Liu                    phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
37898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                if (c.initiatingUser != null &&
37998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                        UserUtil.isManagedProfile(mContext, c.initiatingUser)) {
38098e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    return addCall(c, c.initiatingUser);
38198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                } else {
38298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    return addCall(c, null);
38398e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                }
38498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            } else {
38571280ff9e02e476fe4a86170ffe6c769e0e6c27cHall Liu                return addCall(c, c.accountHandle == null ? null : c.accountHandle.getUserHandle());
38698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            }
38798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        }
38898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak
38998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        /**
39098e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         * Insert the call to a specific user or all users except managed profile.
39198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         * @param c context
39298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         * @param userToBeInserted user handle of user that the call going be inserted to. null
39398e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         *                         if insert to all users except managed profile.
39498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         */
39598e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        private Uri addCall(AddCallArgs c, UserHandle userToBeInserted) {
396baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger            return Calls.addCall(c.callerInfo, c.context, c.number, c.postDialDigits, c.viaNumber,
39798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    c.presentation, c.callType, c.features, c.accountHandle, c.timestamp,
39898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    c.durationInSec, c.dataUsage, userToBeInserted == null,
39998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    userToBeInserted);
40098e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        }
40198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak
402982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen
403f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        @Override
404f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        protected void onPostExecute(Uri[] result) {
405982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen            for (int i = 0; i < result.length; i++) {
406982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                Uri uri = result[i];
407982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                /*
408982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                 Performs a simple sanity check to make sure the call was written in the database.
409982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                 Typically there is only one result per call so it is easy to identify which one
410982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                 failed.
411982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                 */
412f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                if (uri == null) {
413f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    Log.w(TAG, "Failed to write call to the log.");
414f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                }
415982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                if (mListeners[i] != null) {
416982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                    mListeners[i].onLogCompleted(uri);
417982c0bd962bc7ed208d0e73380e90b0fdcdf01dcTa-wei Yen                }
418f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            }
419f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
420f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
421271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang
422271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private void sendAddCallBroadcast(int callType, long duration) {
423271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        Intent callAddIntent = new Intent(ACTION_CALLS_TABLE_ADD_ENTRY);
424271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        callAddIntent.putExtra(CALL_TYPE, callType);
425271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        callAddIntent.putExtra(CALL_DURATION, duration);
426271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        mContext.sendBroadcast(callAddIntent, PERMISSION_PROCESS_CALLLOG_INFO);
427271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    }
428c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
429c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    private String getCountryIsoFromCountry(Country country) {
430c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        if(country == null) {
431c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger            // Fallback to Locale if there are issues with CountryDetector
432c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger            Log.w(TAG, "Value for country was null. Falling back to Locale.");
433c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger            return Locale.getDefault().getCountry();
434c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        }
435c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
436c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        return country.getCountryIso();
437c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    }
438c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
439c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    /**
440c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger     * Get the current country code
441c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger     *
442c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger     * @return the ISO 3166-1 two letters country code of current country.
443c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger     */
444c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    public String getCountryIso() {
445c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        synchronized (mLock) {
446c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger            if (mCurrentCountryIso == null) {
447c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                Log.i(TAG, "Country cache is null. Detecting Country and Setting Cache...");
448c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                final CountryDetector countryDetector =
449c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                        (CountryDetector) mContext.getSystemService(Context.COUNTRY_DETECTOR);
450c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                Country country = null;
451c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                if (countryDetector != null) {
452c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                    country = countryDetector.detectCountry();
453c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger
454c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                    countryDetector.addCountryListener((newCountry) -> {
455c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                        Log.startSession("CLM.oCD");
456c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                        try {
457c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                            synchronized (mLock) {
458c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                                Log.i(TAG, "Country ISO changed. Retrieving new ISO...");
459c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                                mCurrentCountryIso = getCountryIsoFromCountry(newCountry);
460c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                            }
461c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                        } finally {
462c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                            Log.endSession();
463c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                        }
464c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                    }, Looper.getMainLooper());
465c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                }
466c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger                mCurrentCountryIso = getCountryIsoFromCountry(country);
467c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger            }
468c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger            return mCurrentCountryIso;
469c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger        }
470c6ab2cca08ff427174b790a0ed34ebb19b1ce9cdBrad Ebinger    }
4719f2bed31374a56487f370be01224baf6ce97e8adBen Gilad}
472