Merge "Fix issue that default dialer change is broadcasted unintentionally"
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index 8b7c37d..d6780ed 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -548,17 +548,19 @@
         private String getInCallServicesString() {
             StringBuilder s = new StringBuilder();
             s.append("[\n");
-            for (TelecomLogClass.InCallServiceInfo service : inCallServiceInfos) {
-                s.append("    ");
-                s.append("name: ");
-                s.append(service.getInCallServiceName());
-                s.append(" type: ");
-                s.append(service.getInCallServiceType());
-                s.append(" is crashed: ");
-                s.append(service.getIsNullBinding());
-                s.append(" service last time in ms: ");
-                s.append(service.getBoundDurationMillis());
-                s.append("\n");
+            if (inCallServiceInfos != null) {
+                for (TelecomLogClass.InCallServiceInfo service : inCallServiceInfos) {
+                    s.append("    ");
+                    s.append("name: ");
+                    s.append(service.getInCallServiceName());
+                    s.append(" type: ");
+                    s.append(service.getInCallServiceType());
+                    s.append(" is crashed: ");
+                    s.append(service.getIsNullBinding());
+                    s.append(" service last time in ms: ");
+                    s.append(service.getBoundDurationMillis());
+                    s.append("\n");
+                }
             }
             s.append("]");
             return s.toString();
@@ -631,7 +633,7 @@
     }
 
     public static CallInfo initiateCallAnalytics(String callId, int direction) {
-        Log.d(TAG, "Starting analytics for call " + callId);
+        Log.i(TAG, "Starting analytics for call " + callId);
         CallInfoImpl callInfo = new CallInfoImpl(callId, direction);
         synchronized (sLock) {
             while (sActiveCallIds.size() >= MAX_NUM_CALLS_TO_STORE) {
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index ffcdca9..dc862ab 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -624,6 +624,18 @@
     private long mStartRingTime;
 
     /**
+     * The package name of the call screening service that silence this call. If the call is not
+     * silenced, this field will be null.
+     */
+    private CharSequence mCallScreeningAppName;
+
+    /**
+     * The component name of the call screening service that silence this call. If the call is not
+     * silenced, this field will be null.
+     */
+    private String mCallScreeningComponentName;
+
+    /**
      * Persists the specified parameters and initializes the new instance.
      * @param context The context.
      * @param repository The connection service repository.
@@ -3906,6 +3918,10 @@
         mMissedReason = missedReason;
     }
 
+    public void setUserMissed(long code) {
+        mMissedReason |= code;
+    }
+
     public long getStartRingTime() {
         return mStartRingTime;
     }
@@ -3913,4 +3929,20 @@
     public void setStartRingTime(long startRingTime) {
         mStartRingTime = startRingTime;
     }
+
+    public CharSequence getCallScreeningAppName() {
+        return mCallScreeningAppName;
+    }
+
+    public void setCallScreeningAppName(CharSequence callScreeningAppName) {
+        mCallScreeningAppName = callScreeningAppName;
+    }
+
+    public String getCallScreeningComponentName() {
+        return mCallScreeningComponentName;
+    }
+
+    public void setCallScreeningComponentName(String callScreeningComponentName) {
+        mCallScreeningComponentName = callScreeningComponentName;
+    }
 }
diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java
index 7305ab9..7f864b8 100644
--- a/src/com/android/server/telecom/CallIntentProcessor.java
+++ b/src/com/android/server/telecom/CallIntentProcessor.java
@@ -141,6 +141,23 @@
             clientExtras.putString(TelecomManager.EXTRA_CALL_SUBJECT, callsubject);
         }
 
+        if (intent.hasExtra(android.telecom.TelecomManager.EXTRA_PRIORITY)) {
+            clientExtras.putInt(android.telecom.TelecomManager.EXTRA_PRIORITY, intent.getIntExtra(
+                    android.telecom.TelecomManager.EXTRA_PRIORITY,
+                            android.telecom.TelecomManager.PRIORITY_NORMAL));
+        }
+
+        if (intent.hasExtra(android.telecom.TelecomManager.EXTRA_LOCATION)) {
+            clientExtras.putParcelable(android.telecom.TelecomManager.EXTRA_LOCATION,
+                    intent.getParcelableExtra(android.telecom.TelecomManager.EXTRA_LOCATION));
+        }
+
+        if (intent.hasExtra(android.telecom.TelecomManager.EXTRA_OUTGOING_PICTURE)) {
+            clientExtras.putParcelable(android.telecom.TelecomManager.EXTRA_OUTGOING_PICTURE,
+                    intent.getParcelableExtra(
+                            android.telecom.TelecomManager.EXTRA_OUTGOING_PICTURE));
+        }
+
         final int videoState = intent.getIntExtra( TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
                 VideoProfile.STATE_AUDIO_ONLY);
         clientExtras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index cedd41c..3cec618 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -358,8 +358,10 @@
                 call.wasVolte());
 
         if (result == null) {
-            // Call auto missed before filtered
-            result = new CallFilteringResult.Builder().build();
+            result = new CallFilteringResult.Builder()
+                    .setCallScreeningAppName(call.getCallScreeningAppName())
+                    .setCallScreeningComponentName(call.getCallScreeningComponentName())
+                    .build();
         }
 
         if (callLogType == Calls.BLOCKED_TYPE || callLogType == Calls.MISSED_TYPE) {
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 6b99633..1e963c4 100755
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -31,6 +31,8 @@
 import static android.provider.CallLog.Calls.AUTO_MISSED_EMERGENCY_CALL;
 import static android.provider.CallLog.Calls.AUTO_MISSED_MAXIMUM_DIALING;
 import static android.provider.CallLog.Calls.AUTO_MISSED_MAXIMUM_RINGING;
+import static android.provider.CallLog.Calls.USER_MISSED_CALL_FILTERS_TIMEOUT;
+import static android.provider.CallLog.Calls.USER_MISSED_CALL_SCREENING_SERVICE_SILENCED;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -106,7 +108,6 @@
 import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;
 import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
 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.callredirection.CallRedirectionProcessor;
 import com.android.server.telecom.components.ErrorDialogActivity;
@@ -356,7 +357,6 @@
     private final DisconnectedCallNotifier mDisconnectedCallNotifier;
     private IncomingCallNotifier mIncomingCallNotifier;
     private final CallerInfoLookupHelper mCallerInfoLookupHelper;
-    private final IncomingCallFilter.Factory mIncomingCallFilterFactory;
     private final DefaultDialerCache mDefaultDialerCache;
     private final Timeouts.Adapter mTimeoutsAdapter;
     private final PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
@@ -488,7 +488,6 @@
             CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
             InCallControllerFactory inCallControllerFactory,
             RoleManagerAdapter roleManagerAdapter,
-            IncomingCallFilter.Factory incomingCallFilterFactory,
             ToastFactory toastFactory) {
         mContext = context;
         mLock = lock;
@@ -506,7 +505,6 @@
         mTimeoutsAdapter = timeoutsAdapter;
         mEmergencyCallHelper = emergencyCallHelper;
         mCallerInfoLookupHelper = callerInfoLookupHelper;
-        mIncomingCallFilterFactory = incomingCallFilterFactory;
 
         mDtmfLocalTonePlayer =
                 new DtmfLocalTonePlayer(new DtmfLocalTonePlayer.ToneGeneratorProxy());
@@ -673,7 +671,7 @@
                     .setShouldReject(false)
                     .setShouldAddToCallLog(true)
                     .setShouldShowNotification(true)
-                    .build());
+                    .build(), false);
             incomingCall.setIsUsingCallFiltering(false);
             return;
         }
@@ -739,13 +737,19 @@
     }
 
     @Override
-    public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result) {
+    public void onCallFilteringComplete(Call incomingCall, CallFilteringResult result,
+            boolean timeout) {
         // 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.
         Log.i(this, "onCallFilteringComplete");
         mGraphHandlerThreads.clear();
 
+        if (timeout) {
+            Log.i(this, "onCallFilteringCompleted: Call filters timeout!");
+            incomingCall.setUserMissed(USER_MISSED_CALL_FILTERS_TIMEOUT);
+        }
+
         if (incomingCall.getState() != CallState.DISCONNECTED &&
                 incomingCall.getState() != CallState.DISCONNECTING) {
             setCallState(incomingCall, CallState.RINGING,
@@ -759,6 +763,7 @@
             incomingCall.setPostCallPackageName(
                     getRoleManagerAdapter().getDefaultCallScreeningApp());
 
+            Log.i(this, "onCallFilteringComplete: allow call.");
             if (hasMaximumManagedRingingCalls(incomingCall)) {
                 if (shouldSilenceInsteadOfReject(incomingCall)) {
                     incomingCall.silence();
@@ -767,6 +772,7 @@
                             "Exceeds maximum number of ringing calls.");
                     incomingCall.setMissedReason(AUTO_MISSED_MAXIMUM_RINGING);
                     autoMissCallAndLog(incomingCall, result);
+                    return;
                 }
             } else if (hasMaximumManagedDialingCalls(incomingCall)) {
                 if (shouldSilenceInsteadOfReject(incomingCall)) {
@@ -776,6 +782,7 @@
                             "dialing calls.");
                     incomingCall.setMissedReason(AUTO_MISSED_MAXIMUM_DIALING);
                     autoMissCallAndLog(incomingCall, result);
+                    return;
                 }
             } else if (result.shouldScreenViaAudio) {
                 Log.i(this, "onCallFilteringCompleted: starting background audio processing");
@@ -784,6 +791,9 @@
             } else if (result.shouldSilence) {
                 Log.i(this, "onCallFilteringCompleted: setting the call to silent ringing state");
                 incomingCall.setSilentRingingRequested(true);
+                incomingCall.setUserMissed(USER_MISSED_CALL_SCREENING_SERVICE_SILENCED);
+                incomingCall.setCallScreeningAppName(result.mCallScreeningAppName);
+                incomingCall.setCallScreeningComponentName(result.mCallScreeningComponentName);
                 addCall(incomingCall);
             } else {
                 addCall(incomingCall);
@@ -1353,6 +1363,7 @@
             // call UI during an emergency call. In this case, log the call as missed instead of
             // rejected since the user did not explicitly reject.
             call.setMissedReason(AUTO_MISSED_EMERGENCY_CALL);
+            call.getAnalytics().setMissedReason(call.getMissedReason());
             mCallLogManager.logCall(call, Calls.MISSED_TYPE,
                     true /*showNotificationForMissedCall*/, null /*CallFilteringResult*/);
             if (isConference) {
@@ -3017,9 +3028,10 @@
      *
      * @param disconnectCause The disconnect cause, see {@link android.telecom.DisconnectCause}.
      */
-    void markCallAsDisconnected(Call call, DisconnectCause disconnectCause) {
-      int oldState = call.getState();
-      if (call.getState() == CallState.SIMULATED_RINGING
+    @VisibleForTesting
+    public void markCallAsDisconnected(Call call, DisconnectCause disconnectCause) {
+        int oldState = call.getState();
+        if (call.getState() == CallState.SIMULATED_RINGING
                 && disconnectCause.getCode() == DisconnectCause.REMOTE) {
             // If the remote end hangs up while in SIMULATED_RINGING, the call should
             // be marked as missed.
@@ -3487,7 +3499,7 @@
     @VisibleForTesting
     public void addCall(Call call) {
         Trace.beginSection("addCall");
-        Log.v(this, "addCall(%s)", call);
+        Log.i(this, "addCall(%s)", call);
         call.addListener(this);
         mCalls.add(call);
 
@@ -3599,10 +3611,14 @@
                         (newState == CallState.DISCONNECTED)) {
                     maybeSendPostCallScreenIntent(call);
                 }
-                if (((newState == CallState.ABORTED) || (newState == CallState.DISCONNECTED))
-                        && (call.getDisconnectCause().getCode() != DisconnectCause.MISSED)) {
+                int disconnectCode = call.getDisconnectCause().getCode();
+                if ((newState == CallState.ABORTED || newState == CallState.DISCONNECTED)
+                        && ((disconnectCode != DisconnectCause.MISSED)
+                        && (disconnectCode != DisconnectCause.CANCELED))) {
                     call.setMissedReason(MISSED_REASON_NOT_MISSED);
                 }
+                call.getAnalytics().setMissedReason(call.getMissedReason());
+
                 maybeShowErrorDialogOnDisconnect(call);
 
                 Trace.beginSection("onCallStateChanged");
@@ -4759,7 +4775,6 @@
      * @param call The {@link Call} which could not be added.
      */
     private void notifyCreateConnectionFailed(PhoneAccountHandle phoneAccountHandle, Call call) {
-        call.getAnalytics().setMissedReason(call.getMissedReason());
         if (phoneAccountHandle == null) {
             return;
         }
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 72c372a..8928e76 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -20,7 +20,6 @@
 import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
 import com.android.server.telecom.bluetooth.BluetoothRouteManager;
 import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
-import com.android.server.telecom.callfiltering.IncomingCallFilter;
 import com.android.server.telecom.components.UserCallIntentProcessor;
 import com.android.server.telecom.components.UserCallIntentProcessorFactory;
 import com.android.server.telecom.ui.AudioProcessingNotification;
@@ -202,7 +201,6 @@
             CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
             ClockProxy clockProxy,
             RoleManagerAdapter roleManagerAdapter,
-            IncomingCallFilter.Factory incomingCallFilterFactory,
             ContactsAsyncHelper.Factory contactsAsyncHelperFactory,
             DeviceIdleControllerAdapter deviceIdleControllerAdapter) {
         mContext = context.getApplicationContext();
@@ -306,7 +304,6 @@
                 callAudioModeStateMachineFactory,
                 inCallControllerFactory,
                 roleManagerAdapter,
-                incomingCallFilterFactory,
                 toastFactory);
 
         mIncomingCallNotifier = incomingCallNotifier;
diff --git a/src/com/android/server/telecom/callfiltering/CallFilterResultCallback.java b/src/com/android/server/telecom/callfiltering/CallFilterResultCallback.java
index 052ce57..1043774 100644
--- a/src/com/android/server/telecom/callfiltering/CallFilterResultCallback.java
+++ b/src/com/android/server/telecom/callfiltering/CallFilterResultCallback.java
@@ -18,5 +18,5 @@
 import com.android.server.telecom.Call;
 
 public interface CallFilterResultCallback {
-    void onCallFilteringComplete(Call call, CallFilteringResult result);
+    void onCallFilteringComplete(Call call, CallFilteringResult result, boolean timeout);
 }
diff --git a/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java b/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java
deleted file mode 100644
index 860de1f..0000000
--- a/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.telecom.callfiltering;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.telecom.Log;
-import android.telecom.Logging.Runnable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.telecom.Call;
-import com.android.server.telecom.LogUtils;
-import com.android.server.telecom.TelecomSystem;
-import com.android.server.telecom.Timeouts;
-import com.android.server.telecom.callfiltering.CallFilteringResult.Builder;
-
-import java.util.List;
-
-public class IncomingCallFilter implements CallFilterResultCallback {
-
-    public static class Factory {
-        public IncomingCallFilter create(Context context, CallFilterResultCallback listener,
-                Call call, TelecomSystem.SyncRoot lock, Timeouts.Adapter timeoutsAdapter,
-                List<CallFilter> filters) {
-            return new IncomingCallFilter(context, listener, call, lock, timeoutsAdapter, filters,
-                    new Handler(Looper.getMainLooper()));
-        }
-    }
-
-    public interface CallFilter {
-        void startFilterLookup(Call call, CallFilterResultCallback listener);
-    }
-
-    private final TelecomSystem.SyncRoot mTelecomLock;
-    private final Context mContext;
-    private final Handler mHandler;
-    private final List<CallFilter> mFilters;
-    private final Call mCall;
-    private final CallFilterResultCallback mListener;
-    private final Timeouts.Adapter mTimeoutsAdapter;
-
-    private CallFilteringResult mResult = new Builder()
-            .setShouldAllowCall(true)
-            .setShouldReject(false)
-            .setShouldAddToCallLog(true)
-            .setShouldShowNotification(true)
-            .build();
-
-    private boolean mIsPending = true;
-    private int mNumPendingFilters;
-
-    public IncomingCallFilter(Context context, CallFilterResultCallback listener, Call call,
-            TelecomSystem.SyncRoot lock, Timeouts.Adapter timeoutsAdapter,
-            List<CallFilter> filters, Handler handler) {
-        mContext = context;
-        mListener = listener;
-        mCall = call;
-        mTelecomLock = lock;
-        mFilters = filters;
-        mNumPendingFilters = filters.size();
-        mTimeoutsAdapter = timeoutsAdapter;
-        mHandler = handler;
-    }
-
-    public void performFiltering() {
-        Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
-        for (CallFilter filter : mFilters) {
-            filter.startFilterLookup(mCall, this);
-        }
-        // synchronized to prevent a race on mResult and to enter into Telecom.
-        mHandler.postDelayed(new Runnable("ICF.pFTO", mTelecomLock) { // performFiltering time-out
-            @Override
-            public void loggedRun() {
-                if (mIsPending) {
-                    Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
-                    Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
-                    mListener.onCallFilteringComplete(mCall, mResult);
-                    mIsPending = false;
-                }
-            }
-        }.prepare(), mTimeoutsAdapter.getCallScreeningTimeoutMillis(mContext.getContentResolver()));
-    }
-
-    public void onCallFilteringComplete(Call call, CallFilteringResult result) {
-        synchronized (mTelecomLock) { // synchronizing to prevent race on mResult
-            mNumPendingFilters--;
-            mResult = result.combine(mResult);
-            if (mNumPendingFilters == 0) {
-                // synchronized on mTelecomLock to enter into Telecom.
-                mHandler.post(new Runnable("ICF.oCFC", mTelecomLock) {
-                    @Override
-                    public void loggedRun() {
-                        if (mIsPending) {
-                            Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, mResult);
-                            mListener.onCallFilteringComplete(mCall, mResult);
-                            mIsPending = false;
-                        }
-                    }
-                }.prepare());
-            }
-        }
-    }
-
-    /**
-     * Returns the handler, for testing purposes.
-     */
-    @VisibleForTesting
-    public Handler getHandler() {
-        return mHandler;
-    }
-}
diff --git a/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java b/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java
index 1543270..e3c68c9 100644
--- a/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java
+++ b/src/com/android/server/telecom/callfiltering/IncomingCallFilterGraph.java
@@ -73,7 +73,7 @@
             if (mFilter.equals(mDummyComplete)) {
                 synchronized (mLock) {
                     mFinished = true;
-                    mListener.onCallFilteringComplete(mCall, result);
+                    mListener.onCallFilteringComplete(mCall, result, false);
                     Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, result);
                 }
                 mHandlerThread.quit();
@@ -122,7 +122,7 @@
                 if (!mFinished) {
                     Log.i(this, "Graph timed out when performing filtering.");
                     Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
-                    mListener.onCallFilteringComplete(mCall, mCurrentResult);
+                    mListener.onCallFilteringComplete(mCall, mCurrentResult, true);
                     mFinished = true;
                     mHandlerThread.quit();
                 }
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index 682990f..9ad0da4 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -57,7 +57,6 @@
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.TelecomWakeLock;
 import com.android.server.telecom.Timeouts;
-import com.android.server.telecom.callfiltering.IncomingCallFilter;
 import com.android.server.telecom.ui.IncomingCallNotifier;
 import com.android.server.telecom.ui.MissedCallNotifierImpl;
 import com.android.server.telecom.ui.NotificationChannelManager;
@@ -191,7 +190,6 @@
                             },
                             new RoleManagerAdapterImpl(context,
                                     (RoleManager) context.getSystemService(Context.ROLE_SERVICE)),
-                            new IncomingCallFilter.Factory(),
                             new ContactsAsyncHelper.Factory(),
                             internalServiceRetriever.getDeviceIdleController()));
         }
diff --git a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
index 953c711..dfc3258 100644
--- a/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallLogManagerTest.java
@@ -60,6 +60,7 @@
 
 import androidx.test.filters.FlakyTest;
 
+import com.android.server.telecom.Analytics;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallLogManager;
 import com.android.server.telecom.CallState;
@@ -89,6 +90,7 @@
     private PhoneAccountHandle mOtherUserAccountHandle;
     private PhoneAccountHandle mManagedProfileAccountHandle;
     private PhoneAccountHandle mSelfManagedAccountHandle;
+    private Analytics.CallInfo mCallInfo;
 
     private static final Uri TEL_PHONEHANDLE = Uri.parse("tel:5555551234");
 
@@ -148,6 +150,7 @@
                 TEST_SELF_MGD_PHONE_ACCOUNT_ID,
                 UserHandle.of(CURRENT_USER_ID)
         );
+        mCallInfo = new Analytics.CallInfo();
 
         // Since we can't mock ContentResolver directly, use a ContentProvider
         when(mContext.getContentResolver()).thenReturn(ContentResolver.wrap(mContentProvider));
@@ -1006,6 +1009,7 @@
         when(fakeCall.getParentCall()).thenReturn(null);
         when(fakeCall.hadChildren()).thenReturn(true);
         when(fakeCall.hasProperty(eq(Connection.PROPERTY_REMOTELY_HOSTED))).thenReturn(false);
+        when(fakeCall.getAnalytics()).thenReturn(mCallInfo);
         return fakeCall;
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 3fd5e60..8378e3b 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -96,7 +96,6 @@
 import com.android.server.telecom.bluetooth.BluetoothRouteManager;
 import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
 import com.android.server.telecom.callfiltering.CallFilteringResult;
-import com.android.server.telecom.callfiltering.IncomingCallFilter;
 import com.android.server.telecom.ui.AudioProcessingNotification;
 import com.android.server.telecom.ui.DisconnectedCallNotifier;
 import com.android.server.telecom.ui.ToastFactory;
@@ -111,8 +110,6 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -201,8 +198,6 @@
     @Mock private CallAudioModeStateMachine.Factory mCallAudioModeStateMachineFactory;
     @Mock private BluetoothStateReceiver mBluetoothStateReceiver;
     @Mock private RoleManagerAdapter mRoleManagerAdapter;
-    @Mock private IncomingCallFilter.Factory mIncomingCallFilterFactory;
-    @Mock private IncomingCallFilter mIncomingCallFilter;
     @Mock private ToastFactory mToastFactory;
     @Mock private Toast mToast;
 
@@ -225,8 +220,6 @@
                 anyInt())).thenReturn(mCallAudioRouteStateMachine);
         when(mCallAudioModeStateMachineFactory.create(any(), any()))
                 .thenReturn(mCallAudioModeStateMachine);
-        when(mIncomingCallFilterFactory.create(any(), any(), any(), any(), any(), any()))
-                .thenReturn(mIncomingCallFilter);
         when(mClockProxy.currentTimeMillis()).thenReturn(System.currentTimeMillis());
         when(mClockProxy.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
         when(mConnSvrFocusManagerFactory.create(any())).thenReturn(mConnectionSvrFocusMgr);
@@ -261,7 +254,6 @@
                 mCallAudioModeStateMachineFactory,
                 mInCallControllerFactory,
                 mRoleManagerAdapter,
-                mIncomingCallFilterFactory,
                 mToastFactory);
 
         when(mPhoneAccountRegistrar.getPhoneAccount(
@@ -1338,6 +1330,8 @@
     @Test
     public void testHandleSilenceVsBackgroundScreeningOrdering() throws Exception {
         Call screenedCall = mock(Call.class);
+        Bundle extra = new Bundle();
+        when(screenedCall.getIntentExtras()).thenReturn(extra);
         String appName = "blah";
         CallFilteringResult result = new CallFilteringResult.Builder()
                 .setShouldAllowCall(true)
@@ -1348,7 +1342,7 @@
                 .setShouldShowNotification(true)
                 .setCallScreeningAppName(appName)
                 .build();
-        mCallsManager.onCallFilteringComplete(screenedCall, result);
+        mCallsManager.onCallFilteringComplete(screenedCall, result, false);
 
         verify(mConnectionSvrFocusMgr).requestFocus(eq(screenedCall),
                 nullable(ConnectionServiceFocusManager.RequestFocusCallback.class));
diff --git a/tests/src/com/android/server/telecom/tests/IncomingCallFilterGraphTest.java b/tests/src/com/android/server/telecom/tests/IncomingCallFilterGraphTest.java
index 8c0adfb..9269836 100644
--- a/tests/src/com/android/server/telecom/tests/IncomingCallFilterGraphTest.java
+++ b/tests/src/com/android/server/telecom/tests/IncomingCallFilterGraphTest.java
@@ -112,7 +112,7 @@
     @Test
     public void testEmptyGraph() throws Exception {
         CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>();
-        CallFilterResultCallback listener = (call, result) -> testResult.complete(result);
+        CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result);
 
         IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext,
                 mTimeoutsAdapter, mLock);
@@ -125,7 +125,7 @@
     @Test
     public void testFiltersPerformOrder() throws Exception {
         CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>();
-        CallFilterResultCallback listener = (call, result) -> testResult.complete(result);
+        CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result);
 
         IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext,
                 mTimeoutsAdapter, mLock);
@@ -143,7 +143,7 @@
     @Test
     public void testFiltersPerformInParallel() throws Exception {
         CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>();
-        CallFilterResultCallback listener = (call, result) -> testResult.complete(result);
+        CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result);
 
         IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext,
                 mTimeoutsAdapter, mLock);
@@ -162,7 +162,7 @@
     @Test
     public void testFiltersTimeout() throws Exception {
         CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>();
-        CallFilterResultCallback listener = (call, result) -> testResult.complete(result);
+        CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result);
 
         IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext,
                 mTimeoutsAdapter, mLock);
diff --git a/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java b/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java
deleted file mode 100644
index 8e2d11e..0000000
--- a/tests/src/com/android/server/telecom/tests/IncomingCallFilterTest.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.telecom.tests;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.CallLog.Calls;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.server.telecom.Call;
-import com.android.server.telecom.Timeouts;
-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.IncomingCallFilter;
-import com.android.server.telecom.TelecomSystem;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.Mock;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atMost;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(JUnit4.class)
-public class IncomingCallFilterTest extends TelecomTestCase {
-    @Mock private CallFilterResultCallback mResultCallback;
-    @Mock private Call mCall;
-    private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {};
-
-    @Mock private IncomingCallFilter.CallFilter mFilter1;
-    @Mock private IncomingCallFilter.CallFilter mFilter2;
-    @Mock private IncomingCallFilter.CallFilter mFilter3;
-    @Mock private IncomingCallFilter.CallFilter mFilter4;
-
-    @Mock private Timeouts.Adapter mTimeoutsAdapter;
-
-    private static final Uri TEST_HANDLE = Uri.parse("tel:1235551234");
-    private static final long LONG_TIMEOUT = 1000000;
-    private static final long SHORT_TIMEOUT = 100;
-
-    private static final CallFilteringResult PASS_CALL_RESULT =
-            new Builder()
-                    .setShouldAllowCall(true)
-                    .setShouldReject(false)
-                    .setShouldAddToCallLog(true)
-                    .setShouldShowNotification(true)
-                    .build();
-
-    private static final CallFilteringResult ASYNC_BLOCK_CHECK_BLOCK_RESULT =
-            new Builder()
-                    .setShouldAllowCall(false)
-                    .setShouldReject(true)
-                    .setShouldAddToCallLog(true)
-                    .setShouldShowNotification(false)
-                    .setCallBlockReason(Calls.BLOCK_REASON_BLOCKED_NUMBER)
-                    .setCallScreeningAppName(null)
-                    .setCallScreeningComponentName(null)
-                    .build();
-
-    private static final CallFilteringResult DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT =
-            new Builder()
-                    .setShouldAllowCall(false)
-                    .setShouldReject(true)
-                    .setShouldAddToCallLog(true)
-                    .setShouldShowNotification(true)
-                    .setCallBlockReason(Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL)
-                    .setCallScreeningAppName(null)
-                    .setCallScreeningComponentName(null)
-                    .build();
-
-    private static final CallFilteringResult CALL_SCREENING_SERVICE_BLOCK_RESULT =
-            new Builder()
-                    .setShouldAllowCall(false)
-                    .setShouldReject(true)
-                    .setShouldAddToCallLog(false)
-                    .setShouldShowNotification(true)
-                    .setCallBlockReason(Calls.BLOCK_REASON_CALL_SCREENING_SERVICE)
-                    .setCallScreeningAppName("com.android.thirdparty")
-                    .setCallScreeningComponentName(
-                            "com.android.thirdparty/"
-                                    + "com.android.thirdparty.callscreeningserviceimpl")
-                    .build();
-
-    private static final CallFilteringResult DEFAULT_RESULT = PASS_CALL_RESULT;
-    private Handler mHandler = new Handler(Looper.getMainLooper());
-
-    @Override
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        mContext = mComponentContextFixture.getTestDouble().getApplicationContext();
-        when(mCall.getHandle()).thenReturn(TEST_HANDLE);
-        setTimeoutLength(LONG_TIMEOUT);
-    }
-
-    @Override
-    @After
-    public void tearDown() throws Exception {
-        mHandler.removeCallbacksAndMessages(null);
-        waitForHandlerAction(mHandler, 1000);
-        super.tearDown();
-    }
-
-    @SmallTest
-    @Test
-    public void testAsyncBlockCallResultFilter() {
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1), mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, ASYNC_BLOCK_CHECK_BLOCK_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq
-                (ASYNC_BLOCK_CHECK_BLOCK_RESULT));
-    }
-
-    @SmallTest
-    @Test
-    public void testDirectToVoiceMailCallResultFilter() {
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1), mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq
-                (DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT));
-    }
-
-    @SmallTest
-    @Test
-    public void testCallScreeningServiceBlockCallResultFilter() {
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1), mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq
-                (CALL_SCREENING_SERVICE_BLOCK_RESULT));
-    }
-
-    @SmallTest
-    @Test
-    public void testPassCallResultFilter() {
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1), mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(PASS_CALL_RESULT));
-    }
-
-    @SmallTest
-    @Test
-    public void testMultipleFiltersForAsyncBlockCheckFilter() {
-        List<IncomingCallFilter.CallFilter> filters =
-                new ArrayList<IncomingCallFilter.CallFilter>() {{
-                    add(mFilter1);
-                    add(mFilter2);
-                    add(mFilter3);
-                    add(mFilter4);
-                }};
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, filters, mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-        verify(mFilter2).startFilterLookup(mCall, testFilter);
-        verify(mFilter3).startFilterLookup(mCall, testFilter);
-        verify(mFilter4).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
-        testFilter.onCallFilteringComplete(mCall, ASYNC_BLOCK_CHECK_BLOCK_RESULT);
-        testFilter.onCallFilteringComplete(mCall, DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT);
-        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(new Builder()
-                .setShouldAllowCall(false)
-                .setShouldReject(true)
-                .setShouldAddToCallLog(false)
-                .setShouldShowNotification(false)
-                .setCallBlockReason(Calls.BLOCK_REASON_BLOCKED_NUMBER)
-                .setCallScreeningAppName(null)
-                .setCallScreeningComponentName(null)
-                .build()));
-    }
-
-    @SmallTest
-    @Test
-    public void testMultipleFiltersForDirectToVoicemailCallFilter() {
-        List<IncomingCallFilter.CallFilter> filters =
-                new ArrayList<IncomingCallFilter.CallFilter>() {{
-                    add(mFilter1);
-                    add(mFilter2);
-                    add(mFilter3);
-                }};
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, filters, mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-        verify(mFilter2).startFilterLookup(mCall, testFilter);
-        verify(mFilter3).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
-        testFilter.onCallFilteringComplete(mCall, DIRECT_TO_VOICEMAIL_CALL_BLOCK_RESULT);
-        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(new Builder()
-                .setShouldAllowCall(false)
-                .setShouldReject(true)
-                .setShouldAddToCallLog(false)
-                .setShouldShowNotification(true)
-                .setCallBlockReason(Calls.BLOCK_REASON_DIRECT_TO_VOICEMAIL)
-                .setCallScreeningAppName(null)
-                .setCallScreeningComponentName(null)
-                .build()));
-    }
-
-    @SmallTest
-    @Test
-    public void testMultipleFiltersForCallScreeningServiceFilter() {
-        List<IncomingCallFilter.CallFilter> filters =
-                new ArrayList<IncomingCallFilter.CallFilter>() {{
-                    add(mFilter1);
-                    add(mFilter2);
-                }};
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, filters, mHandler);
-        testFilter.performFiltering();
-        verify(mFilter1).startFilterLookup(mCall, testFilter);
-        verify(mFilter2).startFilterLookup(mCall, testFilter);
-
-        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
-        testFilter.onCallFilteringComplete(mCall, CALL_SCREENING_SERVICE_BLOCK_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        verify(mResultCallback).onCallFilteringComplete(eq(mCall), eq(new Builder()
-                .setShouldAllowCall(false)
-                .setShouldReject(true)
-                .setShouldAddToCallLog(false)
-                .setShouldShowNotification(true)
-                .setCallBlockReason(Calls.BLOCK_REASON_CALL_SCREENING_SERVICE)
-                .setCallScreeningAppName("com.android.thirdparty")
-                .setCallScreeningComponentName(
-                        "com.android.thirdparty/com.android.thirdparty.callscreeningserviceimpl")
-                .build()));
-    }
-
-    @SmallTest
-    @Test
-    public void testFilterTimeout() throws Exception {
-        setTimeoutLength(SHORT_TIMEOUT);
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1), mHandler);
-        testFilter.performFiltering();
-        verify(mResultCallback, timeout((int) SHORT_TIMEOUT * 2)).onCallFilteringComplete(eq(mCall),
-                eq(DEFAULT_RESULT));
-        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        // verify that we don't report back again with the result
-        verify(mResultCallback, atMost(1)).onCallFilteringComplete(any(Call.class),
-                any(CallFilteringResult.class));
-    }
-
-    @SmallTest
-    @Test
-    public void testFilterTimeoutDoesntTrip() throws Exception {
-        setTimeoutLength(SHORT_TIMEOUT);
-        IncomingCallFilter testFilter = new IncomingCallFilter(mContext, mResultCallback, mCall,
-                mLock, mTimeoutsAdapter, Collections.singletonList(mFilter1), mHandler);
-        testFilter.performFiltering();
-        testFilter.onCallFilteringComplete(mCall, PASS_CALL_RESULT);
-        waitForHandlerAction(testFilter.getHandler(), SHORT_TIMEOUT * 2);
-        Thread.sleep(SHORT_TIMEOUT);
-        verify(mResultCallback, atMost(1)).onCallFilteringComplete(any(Call.class),
-                any(CallFilteringResult.class));
-    }
-
-    @SmallTest
-    @Test
-    public void testToString() {
-        assertEquals("[Allow, logged, notified]", PASS_CALL_RESULT.toString());
-        assertEquals("[Reject, notified, mCallBlockReason = 1, mCallScreeningAppName = com" +
-                ".android.thirdparty, mCallScreeningComponentName = com.android.thirdparty/com" +
-                ".android.thirdparty.callscreeningserviceimpl]",
-            CALL_SCREENING_SERVICE_BLOCK_RESULT.toString());
-        assertEquals("[Reject, logged, mCallBlockReason = 3]",
-            ASYNC_BLOCK_CHECK_BLOCK_RESULT.toString());
-    }
-
-    private void setTimeoutLength(long length) throws Exception {
-        when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class)))
-                .thenReturn(length);
-    }
-}
diff --git a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
index d2c832a..a8e1c5f 100644
--- a/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
+++ b/tests/src/com/android/server/telecom/tests/MissedInformationTest.java
@@ -20,11 +20,14 @@
 import static android.provider.CallLog.Calls.AUTO_MISSED_MAXIMUM_DIALING;
 import static android.provider.CallLog.Calls.AUTO_MISSED_MAXIMUM_RINGING;
 import static android.provider.CallLog.Calls.MISSED_REASON_NOT_MISSED;
+import static android.provider.CallLog.Calls.USER_MISSED_CALL_FILTERS_TIMEOUT;
+import static android.provider.CallLog.Calls.USER_MISSED_CALL_SCREENING_SERVICE_SILENCED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -44,6 +47,8 @@
 import com.android.server.telecom.CallIntentProcessor;
 import com.android.server.telecom.CallState;
 import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.TelecomSystem;
+import com.android.server.telecom.callfiltering.CallFilteringResult;
 
 import org.junit.After;
 import org.junit.Before;
@@ -58,10 +63,14 @@
     private static final String TEST_NUMBER = "650-555-1212";
     private static final String TEST_NUMBER_1 = "7";
     private static final String PACKAGE_NAME = "com.android.server.telecom.tests";
+    private static final String CALL_SCREENING_SERVICE_PACKAGE_NAME = "testapp";
+    private static final String CALL_SCREENING_COMPONENT_NAME = "testapp";
+
     @Mock ContentResolver mContentResolver;
     @Mock IContentProvider mContentProvider;
     @Mock Call mEmergencyCall;
     @Mock Analytics.CallInfo mCallInfo;
+    @Mock Call mIncomingCall;
     private CallsManager mCallsManager;
     private CallIntentProcessor.AdapterImpl mAdapter;
 
@@ -98,7 +107,8 @@
         Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
         Analytics.CallInfoImpl callAnalytics = analyticsMap.get(testCall.mCallId);
         assertEquals(MISSED_REASON_NOT_MISSED, callAnalytics.missedReason);
-        assertEquals(MISSED_REASON_NOT_MISSED, (int) values.getAsInteger(CallLog.Calls.MISSED_REASON));
+        assertEquals(MISSED_REASON_NOT_MISSED,
+                (long) values.getAsLong(CallLog.Calls.MISSED_REASON));
     }
 
     @Test
@@ -116,11 +126,11 @@
         ContentValues values = verifyInsertionWithCapture();
 
         Map<String, Analytics.CallInfoImpl> analyticsMap = Analytics.cloneData();
+        assertEquals(AUTO_MISSED_EMERGENCY_CALL,
+                (long) values.getAsLong(CallLog.Calls.MISSED_REASON));
         for (Analytics.CallInfoImpl ci : analyticsMap.values()) {
             assertEquals(AUTO_MISSED_EMERGENCY_CALL, ci.missedReason);
         }
-        assertEquals(AUTO_MISSED_EMERGENCY_CALL,
-                (int) values.getAsInteger(CallLog.Calls.MISSED_REASON));
     }
 
     @Test
@@ -146,7 +156,7 @@
             assertEquals(AUTO_MISSED_MAXIMUM_DIALING, analyticsMap.get(callId).missedReason);
         }
         assertEquals(AUTO_MISSED_MAXIMUM_DIALING,
-                (int) values.getAsInteger(CallLog.Calls.MISSED_REASON));
+                (long) values.getAsLong(CallLog.Calls.MISSED_REASON));
     }
 
     @Test
@@ -172,7 +182,49 @@
             assertEquals(AUTO_MISSED_MAXIMUM_RINGING, analyticsMap.get(callId).missedReason);
         }
         assertEquals(AUTO_MISSED_MAXIMUM_RINGING,
-                (int) values.getAsInteger(CallLog.Calls.MISSED_REASON));
+                (long) values.getAsLong(CallLog.Calls.MISSED_REASON));
+    }
+
+    @Test
+    public void testCallFiltersTimeout() throws Exception {
+        setUpIncomingCall();
+        CallFilteringResult result = new CallFilteringResult.Builder()
+                .setShouldAllowCall(true)
+                .build();
+        mCallsManager.onCallFilteringComplete(mIncomingCall, result, true);
+        mCallsManager.markCallAsDisconnected(mIncomingCall,
+                    new DisconnectCause(DisconnectCause.MISSED));
+        ContentValues values = verifyInsertionWithCapture();
+
+        long missedReason = values.getAsLong(CallLog.Calls.MISSED_REASON);
+        assertTrue((missedReason & USER_MISSED_CALL_FILTERS_TIMEOUT) > 0);
+        missedReason = ((Analytics.CallInfoImpl) mIncomingCall.getAnalytics()).missedReason;
+        assertTrue((missedReason & USER_MISSED_CALL_FILTERS_TIMEOUT) > 0);
+    }
+
+    @Test
+    public void testCallScreeningServiceSilence() throws Exception {
+        setUpIncomingCall();
+        CallFilteringResult result = new CallFilteringResult.Builder()
+                .setShouldAllowCall(true)
+                .setShouldSilence(true)
+                .setCallScreeningAppName(CALL_SCREENING_SERVICE_PACKAGE_NAME)
+                .setCallScreeningComponentName(CALL_SCREENING_COMPONENT_NAME)
+                .build();
+        mCallsManager.onCallFilteringComplete(mIncomingCall, result, false);
+        assertTrue(mIncomingCall.isIncoming());
+        mCallsManager.markCallAsDisconnected(mIncomingCall,
+                new DisconnectCause(DisconnectCause.MISSED));
+        ContentValues values = verifyInsertionWithCapture();
+
+        long missedReason = values.getAsLong(CallLog.Calls.MISSED_REASON);
+        assertTrue((missedReason & USER_MISSED_CALL_SCREENING_SERVICE_SILENCED) > 0);
+        assertEquals(CALL_SCREENING_COMPONENT_NAME,
+                values.getAsString(CallLog.Calls.CALL_SCREENING_COMPONENT_NAME));
+        assertEquals(CALL_SCREENING_SERVICE_PACKAGE_NAME,
+                values.getAsString(CallLog.Calls.CALL_SCREENING_APP_NAME));
+        missedReason = ((Analytics.CallInfoImpl) mIncomingCall.getAnalytics()).missedReason;
+        assertTrue((missedReason & USER_MISSED_CALL_SCREENING_SERVICE_SILENCED) > 0);
     }
 
     private ContentValues verifyInsertionWithCapture() {
@@ -190,4 +242,16 @@
         when(mEmergencyCall.getContext()).thenReturn(mSpyContext);
         when(mEmergencyCall.getHandle()).thenReturn(Uri.parse("tel:" + TEST_NUMBER));
     }
+
+    private void setUpIncomingCall() throws Exception {
+        mIncomingCall = spy(new Call("0", mSpyContext, mCallsManager,
+                (TelecomSystem.SyncRoot) mTelecomSystem.getLock(),
+                null, mCallsManager.getPhoneNumberUtilsAdapter(), null,
+                null, null, mPhoneAccountA0.getAccountHandle(),
+                Call.CALL_DIRECTION_INCOMING, false, false,
+                mClockProxy, null));
+        mIncomingCall.initAnalytics();
+        when(mIncomingCall.getIntentExtras()).thenReturn(new Bundle());
+        when(mIncomingCall.getViaNumber()).thenReturn(TEST_NUMBER);
+    }
 }
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index ab7693a..5c1cdc4 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -95,8 +95,6 @@
 import com.android.server.telecom.Timeouts;
 import com.android.server.telecom.WiredHeadsetManager;
 import com.android.server.telecom.bluetooth.BluetoothRouteManager;
-import com.android.server.telecom.callfiltering.CallFilterResultCallback;
-import com.android.server.telecom.callfiltering.IncomingCallFilter;
 import com.android.server.telecom.components.UserCallIntentProcessor;
 import com.android.server.telecom.ui.IncomingCallNotifier;
 
@@ -522,16 +520,6 @@
                 },
                 mClockProxy,
                 mRoleManagerAdapter,
-                new IncomingCallFilter.Factory() {
-                    @Override
-                    public IncomingCallFilter create(Context context,
-                            CallFilterResultCallback listener, com.android.server.telecom.Call call,
-                            TelecomSystem.SyncRoot lock, Timeouts.Adapter timeoutsAdapter,
-                            List<IncomingCallFilter.CallFilter> filters) {
-                        return new IncomingCallFilter(context, listener, call, lock,
-                                timeoutsAdapter, filters, mHandlerThread.getThreadHandler());
-                    }
-                },
                 new ContactsAsyncHelper.Factory() {
                     @Override
                     public ContactsAsyncHelper create(