Loading src/com/android/server/telecom/CallLogManager.java +54 −21 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.telephony.PhoneNumberUtils; // TODO: Needed for move to system service: import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallerInfo; import com.android.server.telecom.callfiltering.CallFilteringResult; import java.util.Arrays; import java.util.HashSet; Loading Loading @@ -83,7 +84,8 @@ public final class CallLogManager extends CallsManagerListenerBase { String postDialDigits, String viaNumber, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long creationDate, long durationInMillis, Long dataUsage, UserHandle initiatingUser, boolean isRead, @Nullable LogCallCompletedListener logCallCompletedListener) { @Nullable LogCallCompletedListener logCallCompletedListener, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { this.context = context; this.callerInfo = callerInfo; this.number = number; Loading @@ -99,6 +101,9 @@ public final class CallLogManager extends CallsManagerListenerBase { this.initiatingUser = initiatingUser; this.isRead = isRead; this.logCallCompletedListener = logCallCompletedListener; this.callBockReason = callBlockReason; this.callScreeningAppName = callScreeningAppName; this.callScreeningComponentName = callScreeningComponentName; } // Since the members are accessed directly, we don't use the // mXxxx notation. Loading @@ -119,6 +124,10 @@ public final class CallLogManager extends CallsManagerListenerBase { @Nullable public final LogCallCompletedListener logCallCompletedListener; public final int callBockReason; public final String callScreeningAppName; public final String callScreeningComponentName; } private static final String TAG = CallLogManager.class.getSimpleName(); Loading Loading @@ -182,22 +191,23 @@ public final class CallLogManager extends CallsManagerListenerBase { // Always show the notification for managed calls. For self-managed calls, it is up to // the app to show the notification, so suppress the notification when logging the call. boolean showNotification = !call.isSelfManaged(); logCall(call, type, showNotification); logCall(call, type, showNotification, null /*result*/); } } void logCall(Call call, int type, boolean showNotificationForMissedCall) { if (type == Calls.MISSED_TYPE && showNotificationForMissedCall) { logCall(call, Calls.MISSED_TYPE, new LogCallCompletedListener() { void logCall(Call call, int type, boolean showNotificationForMissedCall, CallFilteringResult result) { if ((type == Calls.MISSED_TYPE || type == Calls.BLOCKED_TYPE) && showNotificationForMissedCall) { logCall(call, type, new LogCallCompletedListener() { @Override public void onLogCompleted(@Nullable Uri uri) { mMissedCallNotifier.showMissedCallNotification( new MissedCallNotifier.CallInfo(call)); } }); }, result); } else { logCall(call, type, null); logCall(call, type, null, result); } } Loading @@ -209,10 +219,13 @@ public final class CallLogManager extends CallsManagerListenerBase { * {@link android.provider.CallLog.Calls#INCOMING_TYPE} * {@link android.provider.CallLog.Calls#OUTGOING_TYPE} * {@link android.provider.CallLog.Calls#MISSED_TYPE} * {@link android.provider.CallLog.Calls#BLOCKED_TYPE} * @param logCallCompletedListener optional callback called after the call is logged. * @param result is generated when call type is * {@link android.provider.CallLog.Calls#BLOCKED_TYPE}. */ void logCall(Call call, int callLogType, @Nullable LogCallCompletedListener logCallCompletedListener) { @Nullable LogCallCompletedListener logCallCompletedListener, CallFilteringResult result) { final long creationTime = call.getCreationTimeMillis(); final long age = call.getAgeMillis(); Loading Loading @@ -242,10 +255,22 @@ public final class CallLogManager extends CallsManagerListenerBase { (call.getConnectionProperties() & Connection.PROPERTY_ASSISTED_DIALING_USED) == Connection.PROPERTY_ASSISTED_DIALING_USED, call.wasEverRttCall()); if (callLogType == Calls.BLOCKED_TYPE) { logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber, call.getHandlePresentation(), callLogType, callFeatures, accountHandle, creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener, result.mCallBlockReason, result.mCallScreeningAppName, result.mCallScreeningComponentName); } else { logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber, call.getHandlePresentation(), callLogType, callFeatures, accountHandle, creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener); creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener, Calls.BLOCK_REASON_NOT_BLOCKED, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } } /** Loading @@ -265,6 +290,9 @@ public final class CallLogManager extends CallsManagerListenerBase { * @param logCallCompletedListener optional callback called after the call is logged. * @param initiatingUser The user the call was initiated under. * @param isSelfManaged {@code true} if this is a self-managed call, {@code false} otherwise. * @param callBlockReason The reason why the call is blocked. * @param callScreeningAppName The call screening application name which block the call. * @param callScreeningComponentName The call screening component name which block the call. */ private void logCall( CallerInfo callerInfo, Loading @@ -281,7 +309,10 @@ public final class CallLogManager extends CallsManagerListenerBase { boolean isEmergency, UserHandle initiatingUser, boolean isSelfManaged, @Nullable LogCallCompletedListener logCallCompletedListener) { @Nullable LogCallCompletedListener logCallCompletedListener, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { // On some devices, to avoid accidental redialing of emergency numbers, we *never* log // emergency calls to the Call Log. (This behavior is set on a per-product basis, based Loading Loading @@ -314,7 +345,8 @@ public final class CallLogManager extends CallsManagerListenerBase { } AddCallArgs args = new AddCallArgs(mContext, callerInfo, number, postDialDigits, viaNumber, presentation, callType, features, accountHandle, start, duration, dataUsage, initiatingUser, isRead, logCallCompletedListener); dataUsage, initiatingUser, isRead, logCallCompletedListener, callBlockReason, callScreeningAppName, callScreeningComponentName); logCallAsync(args); } else { Log.d(TAG, "Not adding emergency call to call log."); Loading Loading @@ -475,7 +507,8 @@ public final class CallLogManager extends CallsManagerListenerBase { return Calls.addCall(c.callerInfo, c.context, c.number, c.postDialDigits, c.viaNumber, c.presentation, c.callType, c.features, c.accountHandle, c.timestamp, c.durationInSec, c.dataUsage, userToBeInserted == null, userToBeInserted, c.isRead); userToBeInserted, c.isRead, c.callBockReason, c.callScreeningAppName, c.callScreeningComponentName); } Loading src/com/android/server/telecom/CallsManager.java +8 −7 Original line number Diff line number Diff line Loading @@ -568,7 +568,8 @@ public class CallsManager extends Call.ListenerBase filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(), mCallerInfoLookupHelper, null)); filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar, mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock)); mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock, new TelecomServiceImpl.SettingsSecureAdapterImpl())); new IncomingCallFilter(mContext, this, incomingCall, mLock, mTimeoutsAdapter, filters).performFiltering(); } Loading @@ -594,7 +595,7 @@ public class CallsManager extends Call.ListenerBase } else { Log.i(this, "onCallFilteringCompleted: Call rejected! " + "Exceeds maximum number of ringing calls."); rejectCallAndLog(incomingCall); rejectCallAndLog(incomingCall, result); } } else if (hasMaximumManagedDialingCalls(incomingCall)) { if (shouldSilenceInsteadOfReject(incomingCall)) { Loading @@ -603,7 +604,7 @@ public class CallsManager extends Call.ListenerBase Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " + "dialing calls."); rejectCallAndLog(incomingCall); rejectCallAndLog(incomingCall, result); } } else { addCall(incomingCall); Loading @@ -618,8 +619,8 @@ public class CallsManager extends Call.ListenerBase if (result.shouldShowNotification) { Log.w(this, "onCallScreeningCompleted: blocked call, showing notification."); } mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE, result.shouldShowNotification); mCallLogManager.logCall(incomingCall, Calls.BLOCKED_TYPE, result.shouldShowNotification, result); } else if (result.shouldShowNotification) { Log.i(this, "onCallScreeningCompleted: blocked call, showing notification."); mMissedCallNotifier.showMissedCallNotification( Loading Loading @@ -2441,7 +2442,7 @@ public class CallsManager extends Call.ListenerBase * Reject an incoming call and manually add it to the Call Log. * @param incomingCall Incoming call that has been rejected */ private void rejectCallAndLog(Call incomingCall) { private void rejectCallAndLog(Call incomingCall, CallFilteringResult result) { if (incomingCall.getConnectionService() != null) { // Only reject the call if it has not already been destroyed. If a call ends while // incoming call filtering is taking place, it is possible that the call has already Loading @@ -2456,7 +2457,7 @@ public class CallsManager extends Call.ListenerBase // call notifier and the call logger manually. // Do we need missed call notification for direct to Voicemail calls? mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE, true /*showNotificationForMissedCall*/); true /*showNotificationForMissedCall*/, result); } /** Loading src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java +30 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.BlockedNumberContract; import android.provider.CallLog; import android.telecom.Log; import android.telecom.Logging.Session; import android.telecom.TelecomManager; Loading Loading @@ -123,8 +124,11 @@ public class AsyncBlockCheckFilter extends AsyncTask<String, Void, Boolean> result = new CallFilteringResult( false, // shouldAllowCall true, //shouldReject false, //shouldAddToCallLog false // shouldShowNotification true, //shouldAddToCallLog false, // shouldShowNotification convertBlockStatusToReason(), //callBlockReason null, //callScreeningAppName null //callScreeningComponentName ); if (mCallBlockListener != null) { String number = mIncomingCall.getHandle() == null ? null Loading @@ -148,4 +152,28 @@ public class AsyncBlockCheckFilter extends AsyncTask<String, Void, Boolean> Log.endSession(); } } private int convertBlockStatusToReason() { switch (mBlockStatus) { case BlockedNumberContract.STATUS_BLOCKED_IN_LIST: return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER: return CallLog.Calls.BLOCK_REASON_UNKNOWN_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED: return CallLog.Calls.BLOCK_REASON_RESTRICTED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE: return CallLog.Calls.BLOCK_REASON_PAY_PHONE; case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS: return CallLog.Calls.BLOCK_REASON_NOT_IN_CONTACTS; default: Log.w(AsyncBlockCheckFilter.class.getSimpleName(), "There's no call log block reason can be converted"); return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; } } } src/com/android/server/telecom/callfiltering/CallFilteringResult.java +109 −7 Original line number Diff line number Diff line Loading @@ -16,11 +16,18 @@ package com.android.server.telecom.callfiltering; import android.provider.CallLog; import android.provider.CallLog.Calls; import android.text.TextUtils; public class CallFilteringResult { public boolean shouldAllowCall; public boolean shouldReject; public boolean shouldAddToCallLog; public boolean shouldShowNotification; public int mCallBlockReason = CallLog.Calls.BLOCK_REASON_NOT_BLOCKED; public String mCallScreeningAppName = null; public String mCallScreeningComponentName = null; public CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification) { Loading @@ -30,15 +37,53 @@ public class CallFilteringResult { this.shouldShowNotification = shouldShowNotification; } public CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { this.shouldAllowCall = shouldAllowCall; this.shouldReject = shouldReject; this.shouldAddToCallLog = shouldAddToCallLog; this.shouldShowNotification = shouldShowNotification; this.mCallBlockReason = callBlockReason; this.mCallScreeningAppName = callScreeningAppName; this.mCallScreeningComponentName = callScreeningComponentName; } /** * Combine this CallFilteringResult with another, returning a CallFilteringResult with * the more restrictive properties of the two. * Combine this CallFilteringResult with another, returning a CallFilteringResult with the more * restrictive properties of the two. Where there are multiple call filtering components which * block a call, the first filter from {@link AsyncBlockCheckFilter}, * {@link DirectToVoicemailCallFilter}, {@link CallScreeningServiceFilter} which blocked a call * shall be used to populate the call block reason, component name, etc. */ public CallFilteringResult combine(CallFilteringResult other) { if (other == null) { return this; } if (isBlockedByProvider(mCallBlockReason)) { return getCombinedCallFilteringResult(other, mCallBlockReason, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } else if (isBlockedByProvider(other.mCallBlockReason)) { return getCombinedCallFilteringResult(other, other.mCallBlockReason, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } if (mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL || other.mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL) { return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } if (shouldReject && mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) { return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, mCallScreeningAppName, mCallScreeningComponentName); } else if (other.shouldReject && other.mCallBlockReason == CallLog.Calls .BLOCK_REASON_CALL_SCREENING_SERVICE) { return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, other.mCallScreeningAppName, other.mCallScreeningComponentName); } return new CallFilteringResult( shouldAllowCall && other.shouldAllowCall, shouldReject || other.shouldReject, Loading @@ -46,6 +91,31 @@ public class CallFilteringResult { shouldShowNotification && other.shouldShowNotification); } private boolean isBlockedByProvider(int blockReason) { if (blockReason == Calls.BLOCK_REASON_BLOCKED_NUMBER || blockReason == Calls.BLOCK_REASON_UNKNOWN_NUMBER || blockReason == Calls.BLOCK_REASON_RESTRICTED_NUMBER || blockReason == Calls.BLOCK_REASON_PAY_PHONE || blockReason == Calls.BLOCK_REASON_NOT_IN_CONTACTS) { return true; } return false; } private CallFilteringResult getCombinedCallFilteringResult(CallFilteringResult other, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { return new CallFilteringResult( shouldAllowCall && other.shouldAllowCall, shouldReject || other.shouldReject, shouldAddToCallLog && other.shouldAddToCallLog, shouldShowNotification && other.shouldShowNotification, callBlockReason, callScreeningAppName, callScreeningComponentName); } @Override public boolean equals(Object o) { if (this == o) return true; Loading @@ -56,7 +126,24 @@ public class CallFilteringResult { if (shouldAllowCall != that.shouldAllowCall) return false; if (shouldReject != that.shouldReject) return false; if (shouldAddToCallLog != that.shouldAddToCallLog) return false; return shouldShowNotification == that.shouldShowNotification; if (shouldShowNotification != that.shouldShowNotification) return false; if (mCallBlockReason != that.mCallBlockReason) return false; if ((TextUtils.isEmpty(mCallScreeningAppName) && TextUtils.isEmpty(that.mCallScreeningAppName)) && (TextUtils.isEmpty(mCallScreeningComponentName) && TextUtils.isEmpty(that.mCallScreeningComponentName))) { return true; } else if (!TextUtils.isEmpty(mCallScreeningAppName) && !TextUtils.isEmpty(that.mCallScreeningAppName) && mCallScreeningAppName.equals(that.mCallScreeningAppName) && !TextUtils.isEmpty(mCallScreeningComponentName) && !TextUtils.isEmpty(that.mCallScreeningComponentName) && mCallScreeningComponentName.equals(that.mCallScreeningComponentName)) { return true; } return false; } @Override Loading Loading @@ -87,6 +174,21 @@ public class CallFilteringResult { if (shouldShowNotification) { sb.append(", notified"); } if (mCallBlockReason != 0) { sb.append(", mCallBlockReason = "); sb.append(mCallBlockReason); } if (!TextUtils.isEmpty(mCallScreeningAppName)) { sb.append(", mCallScreeningAppName = "); sb.append(mCallScreeningAppName); } if (!TextUtils.isEmpty(mCallScreeningComponentName)) { sb.append(", mCallScreeningComponentName = "); sb.append(mCallScreeningComponentName); } sb.append("]"); return sb.toString(); Loading src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java +75 −8 Original line number Diff line number Diff line Loading @@ -24,10 +24,15 @@ import android.content.ServiceConnection; import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.IBinder; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.UserHandle; import android.provider.CallLog; import android.provider.Settings; import android.telecom.CallScreeningService; import android.telecom.Log; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.text.TextUtils; import com.android.internal.telecom.ICallScreeningAdapter; Loading @@ -39,6 +44,7 @@ import com.android.server.telecom.LogUtils; import com.android.server.telecom.ParcelableCallUtils; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.TelecomServiceImpl; import com.android.server.telecom.TelecomServiceImpl.SettingsSecureAdapter; import com.android.server.telecom.TelecomSystem; import java.util.List; Loading Loading @@ -108,20 +114,26 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter String callId, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification) { boolean shouldShowNotification, ComponentName componentName) { Log.startSession("CSCR.dC"); long token = Binder.clearCallingIdentity(); try { synchronized (mTelecomLock) { boolean isServiceRequestingLogging = isLoggable(componentName, shouldAddToCallLog); Log.i(this, "disallowCall(%s), shouldReject: %b, shouldAddToCallLog: %b, " + "shouldShowNotification: %b", callId, shouldReject, shouldAddToCallLog, shouldShowNotification); isServiceRequestingLogging, shouldShowNotification); if (mCall != null && mCall.getId().equals(callId)) { mResult = new CallFilteringResult( false, // shouldAllowCall shouldReject, //shouldReject shouldAddToCallLog, //shouldAddToCallLog shouldShowNotification // shouldShowNotification isServiceRequestingLogging, //shouldAddToCallLog shouldShowNotification, // shouldShowNotification CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason componentName.getPackageName(), //callScreeningAppName componentName.flattenToString() //callScreeningComponentName ); } else { Log.w(this, "disallowCall, unknown call id: %s", callId); Loading @@ -141,6 +153,7 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter private final DefaultDialerCache mDefaultDialerCache; private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter; private final TelecomSystem.SyncRoot mTelecomLock; private final SettingsSecureAdapter mSettingsSecureAdapter; private Call mCall; private CallFilterResultCallback mCallback; Loading @@ -161,13 +174,15 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter PhoneAccountRegistrar phoneAccountRegistrar, DefaultDialerCache defaultDialerCache, ParcelableCallUtils.Converter parcelableCallUtilsConverter, TelecomSystem.SyncRoot lock) { TelecomSystem.SyncRoot lock, SettingsSecureAdapter settingsSecureAdapter) { mContext = context; mPhoneAccountRegistrar = phoneAccountRegistrar; mCallsManager = callsManager; mDefaultDialerCache = defaultDialerCache; mParcelableCallUtilsConverter = parcelableCallUtilsConverter; mTelecomLock = lock; mSettingsSecureAdapter = settingsSecureAdapter; } @Override Loading Loading @@ -261,4 +276,56 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter finishCallScreening(); } } private boolean isLoggable(ComponentName componentName, boolean shouldAddToCallLog) { if (isCarrierCallScreeningApp(componentName)) { return shouldAddToCallLog; } else if (isDefaultDialer(componentName) || isUserChosenCallScreeningApp(componentName)) { return true; } return shouldAddToCallLog; } private boolean isCarrierCallScreeningApp(ComponentName componentName) { String carrierCallScreeningApp = null; CarrierConfigManager configManager = (CarrierConfigManager) mContext .getSystemService(Context.CARRIER_CONFIG_SERVICE); PersistableBundle configBundle = configManager.getConfig(); if (configBundle != null) { carrierCallScreeningApp = configBundle .getString(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING); } if (!TextUtils.isEmpty(carrierCallScreeningApp) && carrierCallScreeningApp .equals(componentName.flattenToString())) { return true; } return false; } private boolean isDefaultDialer(ComponentName componentName) { String defaultDialer = TelecomManager.from(mContext).getDefaultDialerPackage(); if (!TextUtils.isEmpty(defaultDialer) && defaultDialer .equals(componentName.getPackageName())) { return true; } return false; } private boolean isUserChosenCallScreeningApp(ComponentName componentName) { String defaultCallScreeningApplication = mSettingsSecureAdapter .getStringForUser(mContext.getContentResolver(), Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, UserHandle.USER_CURRENT); if (!TextUtils.isEmpty(defaultCallScreeningApplication) && defaultCallScreeningApplication .equals(componentName.flattenToString())) { return true; } return false; } } Loading
src/com/android/server/telecom/CallLogManager.java +54 −21 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import android.telephony.PhoneNumberUtils; // TODO: Needed for move to system service: import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallerInfo; import com.android.server.telecom.callfiltering.CallFilteringResult; import java.util.Arrays; import java.util.HashSet; Loading Loading @@ -83,7 +84,8 @@ public final class CallLogManager extends CallsManagerListenerBase { String postDialDigits, String viaNumber, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long creationDate, long durationInMillis, Long dataUsage, UserHandle initiatingUser, boolean isRead, @Nullable LogCallCompletedListener logCallCompletedListener) { @Nullable LogCallCompletedListener logCallCompletedListener, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { this.context = context; this.callerInfo = callerInfo; this.number = number; Loading @@ -99,6 +101,9 @@ public final class CallLogManager extends CallsManagerListenerBase { this.initiatingUser = initiatingUser; this.isRead = isRead; this.logCallCompletedListener = logCallCompletedListener; this.callBockReason = callBlockReason; this.callScreeningAppName = callScreeningAppName; this.callScreeningComponentName = callScreeningComponentName; } // Since the members are accessed directly, we don't use the // mXxxx notation. Loading @@ -119,6 +124,10 @@ public final class CallLogManager extends CallsManagerListenerBase { @Nullable public final LogCallCompletedListener logCallCompletedListener; public final int callBockReason; public final String callScreeningAppName; public final String callScreeningComponentName; } private static final String TAG = CallLogManager.class.getSimpleName(); Loading Loading @@ -182,22 +191,23 @@ public final class CallLogManager extends CallsManagerListenerBase { // Always show the notification for managed calls. For self-managed calls, it is up to // the app to show the notification, so suppress the notification when logging the call. boolean showNotification = !call.isSelfManaged(); logCall(call, type, showNotification); logCall(call, type, showNotification, null /*result*/); } } void logCall(Call call, int type, boolean showNotificationForMissedCall) { if (type == Calls.MISSED_TYPE && showNotificationForMissedCall) { logCall(call, Calls.MISSED_TYPE, new LogCallCompletedListener() { void logCall(Call call, int type, boolean showNotificationForMissedCall, CallFilteringResult result) { if ((type == Calls.MISSED_TYPE || type == Calls.BLOCKED_TYPE) && showNotificationForMissedCall) { logCall(call, type, new LogCallCompletedListener() { @Override public void onLogCompleted(@Nullable Uri uri) { mMissedCallNotifier.showMissedCallNotification( new MissedCallNotifier.CallInfo(call)); } }); }, result); } else { logCall(call, type, null); logCall(call, type, null, result); } } Loading @@ -209,10 +219,13 @@ public final class CallLogManager extends CallsManagerListenerBase { * {@link android.provider.CallLog.Calls#INCOMING_TYPE} * {@link android.provider.CallLog.Calls#OUTGOING_TYPE} * {@link android.provider.CallLog.Calls#MISSED_TYPE} * {@link android.provider.CallLog.Calls#BLOCKED_TYPE} * @param logCallCompletedListener optional callback called after the call is logged. * @param result is generated when call type is * {@link android.provider.CallLog.Calls#BLOCKED_TYPE}. */ void logCall(Call call, int callLogType, @Nullable LogCallCompletedListener logCallCompletedListener) { @Nullable LogCallCompletedListener logCallCompletedListener, CallFilteringResult result) { final long creationTime = call.getCreationTimeMillis(); final long age = call.getAgeMillis(); Loading Loading @@ -242,10 +255,22 @@ public final class CallLogManager extends CallsManagerListenerBase { (call.getConnectionProperties() & Connection.PROPERTY_ASSISTED_DIALING_USED) == Connection.PROPERTY_ASSISTED_DIALING_USED, call.wasEverRttCall()); if (callLogType == Calls.BLOCKED_TYPE) { logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber, call.getHandlePresentation(), callLogType, callFeatures, accountHandle, creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener, result.mCallBlockReason, result.mCallScreeningAppName, result.mCallScreeningComponentName); } else { logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber, call.getHandlePresentation(), callLogType, callFeatures, accountHandle, creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener); creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(), call.isSelfManaged(), logCallCompletedListener, Calls.BLOCK_REASON_NOT_BLOCKED, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } } /** Loading @@ -265,6 +290,9 @@ public final class CallLogManager extends CallsManagerListenerBase { * @param logCallCompletedListener optional callback called after the call is logged. * @param initiatingUser The user the call was initiated under. * @param isSelfManaged {@code true} if this is a self-managed call, {@code false} otherwise. * @param callBlockReason The reason why the call is blocked. * @param callScreeningAppName The call screening application name which block the call. * @param callScreeningComponentName The call screening component name which block the call. */ private void logCall( CallerInfo callerInfo, Loading @@ -281,7 +309,10 @@ public final class CallLogManager extends CallsManagerListenerBase { boolean isEmergency, UserHandle initiatingUser, boolean isSelfManaged, @Nullable LogCallCompletedListener logCallCompletedListener) { @Nullable LogCallCompletedListener logCallCompletedListener, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { // On some devices, to avoid accidental redialing of emergency numbers, we *never* log // emergency calls to the Call Log. (This behavior is set on a per-product basis, based Loading Loading @@ -314,7 +345,8 @@ public final class CallLogManager extends CallsManagerListenerBase { } AddCallArgs args = new AddCallArgs(mContext, callerInfo, number, postDialDigits, viaNumber, presentation, callType, features, accountHandle, start, duration, dataUsage, initiatingUser, isRead, logCallCompletedListener); dataUsage, initiatingUser, isRead, logCallCompletedListener, callBlockReason, callScreeningAppName, callScreeningComponentName); logCallAsync(args); } else { Log.d(TAG, "Not adding emergency call to call log."); Loading Loading @@ -475,7 +507,8 @@ public final class CallLogManager extends CallsManagerListenerBase { return Calls.addCall(c.callerInfo, c.context, c.number, c.postDialDigits, c.viaNumber, c.presentation, c.callType, c.features, c.accountHandle, c.timestamp, c.durationInSec, c.dataUsage, userToBeInserted == null, userToBeInserted, c.isRead); userToBeInserted, c.isRead, c.callBockReason, c.callScreeningAppName, c.callScreeningComponentName); } Loading
src/com/android/server/telecom/CallsManager.java +8 −7 Original line number Diff line number Diff line Loading @@ -568,7 +568,8 @@ public class CallsManager extends Call.ListenerBase filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(), mCallerInfoLookupHelper, null)); filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar, mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock)); mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock, new TelecomServiceImpl.SettingsSecureAdapterImpl())); new IncomingCallFilter(mContext, this, incomingCall, mLock, mTimeoutsAdapter, filters).performFiltering(); } Loading @@ -594,7 +595,7 @@ public class CallsManager extends Call.ListenerBase } else { Log.i(this, "onCallFilteringCompleted: Call rejected! " + "Exceeds maximum number of ringing calls."); rejectCallAndLog(incomingCall); rejectCallAndLog(incomingCall, result); } } else if (hasMaximumManagedDialingCalls(incomingCall)) { if (shouldSilenceInsteadOfReject(incomingCall)) { Loading @@ -603,7 +604,7 @@ public class CallsManager extends Call.ListenerBase Log.i(this, "onCallFilteringCompleted: Call rejected! Exceeds maximum number of " + "dialing calls."); rejectCallAndLog(incomingCall); rejectCallAndLog(incomingCall, result); } } else { addCall(incomingCall); Loading @@ -618,8 +619,8 @@ public class CallsManager extends Call.ListenerBase if (result.shouldShowNotification) { Log.w(this, "onCallScreeningCompleted: blocked call, showing notification."); } mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE, result.shouldShowNotification); mCallLogManager.logCall(incomingCall, Calls.BLOCKED_TYPE, result.shouldShowNotification, result); } else if (result.shouldShowNotification) { Log.i(this, "onCallScreeningCompleted: blocked call, showing notification."); mMissedCallNotifier.showMissedCallNotification( Loading Loading @@ -2441,7 +2442,7 @@ public class CallsManager extends Call.ListenerBase * Reject an incoming call and manually add it to the Call Log. * @param incomingCall Incoming call that has been rejected */ private void rejectCallAndLog(Call incomingCall) { private void rejectCallAndLog(Call incomingCall, CallFilteringResult result) { if (incomingCall.getConnectionService() != null) { // Only reject the call if it has not already been destroyed. If a call ends while // incoming call filtering is taking place, it is possible that the call has already Loading @@ -2456,7 +2457,7 @@ public class CallsManager extends Call.ListenerBase // call notifier and the call logger manually. // Do we need missed call notification for direct to Voicemail calls? mCallLogManager.logCall(incomingCall, Calls.MISSED_TYPE, true /*showNotificationForMissedCall*/); true /*showNotificationForMissedCall*/, result); } /** Loading
src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java +30 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.BlockedNumberContract; import android.provider.CallLog; import android.telecom.Log; import android.telecom.Logging.Session; import android.telecom.TelecomManager; Loading Loading @@ -123,8 +124,11 @@ public class AsyncBlockCheckFilter extends AsyncTask<String, Void, Boolean> result = new CallFilteringResult( false, // shouldAllowCall true, //shouldReject false, //shouldAddToCallLog false // shouldShowNotification true, //shouldAddToCallLog false, // shouldShowNotification convertBlockStatusToReason(), //callBlockReason null, //callScreeningAppName null //callScreeningComponentName ); if (mCallBlockListener != null) { String number = mIncomingCall.getHandle() == null ? null Loading @@ -148,4 +152,28 @@ public class AsyncBlockCheckFilter extends AsyncTask<String, Void, Boolean> Log.endSession(); } } private int convertBlockStatusToReason() { switch (mBlockStatus) { case BlockedNumberContract.STATUS_BLOCKED_IN_LIST: return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER: return CallLog.Calls.BLOCK_REASON_UNKNOWN_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED: return CallLog.Calls.BLOCK_REASON_RESTRICTED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE: return CallLog.Calls.BLOCK_REASON_PAY_PHONE; case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS: return CallLog.Calls.BLOCK_REASON_NOT_IN_CONTACTS; default: Log.w(AsyncBlockCheckFilter.class.getSimpleName(), "There's no call log block reason can be converted"); return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; } } }
src/com/android/server/telecom/callfiltering/CallFilteringResult.java +109 −7 Original line number Diff line number Diff line Loading @@ -16,11 +16,18 @@ package com.android.server.telecom.callfiltering; import android.provider.CallLog; import android.provider.CallLog.Calls; import android.text.TextUtils; public class CallFilteringResult { public boolean shouldAllowCall; public boolean shouldReject; public boolean shouldAddToCallLog; public boolean shouldShowNotification; public int mCallBlockReason = CallLog.Calls.BLOCK_REASON_NOT_BLOCKED; public String mCallScreeningAppName = null; public String mCallScreeningComponentName = null; public CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification) { Loading @@ -30,15 +37,53 @@ public class CallFilteringResult { this.shouldShowNotification = shouldShowNotification; } public CallFilteringResult(boolean shouldAllowCall, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { this.shouldAllowCall = shouldAllowCall; this.shouldReject = shouldReject; this.shouldAddToCallLog = shouldAddToCallLog; this.shouldShowNotification = shouldShowNotification; this.mCallBlockReason = callBlockReason; this.mCallScreeningAppName = callScreeningAppName; this.mCallScreeningComponentName = callScreeningComponentName; } /** * Combine this CallFilteringResult with another, returning a CallFilteringResult with * the more restrictive properties of the two. * Combine this CallFilteringResult with another, returning a CallFilteringResult with the more * restrictive properties of the two. Where there are multiple call filtering components which * block a call, the first filter from {@link AsyncBlockCheckFilter}, * {@link DirectToVoicemailCallFilter}, {@link CallScreeningServiceFilter} which blocked a call * shall be used to populate the call block reason, component name, etc. */ public CallFilteringResult combine(CallFilteringResult other) { if (other == null) { return this; } if (isBlockedByProvider(mCallBlockReason)) { return getCombinedCallFilteringResult(other, mCallBlockReason, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } else if (isBlockedByProvider(other.mCallBlockReason)) { return getCombinedCallFilteringResult(other, other.mCallBlockReason, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } if (mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL || other.mCallBlockReason == Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL) { return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL, null /*callScreeningAppName*/, null /*callScreeningComponentName*/); } if (shouldReject && mCallBlockReason == CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) { return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, mCallScreeningAppName, mCallScreeningComponentName); } else if (other.shouldReject && other.mCallBlockReason == CallLog.Calls .BLOCK_REASON_CALL_SCREENING_SERVICE) { return getCombinedCallFilteringResult(other, Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, other.mCallScreeningAppName, other.mCallScreeningComponentName); } return new CallFilteringResult( shouldAllowCall && other.shouldAllowCall, shouldReject || other.shouldReject, Loading @@ -46,6 +91,31 @@ public class CallFilteringResult { shouldShowNotification && other.shouldShowNotification); } private boolean isBlockedByProvider(int blockReason) { if (blockReason == Calls.BLOCK_REASON_BLOCKED_NUMBER || blockReason == Calls.BLOCK_REASON_UNKNOWN_NUMBER || blockReason == Calls.BLOCK_REASON_RESTRICTED_NUMBER || blockReason == Calls.BLOCK_REASON_PAY_PHONE || blockReason == Calls.BLOCK_REASON_NOT_IN_CONTACTS) { return true; } return false; } private CallFilteringResult getCombinedCallFilteringResult(CallFilteringResult other, int callBlockReason, String callScreeningAppName, String callScreeningComponentName) { return new CallFilteringResult( shouldAllowCall && other.shouldAllowCall, shouldReject || other.shouldReject, shouldAddToCallLog && other.shouldAddToCallLog, shouldShowNotification && other.shouldShowNotification, callBlockReason, callScreeningAppName, callScreeningComponentName); } @Override public boolean equals(Object o) { if (this == o) return true; Loading @@ -56,7 +126,24 @@ public class CallFilteringResult { if (shouldAllowCall != that.shouldAllowCall) return false; if (shouldReject != that.shouldReject) return false; if (shouldAddToCallLog != that.shouldAddToCallLog) return false; return shouldShowNotification == that.shouldShowNotification; if (shouldShowNotification != that.shouldShowNotification) return false; if (mCallBlockReason != that.mCallBlockReason) return false; if ((TextUtils.isEmpty(mCallScreeningAppName) && TextUtils.isEmpty(that.mCallScreeningAppName)) && (TextUtils.isEmpty(mCallScreeningComponentName) && TextUtils.isEmpty(that.mCallScreeningComponentName))) { return true; } else if (!TextUtils.isEmpty(mCallScreeningAppName) && !TextUtils.isEmpty(that.mCallScreeningAppName) && mCallScreeningAppName.equals(that.mCallScreeningAppName) && !TextUtils.isEmpty(mCallScreeningComponentName) && !TextUtils.isEmpty(that.mCallScreeningComponentName) && mCallScreeningComponentName.equals(that.mCallScreeningComponentName)) { return true; } return false; } @Override Loading Loading @@ -87,6 +174,21 @@ public class CallFilteringResult { if (shouldShowNotification) { sb.append(", notified"); } if (mCallBlockReason != 0) { sb.append(", mCallBlockReason = "); sb.append(mCallBlockReason); } if (!TextUtils.isEmpty(mCallScreeningAppName)) { sb.append(", mCallScreeningAppName = "); sb.append(mCallScreeningAppName); } if (!TextUtils.isEmpty(mCallScreeningComponentName)) { sb.append(", mCallScreeningComponentName = "); sb.append(mCallScreeningComponentName); } sb.append("]"); return sb.toString(); Loading
src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java +75 −8 Original line number Diff line number Diff line Loading @@ -24,10 +24,15 @@ import android.content.ServiceConnection; import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.IBinder; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.UserHandle; import android.provider.CallLog; import android.provider.Settings; import android.telecom.CallScreeningService; import android.telecom.Log; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.text.TextUtils; import com.android.internal.telecom.ICallScreeningAdapter; Loading @@ -39,6 +44,7 @@ import com.android.server.telecom.LogUtils; import com.android.server.telecom.ParcelableCallUtils; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.TelecomServiceImpl; import com.android.server.telecom.TelecomServiceImpl.SettingsSecureAdapter; import com.android.server.telecom.TelecomSystem; import java.util.List; Loading Loading @@ -108,20 +114,26 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter String callId, boolean shouldReject, boolean shouldAddToCallLog, boolean shouldShowNotification) { boolean shouldShowNotification, ComponentName componentName) { Log.startSession("CSCR.dC"); long token = Binder.clearCallingIdentity(); try { synchronized (mTelecomLock) { boolean isServiceRequestingLogging = isLoggable(componentName, shouldAddToCallLog); Log.i(this, "disallowCall(%s), shouldReject: %b, shouldAddToCallLog: %b, " + "shouldShowNotification: %b", callId, shouldReject, shouldAddToCallLog, shouldShowNotification); isServiceRequestingLogging, shouldShowNotification); if (mCall != null && mCall.getId().equals(callId)) { mResult = new CallFilteringResult( false, // shouldAllowCall shouldReject, //shouldReject shouldAddToCallLog, //shouldAddToCallLog shouldShowNotification // shouldShowNotification isServiceRequestingLogging, //shouldAddToCallLog shouldShowNotification, // shouldShowNotification CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, //callBlockReason componentName.getPackageName(), //callScreeningAppName componentName.flattenToString() //callScreeningComponentName ); } else { Log.w(this, "disallowCall, unknown call id: %s", callId); Loading @@ -141,6 +153,7 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter private final DefaultDialerCache mDefaultDialerCache; private final ParcelableCallUtils.Converter mParcelableCallUtilsConverter; private final TelecomSystem.SyncRoot mTelecomLock; private final SettingsSecureAdapter mSettingsSecureAdapter; private Call mCall; private CallFilterResultCallback mCallback; Loading @@ -161,13 +174,15 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter PhoneAccountRegistrar phoneAccountRegistrar, DefaultDialerCache defaultDialerCache, ParcelableCallUtils.Converter parcelableCallUtilsConverter, TelecomSystem.SyncRoot lock) { TelecomSystem.SyncRoot lock, SettingsSecureAdapter settingsSecureAdapter) { mContext = context; mPhoneAccountRegistrar = phoneAccountRegistrar; mCallsManager = callsManager; mDefaultDialerCache = defaultDialerCache; mParcelableCallUtilsConverter = parcelableCallUtilsConverter; mTelecomLock = lock; mSettingsSecureAdapter = settingsSecureAdapter; } @Override Loading Loading @@ -261,4 +276,56 @@ public class CallScreeningServiceFilter implements IncomingCallFilter.CallFilter finishCallScreening(); } } private boolean isLoggable(ComponentName componentName, boolean shouldAddToCallLog) { if (isCarrierCallScreeningApp(componentName)) { return shouldAddToCallLog; } else if (isDefaultDialer(componentName) || isUserChosenCallScreeningApp(componentName)) { return true; } return shouldAddToCallLog; } private boolean isCarrierCallScreeningApp(ComponentName componentName) { String carrierCallScreeningApp = null; CarrierConfigManager configManager = (CarrierConfigManager) mContext .getSystemService(Context.CARRIER_CONFIG_SERVICE); PersistableBundle configBundle = configManager.getConfig(); if (configBundle != null) { carrierCallScreeningApp = configBundle .getString(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING); } if (!TextUtils.isEmpty(carrierCallScreeningApp) && carrierCallScreeningApp .equals(componentName.flattenToString())) { return true; } return false; } private boolean isDefaultDialer(ComponentName componentName) { String defaultDialer = TelecomManager.from(mContext).getDefaultDialerPackage(); if (!TextUtils.isEmpty(defaultDialer) && defaultDialer .equals(componentName.getPackageName())) { return true; } return false; } private boolean isUserChosenCallScreeningApp(ComponentName componentName) { String defaultCallScreeningApplication = mSettingsSecureAdapter .getStringForUser(mContext.getContentResolver(), Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT, UserHandle.USER_CURRENT); if (!TextUtils.isEmpty(defaultCallScreeningApplication) && defaultCallScreeningApplication .equals(componentName.flattenToString())) { return true; } return false; } }