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