Loading src/com/android/server/telecom/CallsManager.java +72 −14 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; Loading @@ -34,6 +35,7 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.PersistableBundle; import android.os.Process; Loading Loading @@ -75,14 +77,15 @@ import com.android.internal.telephony.TelephonyProperties; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter; import com.android.server.telecom.callfiltering.BlockCheckerAdapter; import com.android.server.telecom.callfiltering.BlockCheckerFilter; import com.android.server.telecom.callfiltering.CallFilterResultCallback; import com.android.server.telecom.callfiltering.CallFilteringResult; import com.android.server.telecom.callfiltering.CallFilteringResult.Builder; import com.android.server.telecom.callfiltering.CallScreeningServiceController; import com.android.server.telecom.callfiltering.DirectToVoicemailCallFilter; import com.android.server.telecom.callfiltering.DirectToVoicemailFilter; import com.android.server.telecom.callfiltering.IncomingCallFilter; import com.android.server.telecom.callfiltering.IncomingCallFilterGraph; import com.android.server.telecom.callfiltering.NewCallScreeningServiceFilter; import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.components.ErrorDialogActivity; import com.android.server.telecom.settings.BlockedNumbersUtil; Loading @@ -92,13 +95,13 @@ import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity; import com.android.server.telecom.ui.ConfirmCallDialogActivity; import com.android.server.telecom.ui.IncomingCallNotifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -358,6 +361,8 @@ public class CallsManager extends Call.ListenerBase private Runnable mStopTone; private LinkedList<HandlerThread> mGraphHandlerThreads; /** * Listener to PhoneAccountRegistrar events. */ Loading Loading @@ -548,6 +553,7 @@ public class CallsManager extends Call.ListenerBase CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); intentFilter.addAction(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED); context.registerReceiver(mReceiver, intentFilter); mGraphHandlerThreads = new LinkedList<>(); } public void setIncomingCallNotifier(IncomingCallNotifier incomingCallNotifier) { Loading Loading @@ -631,14 +637,16 @@ public class CallsManager extends Call.ListenerBase return; } IncomingCallFilterGraph graph = setUpCallFilterGraph(incomingCall); graph.performFiltering(); } private IncomingCallFilterGraph setUpCallFilterGraph(Call incomingCall) { incomingCall.setIsUsingCallFiltering(true); List<IncomingCallFilter.CallFilter> filters = new ArrayList<>(); filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper)); filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(), mCallerInfoLookupHelper, null)); filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar, new ParcelableCallUtils.Converter(), mLock, new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper, String carrierPackageName = getCarrierPackageName(); String defaultDialerPackageName = TelecomManager.from(mContext).getDefaultDialerPackage(); String userChosenPackageName = getRoleManagerAdapter().getDefaultCallScreeningApp(); CallScreeningServiceHelper.AppLabelProxy appLabelProxy = new CallScreeningServiceHelper.AppLabelProxy() { @Override public CharSequence getAppLabel(String packageName) { Loading @@ -652,9 +660,53 @@ public class CallsManager extends Call.ListenerBase return null; } })); mIncomingCallFilterFactory.create(mContext, this, incomingCall, mLock, mTimeoutsAdapter, filters).performFiltering(); }; ParcelableCallUtils.Converter converter = new ParcelableCallUtils.Converter(); IncomingCallFilterGraph graph = new IncomingCallFilterGraph(incomingCall, this::onCallFilteringComplete, mContext, mTimeoutsAdapter, mLock); DirectToVoicemailFilter voicemailFilter = new DirectToVoicemailFilter(incomingCall, mCallerInfoLookupHelper); BlockCheckerFilter blockCheckerFilter = new BlockCheckerFilter(mContext, incomingCall, mCallerInfoLookupHelper, new BlockCheckerAdapter()); NewCallScreeningServiceFilter carrierCallScreeningServiceFilter = new NewCallScreeningServiceFilter(incomingCall, carrierPackageName, NewCallScreeningServiceFilter.PACKAGE_TYPE_CARRIER, mContext, this, appLabelProxy, converter); NewCallScreeningServiceFilter defaultDialerCallScreeningServiceFilter = new NewCallScreeningServiceFilter(incomingCall, defaultDialerPackageName, NewCallScreeningServiceFilter.PACKAGE_TYPE_DEFAULT_DIALER, mContext, this, appLabelProxy, converter); NewCallScreeningServiceFilter userChosenCallScreeningServiceFilter = new NewCallScreeningServiceFilter(incomingCall, userChosenPackageName, NewCallScreeningServiceFilter.PACKAGE_TYPE_USER_CHOSEN, mContext, this, appLabelProxy, converter); graph.addFilter(voicemailFilter); graph.addFilter(blockCheckerFilter); graph.addFilter(carrierCallScreeningServiceFilter); graph.addFilter(defaultDialerCallScreeningServiceFilter); graph.addFilter(userChosenCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(voicemailFilter, carrierCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(blockCheckerFilter, carrierCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(carrierCallScreeningServiceFilter, defaultDialerCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(carrierCallScreeningServiceFilter, userChosenCallScreeningServiceFilter); mGraphHandlerThreads.add(graph.getHandlerThread()); return graph; } private String getCarrierPackageName() { ComponentName componentName = null; CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService (Context.CARRIER_CONFIG_SERVICE); PersistableBundle configBundle = configManager.getConfig(); if (configBundle != null) { componentName = ComponentName.unflattenFromString(configBundle.getString (CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, "")); } return componentName != null ? componentName.getPackageName() : null; } @Override Loading @@ -662,6 +714,8 @@ public class CallsManager extends Call.ListenerBase // Only set the incoming call as ringing if it isn't already disconnected. It is possible // that the connection service disconnected the call before it was even added to Telecom, in // which case it makes no sense to set it back to a ringing state. mGraphHandlerThreads.clear(); if (incomingCall.getState() != CallState.DISCONNECTED && incomingCall.getState() != CallState.DISCONNECTING) { setCallState(incomingCall, CallState.RINGING, Loading Loading @@ -4778,4 +4832,8 @@ public class CallsManager extends Call.ListenerBase .filter(c -> phoneAccount.getAccountHandle().equals(c.getTargetPhoneAccount())) .forEach(c -> c.setVideoCallingSupportedByPhoneAccount(isVideoNowSupported)); } public LinkedList<HandlerThread> getGraphHandlerThreads() { return mGraphHandlerThreads; } } src/com/android/server/telecom/callfiltering/CallFilteringResult.java +1 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,7 @@ public class CallFilteringResult { .setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog) .setShouldShowNotification(shouldShowNotification && other.shouldShowNotification) .setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio) .setContactExists(contactExists || other.contactExists) .build(); } Loading src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java +10 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.telecom.Logging.Runnable; import com.android.server.telecom.Call; import com.android.server.telecom.LoggedHandlerExecutor; import com.android.server.telecom.LogUtils; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.Timeouts; Loading Loading @@ -62,6 +63,7 @@ public class IncomingCallFilterGraph { } public CallFilteringResult whenDone(CallFilteringResult result) { Log.i(TAG, "Filter %s done, result: %s.", mFilter, result); mFilter.result = result; for (CallFilter filter : mFilter.getFollowings()) { if (filter.decrementAndGetIndegree() == 0) { Loading @@ -72,6 +74,7 @@ public class IncomingCallFilterGraph { synchronized (mLock) { mFinished = true; mListener.onCallFilteringComplete(mCall, result); Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, result); } mHandlerThread.quit(); } Loading Loading @@ -100,7 +103,7 @@ public class IncomingCallFilterGraph { } public void performFiltering() { Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED); CallFilter dummyStart = new CallFilter(); mDummyComplete = new CallFilter(); Loading @@ -118,6 +121,7 @@ public class IncomingCallFilterGraph { public void loggedRun() { if (!mFinished) { Log.i(this, "Graph timed out when performing filtering."); Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT); mListener.onCallFilteringComplete(mCall, mCurrentResult); mFinished = true; mHandlerThread.quit(); Loading Loading @@ -148,10 +152,15 @@ public class IncomingCallFilterGraph { new LoggedHandlerExecutor(mHandler, "ICFG.sF", null)) .thenApplyAsync(postFilterTask::whenDone, new LoggedHandlerExecutor(mHandler, "ICFG.sF", null)); Log.i(TAG, "Filter %s scheduled.", filter); } public static void addEdge(CallFilter before, CallFilter after) { before.addFollowings(after); after.addDependency(before); } public HandlerThread getHandlerThread() { return mHandlerThread; } } src/com/android/server/telecom/callfiltering/NewCallScreeningServiceFilter.java +19 −17 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.telecom.callfiltering; import static com.android.server.telecom.callfiltering.IncomingCallFilterGraph.DEFAULT_RESULT; import android.Manifest; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -70,7 +68,7 @@ public class NewCallScreeningServiceFilter extends CallFilter { if (mCall == null || (!mCall.getId().equals(callId))) { Log.w(this, "allowCall, unknown call id: %s", callId); } mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } Loading @@ -91,10 +89,11 @@ public class NewCallScreeningServiceFilter extends CallFilter { .setCallBlockReason(CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) .setCallScreeningAppName(mAppName) .setCallScreeningComponentName(componentName.flattenToString()) .setContactExists(mPriorStageResult.contactExists) .build()); } else { Log.w(this, "disallowCall, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); Loading @@ -110,10 +109,11 @@ public class NewCallScreeningServiceFilter extends CallFilter { .setShouldSilence(true) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .setContactExists(mPriorStageResult.contactExists) .build()); } else { Log.w(this, "silenceCall, unknown call id: %s" , callId); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); Loading @@ -134,10 +134,11 @@ public class NewCallScreeningServiceFilter extends CallFilter { .setShouldReject(false) .setShouldSilence(false) .setShouldScreenViaAudio(true) .setContactExists(mPriorStageResult.contactExists) .build()); } else { Log.w(this, "screenCallFurther, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); Loading @@ -162,26 +163,26 @@ public class NewCallScreeningServiceFilter extends CallFilter { toParcelableCallForScreening(mCall, isSystemDialer())); } catch (RemoteException e) { Log.e(this, e, "Failed to set the call screening adapter"); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Log.i(this, "Binding completed."); } @Override public void onServiceDisconnected(ComponentName componentName) { mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Log.i(this, "Service disconnected."); } @Override public void onBindingDied(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Log.i(this, "Binding died."); } @Override public void onNullBinding(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Log.i(this, "Null binding."); } } Loading @@ -206,20 +207,22 @@ public class NewCallScreeningServiceFilter extends CallFilter { } @Override public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult priorStageResult) { public CompletionStage<CallFilteringResult> startFilterLookup( CallFilteringResult priorStageResult) { mPriorStageResult = priorStageResult; if (mPackageName == null) { return CompletableFuture.completedFuture(DEFAULT_RESULT); return CompletableFuture.completedFuture(priorStageResult); } if (!priorStageResult.shouldAllowCall) { // Call already blocked by other filters, no need to bind to call screening service. return CompletableFuture.completedFuture(DEFAULT_RESULT); return CompletableFuture.completedFuture(priorStageResult); } if (priorStageResult.contactExists && (!hasReadContactsPermission())) { // Binding to the call screening service will be skipped if it does NOT hold // READ_CONTACTS permission and the number is in the user’s contacts return CompletableFuture.completedFuture(DEFAULT_RESULT); return CompletableFuture.completedFuture(priorStageResult); } CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); Loading @@ -245,7 +248,7 @@ public class NewCallScreeningServiceFilter extends CallFilter { if (!CallScreeningServiceHelper.bindCallScreeningService(mContext, mCallsManager.getCurrentUserHandle(), mPackageName, mConnection)) { Log.i(this, "Call screening service binding failed."); resultFuture.complete(DEFAULT_RESULT); resultFuture.complete(mPriorStageResult); } } Loading @@ -265,7 +268,6 @@ public class NewCallScreeningServiceFilter extends CallFilter { } private boolean packageTypeShouldAdd(int packageType) { return packageType == PACKAGE_TYPE_CARRIER; return packageType != PACKAGE_TYPE_CARRIER; } } tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +7 −4 Original line number Diff line number Diff line Loading @@ -21,14 +21,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; Loading Loading @@ -78,14 +76,12 @@ import com.android.server.telecom.CallsManagerListenerBase; import com.android.server.telecom.ClockProxy; import com.android.server.telecom.ConnectionServiceFocusManager; import com.android.server.telecom.ContactsAsyncHelper; import com.android.server.telecom.DefaultDialerCache; import com.android.server.telecom.HeadsetMediaButton; import com.android.server.telecom.HeadsetMediaButtonFactory; import com.android.server.telecom.InCallWakeLockController; import com.android.server.telecom.InCallWakeLockControllerFactory; import com.android.server.telecom.MissedCallNotifier; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.PhoneNumberUtilsAdapter; import com.android.server.telecom.PhoneNumberUtilsAdapterImpl; import com.android.server.telecom.ProximitySensorManager; import com.android.server.telecom.ProximitySensorManagerFactory; Loading @@ -111,6 +107,7 @@ import org.mockito.stubbing.Answer; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -377,6 +374,12 @@ public class TelecomSystemTest extends TelecomTestCase { @Override public void tearDown() throws Exception { mTelecomSystem.getCallsManager().waitOnHandlers(); LinkedList<HandlerThread> handlerThreads = mTelecomSystem.getCallsManager() .getGraphHandlerThreads(); for (HandlerThread handlerThread : handlerThreads) { handlerThread.quitSafely(); } handlerThreads.clear(); waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); waitForHandlerAction(mHandlerThread.getThreadHandler(), TEST_TIMEOUT); // Bring down the threads that are active. Loading Loading
src/com/android/server/telecom/CallsManager.java +72 −14 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.app.ActivityManager; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; Loading @@ -34,6 +35,7 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.PersistableBundle; import android.os.Process; Loading Loading @@ -75,14 +77,15 @@ import com.android.internal.telephony.TelephonyProperties; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.bluetooth.BluetoothRouteManager; import com.android.server.telecom.bluetooth.BluetoothStateReceiver; import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter; import com.android.server.telecom.callfiltering.BlockCheckerAdapter; import com.android.server.telecom.callfiltering.BlockCheckerFilter; import com.android.server.telecom.callfiltering.CallFilterResultCallback; import com.android.server.telecom.callfiltering.CallFilteringResult; import com.android.server.telecom.callfiltering.CallFilteringResult.Builder; import com.android.server.telecom.callfiltering.CallScreeningServiceController; import com.android.server.telecom.callfiltering.DirectToVoicemailCallFilter; import com.android.server.telecom.callfiltering.DirectToVoicemailFilter; import com.android.server.telecom.callfiltering.IncomingCallFilter; import com.android.server.telecom.callfiltering.IncomingCallFilterGraph; import com.android.server.telecom.callfiltering.NewCallScreeningServiceFilter; import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.components.ErrorDialogActivity; import com.android.server.telecom.settings.BlockedNumbersUtil; Loading @@ -92,13 +95,13 @@ import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity; import com.android.server.telecom.ui.ConfirmCallDialogActivity; import com.android.server.telecom.ui.IncomingCallNotifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -358,6 +361,8 @@ public class CallsManager extends Call.ListenerBase private Runnable mStopTone; private LinkedList<HandlerThread> mGraphHandlerThreads; /** * Listener to PhoneAccountRegistrar events. */ Loading Loading @@ -548,6 +553,7 @@ public class CallsManager extends Call.ListenerBase CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); intentFilter.addAction(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED); context.registerReceiver(mReceiver, intentFilter); mGraphHandlerThreads = new LinkedList<>(); } public void setIncomingCallNotifier(IncomingCallNotifier incomingCallNotifier) { Loading Loading @@ -631,14 +637,16 @@ public class CallsManager extends Call.ListenerBase return; } IncomingCallFilterGraph graph = setUpCallFilterGraph(incomingCall); graph.performFiltering(); } private IncomingCallFilterGraph setUpCallFilterGraph(Call incomingCall) { incomingCall.setIsUsingCallFiltering(true); List<IncomingCallFilter.CallFilter> filters = new ArrayList<>(); filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper)); filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(), mCallerInfoLookupHelper, null)); filters.add(new CallScreeningServiceController(mContext, this, mPhoneAccountRegistrar, new ParcelableCallUtils.Converter(), mLock, new TelecomServiceImpl.SettingsSecureAdapterImpl(), mCallerInfoLookupHelper, String carrierPackageName = getCarrierPackageName(); String defaultDialerPackageName = TelecomManager.from(mContext).getDefaultDialerPackage(); String userChosenPackageName = getRoleManagerAdapter().getDefaultCallScreeningApp(); CallScreeningServiceHelper.AppLabelProxy appLabelProxy = new CallScreeningServiceHelper.AppLabelProxy() { @Override public CharSequence getAppLabel(String packageName) { Loading @@ -652,9 +660,53 @@ public class CallsManager extends Call.ListenerBase return null; } })); mIncomingCallFilterFactory.create(mContext, this, incomingCall, mLock, mTimeoutsAdapter, filters).performFiltering(); }; ParcelableCallUtils.Converter converter = new ParcelableCallUtils.Converter(); IncomingCallFilterGraph graph = new IncomingCallFilterGraph(incomingCall, this::onCallFilteringComplete, mContext, mTimeoutsAdapter, mLock); DirectToVoicemailFilter voicemailFilter = new DirectToVoicemailFilter(incomingCall, mCallerInfoLookupHelper); BlockCheckerFilter blockCheckerFilter = new BlockCheckerFilter(mContext, incomingCall, mCallerInfoLookupHelper, new BlockCheckerAdapter()); NewCallScreeningServiceFilter carrierCallScreeningServiceFilter = new NewCallScreeningServiceFilter(incomingCall, carrierPackageName, NewCallScreeningServiceFilter.PACKAGE_TYPE_CARRIER, mContext, this, appLabelProxy, converter); NewCallScreeningServiceFilter defaultDialerCallScreeningServiceFilter = new NewCallScreeningServiceFilter(incomingCall, defaultDialerPackageName, NewCallScreeningServiceFilter.PACKAGE_TYPE_DEFAULT_DIALER, mContext, this, appLabelProxy, converter); NewCallScreeningServiceFilter userChosenCallScreeningServiceFilter = new NewCallScreeningServiceFilter(incomingCall, userChosenPackageName, NewCallScreeningServiceFilter.PACKAGE_TYPE_USER_CHOSEN, mContext, this, appLabelProxy, converter); graph.addFilter(voicemailFilter); graph.addFilter(blockCheckerFilter); graph.addFilter(carrierCallScreeningServiceFilter); graph.addFilter(defaultDialerCallScreeningServiceFilter); graph.addFilter(userChosenCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(voicemailFilter, carrierCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(blockCheckerFilter, carrierCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(carrierCallScreeningServiceFilter, defaultDialerCallScreeningServiceFilter); IncomingCallFilterGraph.addEdge(carrierCallScreeningServiceFilter, userChosenCallScreeningServiceFilter); mGraphHandlerThreads.add(graph.getHandlerThread()); return graph; } private String getCarrierPackageName() { ComponentName componentName = null; CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService (Context.CARRIER_CONFIG_SERVICE); PersistableBundle configBundle = configManager.getConfig(); if (configBundle != null) { componentName = ComponentName.unflattenFromString(configBundle.getString (CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, "")); } return componentName != null ? componentName.getPackageName() : null; } @Override Loading @@ -662,6 +714,8 @@ public class CallsManager extends Call.ListenerBase // Only set the incoming call as ringing if it isn't already disconnected. It is possible // that the connection service disconnected the call before it was even added to Telecom, in // which case it makes no sense to set it back to a ringing state. mGraphHandlerThreads.clear(); if (incomingCall.getState() != CallState.DISCONNECTED && incomingCall.getState() != CallState.DISCONNECTING) { setCallState(incomingCall, CallState.RINGING, Loading Loading @@ -4778,4 +4832,8 @@ public class CallsManager extends Call.ListenerBase .filter(c -> phoneAccount.getAccountHandle().equals(c.getTargetPhoneAccount())) .forEach(c -> c.setVideoCallingSupportedByPhoneAccount(isVideoNowSupported)); } public LinkedList<HandlerThread> getGraphHandlerThreads() { return mGraphHandlerThreads; } }
src/com/android/server/telecom/callfiltering/CallFilteringResult.java +1 −0 Original line number Diff line number Diff line Loading @@ -182,6 +182,7 @@ public class CallFilteringResult { .setShouldAddToCallLog(shouldAddToCallLog && other.shouldAddToCallLog) .setShouldShowNotification(shouldShowNotification && other.shouldShowNotification) .setShouldScreenViaAudio(shouldScreenViaAudio || other.shouldScreenViaAudio) .setContactExists(contactExists || other.contactExists) .build(); } Loading
src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java +10 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.telecom.Logging.Runnable; import com.android.server.telecom.Call; import com.android.server.telecom.LoggedHandlerExecutor; import com.android.server.telecom.LogUtils; import com.android.server.telecom.TelecomSystem; import com.android.server.telecom.Timeouts; Loading Loading @@ -62,6 +63,7 @@ public class IncomingCallFilterGraph { } public CallFilteringResult whenDone(CallFilteringResult result) { Log.i(TAG, "Filter %s done, result: %s.", mFilter, result); mFilter.result = result; for (CallFilter filter : mFilter.getFollowings()) { if (filter.decrementAndGetIndegree() == 0) { Loading @@ -72,6 +74,7 @@ public class IncomingCallFilterGraph { synchronized (mLock) { mFinished = true; mListener.onCallFilteringComplete(mCall, result); Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, result); } mHandlerThread.quit(); } Loading Loading @@ -100,7 +103,7 @@ public class IncomingCallFilterGraph { } public void performFiltering() { Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED); CallFilter dummyStart = new CallFilter(); mDummyComplete = new CallFilter(); Loading @@ -118,6 +121,7 @@ public class IncomingCallFilterGraph { public void loggedRun() { if (!mFinished) { Log.i(this, "Graph timed out when performing filtering."); Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT); mListener.onCallFilteringComplete(mCall, mCurrentResult); mFinished = true; mHandlerThread.quit(); Loading Loading @@ -148,10 +152,15 @@ public class IncomingCallFilterGraph { new LoggedHandlerExecutor(mHandler, "ICFG.sF", null)) .thenApplyAsync(postFilterTask::whenDone, new LoggedHandlerExecutor(mHandler, "ICFG.sF", null)); Log.i(TAG, "Filter %s scheduled.", filter); } public static void addEdge(CallFilter before, CallFilter after) { before.addFollowings(after); after.addDependency(before); } public HandlerThread getHandlerThread() { return mHandlerThread; } }
src/com/android/server/telecom/callfiltering/NewCallScreeningServiceFilter.java +19 −17 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.telecom.callfiltering; import static com.android.server.telecom.callfiltering.IncomingCallFilterGraph.DEFAULT_RESULT; import android.Manifest; import android.content.ComponentName; import android.content.Context; Loading Loading @@ -70,7 +68,7 @@ public class NewCallScreeningServiceFilter extends CallFilter { if (mCall == null || (!mCall.getId().equals(callId))) { Log.w(this, "allowCall, unknown call id: %s", callId); } mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Binder.restoreCallingIdentity(token); unbindCallScreeningService(); } Loading @@ -91,10 +89,11 @@ public class NewCallScreeningServiceFilter extends CallFilter { .setCallBlockReason(CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE) .setCallScreeningAppName(mAppName) .setCallScreeningComponentName(componentName.flattenToString()) .setContactExists(mPriorStageResult.contactExists) .build()); } else { Log.w(this, "disallowCall, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); Loading @@ -110,10 +109,11 @@ public class NewCallScreeningServiceFilter extends CallFilter { .setShouldSilence(true) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .setContactExists(mPriorStageResult.contactExists) .build()); } else { Log.w(this, "silenceCall, unknown call id: %s" , callId); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); Loading @@ -134,10 +134,11 @@ public class NewCallScreeningServiceFilter extends CallFilter { .setShouldReject(false) .setShouldSilence(false) .setShouldScreenViaAudio(true) .setContactExists(mPriorStageResult.contactExists) .build()); } else { Log.w(this, "screenCallFurther, unknown call id: %s", callId); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Binder.restoreCallingIdentity(token); unbindCallScreeningService(); Loading @@ -162,26 +163,26 @@ public class NewCallScreeningServiceFilter extends CallFilter { toParcelableCallForScreening(mCall, isSystemDialer())); } catch (RemoteException e) { Log.e(this, e, "Failed to set the call screening adapter"); mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); } Log.i(this, "Binding completed."); } @Override public void onServiceDisconnected(ComponentName componentName) { mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Log.i(this, "Service disconnected."); } @Override public void onBindingDied(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Log.i(this, "Binding died."); } @Override public void onNullBinding(ComponentName name) { mResultFuture.complete(DEFAULT_RESULT); mResultFuture.complete(mPriorStageResult); Log.i(this, "Null binding."); } } Loading @@ -206,20 +207,22 @@ public class NewCallScreeningServiceFilter extends CallFilter { } @Override public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult priorStageResult) { public CompletionStage<CallFilteringResult> startFilterLookup( CallFilteringResult priorStageResult) { mPriorStageResult = priorStageResult; if (mPackageName == null) { return CompletableFuture.completedFuture(DEFAULT_RESULT); return CompletableFuture.completedFuture(priorStageResult); } if (!priorStageResult.shouldAllowCall) { // Call already blocked by other filters, no need to bind to call screening service. return CompletableFuture.completedFuture(DEFAULT_RESULT); return CompletableFuture.completedFuture(priorStageResult); } if (priorStageResult.contactExists && (!hasReadContactsPermission())) { // Binding to the call screening service will be skipped if it does NOT hold // READ_CONTACTS permission and the number is in the user’s contacts return CompletableFuture.completedFuture(DEFAULT_RESULT); return CompletableFuture.completedFuture(priorStageResult); } CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); Loading @@ -245,7 +248,7 @@ public class NewCallScreeningServiceFilter extends CallFilter { if (!CallScreeningServiceHelper.bindCallScreeningService(mContext, mCallsManager.getCurrentUserHandle(), mPackageName, mConnection)) { Log.i(this, "Call screening service binding failed."); resultFuture.complete(DEFAULT_RESULT); resultFuture.complete(mPriorStageResult); } } Loading @@ -265,7 +268,6 @@ public class NewCallScreeningServiceFilter extends CallFilter { } private boolean packageTypeShouldAdd(int packageType) { return packageType == PACKAGE_TYPE_CARRIER; return packageType != PACKAGE_TYPE_CARRIER; } }
tests/src/com/android/server/telecom/tests/TelecomSystemTest.java +7 −4 Original line number Diff line number Diff line Loading @@ -21,14 +21,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; Loading Loading @@ -78,14 +76,12 @@ import com.android.server.telecom.CallsManagerListenerBase; import com.android.server.telecom.ClockProxy; import com.android.server.telecom.ConnectionServiceFocusManager; import com.android.server.telecom.ContactsAsyncHelper; import com.android.server.telecom.DefaultDialerCache; import com.android.server.telecom.HeadsetMediaButton; import com.android.server.telecom.HeadsetMediaButtonFactory; import com.android.server.telecom.InCallWakeLockController; import com.android.server.telecom.InCallWakeLockControllerFactory; import com.android.server.telecom.MissedCallNotifier; import com.android.server.telecom.PhoneAccountRegistrar; import com.android.server.telecom.PhoneNumberUtilsAdapter; import com.android.server.telecom.PhoneNumberUtilsAdapterImpl; import com.android.server.telecom.ProximitySensorManager; import com.android.server.telecom.ProximitySensorManagerFactory; Loading @@ -111,6 +107,7 @@ import org.mockito.stubbing.Answer; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -377,6 +374,12 @@ public class TelecomSystemTest extends TelecomTestCase { @Override public void tearDown() throws Exception { mTelecomSystem.getCallsManager().waitOnHandlers(); LinkedList<HandlerThread> handlerThreads = mTelecomSystem.getCallsManager() .getGraphHandlerThreads(); for (HandlerThread handlerThread : handlerThreads) { handlerThread.quitSafely(); } handlerThreads.clear(); waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); waitForHandlerAction(mHandlerThread.getThreadHandler(), TEST_TIMEOUT); // Bring down the threads that are active. Loading