CallLogManager.java revision 71280ff9e02e476fe4a86170ffe6c769e0e6c27c
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
19f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.content.Context;
20271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiangimport android.content.Intent;
21f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.net.Uri;
22f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.os.AsyncTask;
2398e6bdc795585b0d332a7eb86245926c8d80609aTony Makimport android.os.UserHandle;
24a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawalimport android.os.PersistableBundle;
25f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.provider.CallLog.Calls;
26701dc006ac11625b55d872f1639107b028933895Andrew Leeimport android.telecom.DisconnectCause;
2798e6bdc795585b0d332a7eb86245926c8d80609aTony Makimport android.telecom.PhoneAccount;
287cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle;
297cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.VideoProfile;
30a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawalimport android.telephony.CarrierConfigManager;
31f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Leeimport android.telephony.PhoneNumberUtils;
32f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
3391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R;
34ada0301a8190568d90adba04bd1f555b7894a0e1Hall Liuimport com.android.internal.annotations.VisibleForTesting;
356f3f7affb13e93cb70868d3114f02f1ed593194eYorke Leeimport com.android.internal.telephony.CallerInfo;
36f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
37f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee/**
38f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * Helper class that provides functionality to write information about calls and their associated
39f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * caller details to the call log. All logging activity will be performed asynchronously in a
40f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * background thread to avoid blocking on the main thread.
41f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee */
42ada0301a8190568d90adba04bd1f555b7894a0e1Hall Liu@VisibleForTesting
43ada0301a8190568d90adba04bd1f555b7894a0e1Hall Liupublic final class CallLogManager extends CallsManagerListenerBase {
44f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
45f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Parameter object to hold the arguments to add a call in the call log DB.
46f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
47f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private static class AddCallArgs {
48f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        /**
4989176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton         * @param callerInfo Caller details.
50f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param number The phone number to be logged.
51f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param presentation Number presentation of the phone number to be logged.
52f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param callType The type of call (e.g INCOMING_TYPE). @see
53f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         *     {@link android.provider.CallLog} for the list of values.
54765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn         * @param features The features of the call (e.g. FEATURES_VIDEO). @see
55765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn         *     {@link android.provider.CallLog} for the list of values.
56f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param creationDate Time when the call was created (milliseconds since epoch).
57f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * @param durationInMillis Duration of the call (milliseconds).
58765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn         * @param dataUsage Data usage in bytes, or null if not applicable.
59f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         */
60baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger        public AddCallArgs(Context context, CallerInfo callerInfo, String number,
61baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                String postDialDigits, String viaNumber, int presentation, int callType,
62baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                int features, PhoneAccountHandle accountHandle, long creationDate,
63baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                long durationInMillis, Long dataUsage, UserHandle initiatingUser) {
64f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.context = context;
656f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee            this.callerInfo = callerInfo;
66f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.number = number;
67b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu            this.postDialDigits = postDialDigits;
68baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger            this.viaNumber = viaNumber;
69f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.presentation = presentation;
70f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.callType = callType;
71765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            this.features = features;
7289176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton            this.accountHandle = accountHandle;
73f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.timestamp = creationDate;
74f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            this.durationInSec = (int)(durationInMillis / 1000);
75765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            this.dataUsage = dataUsage;
7698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            this.initiatingUser = initiatingUser;
77f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
78f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // Since the members are accessed directly, we don't use the
79f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // mXxxx notation.
80f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final Context context;
816f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee        public final CallerInfo callerInfo;
82f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final String number;
83b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu        public final String postDialDigits;
84baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger        public final String viaNumber;
85f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final int presentation;
86f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final int callType;
87765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn        public final int features;
8889176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton        public final PhoneAccountHandle accountHandle;
89f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final long timestamp;
90f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        public final int durationInSec;
91765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn        public final Long dataUsage;
9298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        public final UserHandle initiatingUser;
93f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
94f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
95f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private static final String TAG = CallLogManager.class.getSimpleName();
96f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
97f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private final Context mContext;
9898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
99271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String ACTION_CALLS_TABLE_ADD_ENTRY =
100271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang                "com.android.server.telecom.intent.action.CALLS_ADD_ENTRY";
101271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String PERMISSION_PROCESS_CALLLOG_INFO =
102271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang                "android.permission.PROCESS_CALLLOG_INFO";
103271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String CALL_TYPE = "callType";
104271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private static final String CALL_DURATION = "duration";
105f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
10698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak    public CallLogManager(Context context, PhoneAccountRegistrar phoneAccountRegistrar) {
107f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        mContext = context;
10898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        mPhoneAccountRegistrar = phoneAccountRegistrar;
109f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
110f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
111810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    @Override
1126fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    public void onCallStateChanged(Call call, int oldState, int newState) {
113ac19f3d150f22be843be4d9f75cb7b5c26e77914Nancy Chen        int disconnectCause = call.getDisconnectCause().getCode();
114672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        boolean isNewlyDisconnected =
115672321e603555849831dd88d5c9f93d88143ee48Santos Cordon                newState == CallState.DISCONNECTED || newState == CallState.ABORTED;
116ac19f3d150f22be843be4d9f75cb7b5c26e77914Nancy Chen        boolean isCallCanceled = isNewlyDisconnected && disconnectCause == DisconnectCause.CANCELED;
117672321e603555849831dd88d5c9f93d88143ee48Santos Cordon
118672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // Log newly disconnected calls only if:
119672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // 1) It was not in the "choose account" phase when disconnected
120672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // 2) It is a conference call
121672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        // 3) Call was not explicitly canceled
122672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        if (isNewlyDisconnected &&
12392694519535c54f542b4ef3973e9c1934f2feeffSantos Cordon                (oldState != CallState.SELECT_PHONE_ACCOUNT &&
124672321e603555849831dd88d5c9f93d88143ee48Santos Cordon                 !call.isConference() &&
125672321e603555849831dd88d5c9f93d88143ee48Santos Cordon                 !isCallCanceled)) {
126810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            int type;
127810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            if (!call.isIncoming()) {
128810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal                type = Calls.OUTGOING_TYPE;
129ac19f3d150f22be843be4d9f75cb7b5c26e77914Nancy Chen            } else if (disconnectCause == DisconnectCause.MISSED) {
130810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal                type = Calls.MISSED_TYPE;
131810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            } else {
132810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal                type = Calls.INCOMING_TYPE;
133810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            }
134810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            logCall(call, type);
135810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        }
136f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
137f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
138f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
139f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Logs a call to the call log based on the {@link Call} object passed in.
140f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
141f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param call The call object being logged
142f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param callLogType The type of call log entry to log this call as. See:
143f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     {@link android.provider.CallLog.Calls#INCOMING_TYPE}
144f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     {@link android.provider.CallLog.Calls#OUTGOING_TYPE}
145f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     {@link android.provider.CallLog.Calls#MISSED_TYPE}
146f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
147f193ba45fae5bc87e6a57779e4f5b56be59d08b0Santos Cordon    void logCall(Call call, int callLogType) {
1488c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        final long creationTime = call.getCreationTimeMillis();
1498c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        final long age = call.getAgeMillis();
150f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
151f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        final String logNumber = getLogNumber(call);
152f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
15333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        Log.d(TAG, "logNumber set to: %s", Log.pii(logNumber));
154f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
1552c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        final PhoneAccountHandle emergencyAccountHandle =
1562c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon                TelephonyUtil.getDefaultEmergencyPhoneAccount().getAccountHandle();
1572c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon
1582c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        PhoneAccountHandle accountHandle = call.getTargetPhoneAccount();
1592c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        if (emergencyAccountHandle.equals(accountHandle)) {
1602c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon            accountHandle = null;
1612c625f3dac466b1391caf0a8c6a04199f5f7e6b8Santos Cordon        }
162f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
1637a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn        Long callDataUsage = call.getCallDataUsage() == Call.DATA_USAGE_NOT_SET ? null :
1647a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn                call.getCallDataUsage();
1657a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn
1660a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        int callFeatures = getCallFeatures(call.getVideoStateHistory());
167baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger        logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), call.getViaNumber(),
168b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu                call.getHandlePresentation(), callLogType, callFeatures, accountHandle,
1697a1f8239f7d22faef49c1f89de522e908e2e43f8Tyler Gunn                creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser());
170f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
171f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
172f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
173f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Inserts a call into the call log, based on the parameters passed in.
174f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
1756f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee     * @param callerInfo Caller details.
176f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param number The number the call was made to or from.
177b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu     * @param postDialDigits The post-dial digits that were dialed after the number,
178b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu     *                       if it was an outgoing call. Otherwise ''.
179f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param presentation
180f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param callType The type of call.
181765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn     * @param features The features of the call.
182f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param start The start time of the call, in milliseconds.
183f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param duration The duration of the call, in milliseconds.
184765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn     * @param dataUsage The data usage for the call, null if not applicable.
1856ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn     * @param isEmergency {@code true} if this is an emergency call, {@code false} otherwise.
186f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
187f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private void logCall(
1886f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee            CallerInfo callerInfo,
189f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            String number,
190b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu            String postDialDigits,
191baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger            String viaNumber,
192f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            int presentation,
193f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            int callType,
194765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            int features,
19589176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton            PhoneAccountHandle accountHandle,
196f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            long start,
197765c35cee084e55614be4e3ee13f1279e6461da5Tyler Gunn            long duration,
1986ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn            Long dataUsage,
19998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            boolean isEmergency,
20098e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            UserHandle initiatingUser) {
201f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
202f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // On some devices, to avoid accidental redialing of emergency numbers, we *never* log
203f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // emergency calls to the Call Log.  (This behavior is set on a per-product basis, based
204f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // on carrier requirements.)
205a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        boolean okToLogEmergencyNumber = false;
206a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
207a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal                Context.CARRIER_CONFIG_SERVICE);
208a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        PersistableBundle configBundle = configManager.getConfig();
209a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        if (configBundle != null) {
210a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal            okToLogEmergencyNumber = configBundle.getBoolean(
211a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal                    CarrierConfigManager.KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL);
212a416e07f853958eb78cd4574c7236f0b76c68040Shishir Agrawal        }
213f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
214f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        // Don't log emergency numbers if the device doesn't allow it.
2156ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn        final boolean isOkToLogThisCall = !isEmergency || okToLogEmergencyNumber;
216f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
217271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        sendAddCallBroadcast(callType, duration);
218271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang
219f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        if (isOkToLogThisCall) {
2206f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee            Log.d(TAG, "Logging Calllog entry: " + callerInfo + ", "
221f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    + Log.pii(number) + "," + presentation + ", " + callType
222f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    + ", " + start + ", " + duration);
223b8ce19c04800b46e37385ea60795b21a7d14cdedHall Liu            AddCallArgs args = new AddCallArgs(mContext, callerInfo, number, postDialDigits,
224baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                    viaNumber, presentation, callType, features, accountHandle, start, duration,
225baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger                    dataUsage, initiatingUser);
226f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            logCallAsync(args);
227f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        } else {
228f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee          Log.d(TAG, "Not adding emergency call to call log.");
229f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
230f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
231f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
232f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
2330a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Based on the video state of the call, determines the call features applicable for the call.
2340a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     *
2350a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @param videoState The video state.
2360a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @return The call features.
2370a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     */
2380a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    private static int getCallFeatures(int videoState) {
2395b8824979e929250a46791c785b8459512236585Tyler Gunn        if (VideoProfile.isVideo(videoState)) {
2400a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn            return Calls.FEATURES_VIDEO;
2410a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        }
242ad5235dfde833ae2c5be986ba9f681d7538742d3Yorke Lee        return 0;
2430a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    }
2440a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
2450a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    /**
246f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Retrieve the phone number from the call, and then process it before returning the
247f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * actual number that is to be logged.
248f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
249f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param call The phone connection.
250f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return the phone number to be logged.
251f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
252f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private String getLogNumber(Call call) {
25333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        Uri handle = call.getOriginalHandle();
254f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
255f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        if (handle == null) {
256f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            return null;
257f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
258f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
259060d1d60f308bb903f7cd699747d014fab1ce70cYorke Lee        String handleString = handle.getSchemeSpecificPart();
260ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal        if (!PhoneNumberUtils.isUriNumber(handleString)) {
261ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal            handleString = PhoneNumberUtils.stripSeparators(handleString);
262f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
263ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal        return handleString;
264f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
265f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
266f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
267f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Adds the call defined by the parameters in the provided AddCallArgs to the CallLogProvider
268f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * using an AsyncTask to avoid blocking the main thread.
269f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *
270f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @param args Prepopulated call details.
271f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return A handle to the AsyncTask that will add the call to the call log asynchronously.
272f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
273f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    public AsyncTask<AddCallArgs, Void, Uri[]> logCallAsync(AddCallArgs args) {
274f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        return new LogCallAsyncTask().execute(args);
275f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
276f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
277f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
278f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * Helper AsyncTask to access the call logs database asynchronously since database operations
279f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * can take a long time depending on the system's load. Since it extends AsyncTask, it uses
280f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * its own thread pool.
281f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
282f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    private class LogCallAsyncTask extends AsyncTask<AddCallArgs, Void, Uri[]> {
283f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        @Override
284f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        protected Uri[] doInBackground(AddCallArgs... callList) {
285f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            int count = callList.length;
286f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            Uri[] result = new Uri[count];
287f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            for (int i = 0; i < count; i++) {
288f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                AddCallArgs c = callList[i];
289f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                try {
290f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // May block.
29198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    result[i] = addCall(c);
292f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                } catch (Exception e) {
293f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // This is very rare but may happen in legitimate cases.
294f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // E.g. If the phone is encrypted and thus write request fails, it may cause
295f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // some kind of Exception (right now it is IllegalArgumentException, but this
296f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // might change).
297f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    //
298f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // We don't want to crash the whole process just because of that, so just log
299f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    // it instead.
300f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    Log.e(TAG, e, "Exception raised during adding CallLog entry.");
301f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    result[i] = null;
302f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                }
303f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            }
304f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            return result;
305f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
306f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
30798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        private Uri addCall(AddCallArgs c) {
30898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            PhoneAccount phoneAccount = mPhoneAccountRegistrar
30998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    .getPhoneAccountUnchecked(c.accountHandle);
31071280ff9e02e476fe4a86170ffe6c769e0e6c27cHall Liu            if (phoneAccount != null &&
31171280ff9e02e476fe4a86170ffe6c769e0e6c27cHall Liu                    phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
31298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                if (c.initiatingUser != null &&
31398e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                        UserUtil.isManagedProfile(mContext, c.initiatingUser)) {
31498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    return addCall(c, c.initiatingUser);
31598e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                } else {
31698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    return addCall(c, null);
31798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                }
31898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            } else {
31971280ff9e02e476fe4a86170ffe6c769e0e6c27cHall Liu                return addCall(c, c.accountHandle == null ? null : c.accountHandle.getUserHandle());
32098e6bdc795585b0d332a7eb86245926c8d80609aTony Mak            }
32198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        }
32298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak
32398e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        /**
32498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         * Insert the call to a specific user or all users except managed profile.
32598e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         * @param c context
32698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         * @param userToBeInserted user handle of user that the call going be inserted to. null
32798e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         *                         if insert to all users except managed profile.
32898e6bdc795585b0d332a7eb86245926c8d80609aTony Mak         */
32998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        private Uri addCall(AddCallArgs c, UserHandle userToBeInserted) {
330baf52ba1520ef528b65329c813389b8183150f3dBrad Ebinger            return Calls.addCall(c.callerInfo, c.context, c.number, c.postDialDigits, c.viaNumber,
33198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    c.presentation, c.callType, c.features, c.accountHandle, c.timestamp,
33298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    c.durationInSec, c.dataUsage, userToBeInserted == null,
33398e6bdc795585b0d332a7eb86245926c8d80609aTony Mak                    userToBeInserted);
33498e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        }
33598e6bdc795585b0d332a7eb86245926c8d80609aTony Mak
336f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        /**
337f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * Performs a simple sanity check to make sure the call was written in the database.
338f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         * Typically there is only one result per call so it is easy to identify which one failed.
339f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee         */
340f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        @Override
341f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        protected void onPostExecute(Uri[] result) {
342f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            for (Uri uri : result) {
343f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                if (uri == null) {
344f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                    Log.w(TAG, "Failed to write call to the log.");
345f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee                }
346f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee            }
347f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee        }
348f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
349271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang
350271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    private void sendAddCallBroadcast(int callType, long duration) {
351271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        Intent callAddIntent = new Intent(ACTION_CALLS_TABLE_ADD_ENTRY);
352271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        callAddIntent.putExtra(CALL_TYPE, callType);
353271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        callAddIntent.putExtra(CALL_DURATION, duration);
354271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang        mContext.sendBroadcast(callAddIntent, PERMISSION_PROCESS_CALLLOG_INFO);
355271b9ae5fe05a3b46a954f0013d642aacea8e045Yong Jiang    }
3569f2bed31374a56487f370be01224baf6ce97e8adBen Gilad}
357