Support enhanced call blocking function

- Add settings about whether to accept or block an incoming call
from unidentified numbers by configuring the setting for each reason
(unregistered/private/pay phone/unknown).
- Show a notification when making an emergency call.

Bug: 28189985
Test: Manual
Change-Id: I00a51947e5b30be8192b08f0c07cb89c8736a75d
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 540e4a4..588e5c3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -102,6 +102,15 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+
+        <activity android:name=".settings.CallBlockDisabledActivity"
+                android:configChanges="keyboardHidden|orientation|screenSize"
+                android:excludeFromRecents="true"
+                android:launchMode="singleInstance"
+                android:theme="@style/Theme.Telecomm.Transparent"
+                android:process=":ui">
+        </activity>
+
         <!-- Activity that starts the outgoing call process by listening to CALL intent which
              contain contact information in the intent's data. CallActivity handles any data
              URL with the schemes "tel", "sip", and "voicemail". It also handles URLs linked to
diff --git a/proguard.flags b/proguard.flags
index 4e0c310..7c71a15 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,5 +1,8 @@
 -verbose
 -keep @com.android.internal.annotations.VisibleForTesting class *
+-keep public class * extends android.widget.ListView {
+    public *;
+}
 -keep class com.android.server.telecom.TelecomSystem {
   *;
 }
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 58e5284..bb63ad2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -252,8 +252,37 @@
     <string name="notification_channel_incoming_call">Incoming calls</string>
     <!-- Notification channel name for a channel containing missed call notifications. -->
     <string name="notification_channel_missed_call">Missed calls</string>
+    <!-- Notification channel name for a channel containing call blocking notifications. -->
+    <string name="notification_channel_call_blocking">Call Blocking</string>
 
     <!-- Alert dialog content used to inform the user that placing a new outgoing call will end the
          ongoing call in the app "other_app". -->
     <string name="alert_outgoing_call">Placing this call will end your <xliff:g id="other_app">%1$s</xliff:g> call.</string>
+
+    <!-- The name of a feature available under the Call settings. -->
+    <string name="phone_settings_call_blocking_txt">Call Blocking</string>
+    <!-- Call type to be blocked. See the explanatory text "phone_settings_number_not_in_contact_summary_txt". -->
+    <string name="phone_settings_number_not_in_contact_txt">Numbers not in Contacts</string>
+    <!-- Explanatory text under the call type "phone_settings_number_not_in_contact_txt". -->
+    <string name="phone_settings_number_not_in_contact_summary_txt">Block numbers that are not listed in your Contacts</string>
+    <!-- Call type to be blocked. See the explanatory text "phone_settings_private_num_summary_txt". This is also called Anonymous or Withheld depending on region. -->
+    <string name="phone_settings_private_num_txt">Private</string>
+    <!-- Explanatory text under the call type "phone_settings_payphone_summary_txt". -->
+    <string name="phone_settings_private_num_summary_txt">Block callers that do not disclose their number</string>
+    <!-- Call type to be blocked. See the explanatory text "phone_settings_private_num_summary_txt".  -->
+    <string name="phone_settings_payphone_txt">Pay phone</string>
+    <!-- Explanatory text under the call type "phone_settings_payphone_txt". -->
+    <string name="phone_settings_payphone_summary_txt">Block calls from pay phones</string>
+    <!-- Call type to be blocked. See the explanatory text "phone_settings_unknown_summary_txt".  -->
+    <string name="phone_settings_unknown_txt">Unknown</string>
+    <!-- Explanatory text under the call type "phone_settings_unknown_txt". This occurs when no caller ID information unavailable (e.g., international calls, IP phones that operators cannot identify the caller) -->
+    <string name="phone_settings_unknown_summary_txt">Block calls from unidentified callers</string>
+    <!-- Notification. Make this translation consistent with "phone_settings_call_blocking_txt". -->
+    <string name="phone_strings_call_blocking_turned_off_notification_title_txt">Call Blocking</string>
+    <!-- Notification that appears when the feature Call Blocking has been disabled. -->
+    <string name="phone_strings_call_blocking_turned_off_notification_text_txt">Call Blocking disabled</string>
+    <!-- Title of the dialog "phone_strings_emergency_call_made_dialog_text_txt". -->
+    <string name="phone_strings_emergency_call_made_dialog_title_txt">Emergency call made</string>
+    <!-- Notification details that appear when the user taps the notification "phone_strings_call_blocking_turned_off_notification_text_txt". -->
+    <string name="phone_strings_emergency_call_made_dialog_call_blocking_text_txt">Call Blocking has been disabled to allow emergency responders to contact you.</string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 29c5566..3216719 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -39,6 +39,7 @@
         <item name="android:homeAsUpIndicator">@drawable/ic_back_arrow</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:colorAccent">@color/theme_color</item>
+        <item name="android:listDivider">@null</item>
     </style>
 
     <style name="TelecomDialerSettingsActionBarStyle" parent="android:Widget.Material.ActionBar">
diff --git a/res/xml/activity_blocked_numbers.xml b/res/xml/activity_blocked_numbers.xml
index 4eb4f85..15e1859 100644
--- a/res/xml/activity_blocked_numbers.xml
+++ b/res/xml/activity_blocked_numbers.xml
@@ -33,9 +33,7 @@
 
         <FrameLayout
                 android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:paddingLeft="@dimen/blocked_numbers_large_padding"
-                android:paddingRight="@dimen/blocked_numbers_large_padding">
+                android:layout_height="match_parent">
 
             <TextView
                     android:id="@+id/non_primary_user"
@@ -43,6 +41,8 @@
                     android:layout_height="wrap_content"
                     android:text="@string/non_primary_user"
                     android:paddingTop="@dimen/blocked_numbers_large_padding"
+                    android:paddingLeft="@dimen/blocked_numbers_large_padding"
+                    android:paddingRight="@dimen/blocked_numbers_large_padding"
                     style="@style/BlockedNumbersTitleText"
                     android:visibility="gone" />
 
@@ -50,40 +50,48 @@
                     android:id="@+id/manage_blocked_ui"
                     android:orientation="vertical"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingTop="@dimen/blocked_numbers_large_padding">
+                    android:layout_height="wrap_content">
 
-                <TextView
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:text="@string/blocked_numbers_msg"
-                        android:paddingBottom="@dimen/blocked_numbers_extra_large_padding"
-                        style="@style/BlockedNumbersTitleText" />
-
-                <TextView
-                        android:id="@+id/add_blocked"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:text="@string/block_number"
-                        android:layout_marginBottom="@dimen/blocked_numbers_button_bottom_margin"
-                        style="@style/BlockedNumbersButton"
-                        android:background="?android:attr/selectableItemBackgroundBorderless" />
-
-                <ProgressBar
-                        android:id="@+id/progress_bar"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="center"
-                        android:indeterminate="true"
-                        android:layout_marginTop="@dimen/blocked_numbers_progress_bar_padding"
-                        style="@android:style/Widget.ProgressBar.Large" />
-
-                <ListView
-                        android:id="@android:id/list"
+                <FrameLayout
+                        android:id="@+id/enhanced_call_blocking_container"
                         android:layout_width="match_parent"
-                        android:layout_height="match_parent"
-                        android:nestedScrollingEnabled="true"
-                        android:paddingBottom="@dimen/blocked_numbers_extra_large_padding" />
+                        android:layout_height="wrap_content" />
+
+                <LinearLayout
+                        android:orientation="vertical"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:paddingTop="@dimen/blocked_numbers_large_padding"
+                        android:paddingLeft="@dimen/blocked_numbers_large_padding"
+                        android:paddingRight="@dimen/blocked_numbers_large_padding">
+
+                    <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/blocked_numbers_msg"
+                            android:paddingBottom="@dimen/blocked_numbers_extra_large_padding"
+                            style="@style/BlockedNumbersTitleText" />
+
+                    <TextView
+                            android:id="@+id/add_blocked"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/block_number"
+                            android:layout_marginBottom="@dimen/blocked_numbers_button_bottom_margin"
+                            style="@style/BlockedNumbersButton"
+                            android:background="?android:attr/selectableItemBackgroundBorderless" />
+
+                    <ProgressBar
+                            android:id="@+id/progress_bar"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:layout_gravity="center"
+                            android:indeterminate="true"
+                            android:layout_marginTop="@dimen/blocked_numbers_progress_bar_padding"
+                            style="@android:style/Widget.ProgressBar.Large" />
+
+                    <include layout="@xml/layout_customized_listview" />
+                </LinearLayout>
             </LinearLayout>
         </FrameLayout>
     </LinearLayout>
diff --git a/res/xml/blocking_suppressed_butterbar.xml b/res/xml/blocking_suppressed_butterbar.xml
index cd4579e..d6a8472 100644
--- a/res/xml/blocking_suppressed_butterbar.xml
+++ b/res/xml/blocking_suppressed_butterbar.xml
@@ -64,11 +64,10 @@
             style="@style/BlockedNumbersButton"
             android:background="?android:attr/selectableItemBackgroundBorderless" />
 
-    <View
-          xmlns:tools="http://schemas.android.com/tools"
-          android:layout_width="match_parent"
-          android:layout_height="@dimen/blocked_numbers_divider_stroke"
-          android:layout_below="@id/reenable_button"
-          android:layout_marginTop="@dimen/blocked_numbers_large_padding"
-          android:background="@color/blocked_numbers_divider_color" />
+    <include
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/reenable_button"
+            android:layout_marginTop="@dimen/blocked_numbers_large_padding"
+            layout="@xml/layout_divider" />
 </RelativeLayout>
\ No newline at end of file
diff --git a/res/xml/enhanced_call_blocking_settings.xml b/res/xml/enhanced_call_blocking_settings.xml
new file mode 100644
index 0000000..32c4c5d
--- /dev/null
+++ b/res/xml/enhanced_call_blocking_settings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/phone_settings_call_blocking_txt">
+    <SwitchPreference
+        android:key="block_numbers_not_in_contacts_setting"
+        android:title="@string/phone_settings_number_not_in_contact_txt"
+        android:summary="@string/phone_settings_number_not_in_contact_summary_txt"
+        android:persistent="false"
+        android:defaultValue="false"/>
+    <SwitchPreference
+        android:key="block_private_number_calls_setting"
+        android:title="@string/phone_settings_private_num_txt"
+        android:summary="@string/phone_settings_private_num_summary_txt"
+        android:persistent="false"
+        android:defaultValue="false"/>
+    <SwitchPreference
+        android:key="block_payphone_calls_setting"
+        android:title="@string/phone_settings_payphone_txt"
+        android:summary="@string/phone_settings_payphone_summary_txt"
+        android:persistent="false"
+        android:defaultValue="false"/>
+    <SwitchPreference
+        android:key="block_unknown_calls_setting"
+        android:title="@string/phone_settings_unknown_txt"
+        android:summary="@string/phone_settings_unknown_summary_txt"
+        android:persistent="false"
+        android:defaultValue="false"/>
+    <!--Add divider to separate this enhanced call blocking settings from other settings-->
+    <Preference
+        android:key="enhanced_call_blocking_divider"
+        android:persistent="false"
+        android:layout="@xml/layout_divider"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/layout_customized_listview.xml b/res/xml/layout_customized_listview.xml
new file mode 100644
index 0000000..f5ced8e
--- /dev/null
+++ b/res/xml/layout_customized_listview.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<com.android.server.telecom.components.NonScrollListView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/list"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:nestedScrollingEnabled="true" />
diff --git a/res/xml/layout_divider.xml b/res/xml/layout_divider.xml
new file mode 100644
index 0000000..2eae636
--- /dev/null
+++ b/res/xml/layout_divider.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/blocked_numbers_divider_stroke"
+        android:background="@color/blocked_numbers_divider_color" />
+</LinearLayout>
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 2758f1b..f905514 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -973,7 +973,7 @@
         }
     }
 
-    int getHandlePresentation() {
+    public int getHandlePresentation() {
         return mHandlePresentation;
     }
 
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 28a54ad..f030e22 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -17,9 +17,11 @@
 package com.android.server.telecom;
 
 import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
@@ -32,6 +34,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.BlockedNumberContract.SystemContract;
 import android.provider.CallLog.Calls;
 import android.provider.Settings;
 import android.telecom.CallAudioState;
@@ -47,6 +50,7 @@
 import android.telecom.Logging.Runnable;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
+import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -66,6 +70,7 @@
 import com.android.server.telecom.callfiltering.DirectToVoicemailCallFilter;
 import com.android.server.telecom.callfiltering.IncomingCallFilter;
 import com.android.server.telecom.components.ErrorDialogActivity;
+import com.android.server.telecom.settings.BlockedNumbersUtil;
 import com.android.server.telecom.ui.ConfirmCallDialogActivity;
 import com.android.server.telecom.ui.IncomingCallNotifier;
 
@@ -312,6 +317,24 @@
     };
 
     /**
+     * Receiver for enhanced call blocking feature to update the emergency call notification
+     * in below cases:
+     *  1) Carrier config changed.
+     *  2) Blocking suppression state changed.
+     */
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
+                    || SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED.equals(action)) {
+                BlockedNumbersUtil.updateEmergencyCallNotification(context,
+                        SystemContract.shouldShowEmergencyCallNotification(context));
+             }
+        }
+    };
+
+    /**
      * Initializes the required Telecom components.
      */
     @VisibleForTesting
@@ -426,6 +449,11 @@
         if (userManager.isPrimaryUser()) {
             onUserSwitch(Process.myUserHandle());
         }
+        // Register BroadcastReceiver to handle enhanced call blocking feature related event.
+        IntentFilter intentFilter = new IntentFilter(
+                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        intentFilter.addAction(SystemContract.ACTION_BLOCK_SUPPRESSION_STATE_CHANGED);
+        context.registerReceiver(mReceiver, intentFilter);
     }
 
     public void setIncomingCallNotifier(IncomingCallNotifier incomingCallNotifier) {
@@ -489,7 +517,8 @@
 
         List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
         filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
-        filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
+        filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter(),
+                mCallerInfoLookupHelper));
         filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
                 mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock));
         new IncomingCallFilter(mContext, this, incomingCall, mLock,
diff --git a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
index 2f78d23..748d15e 100644
--- a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
+++ b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
@@ -17,12 +17,19 @@
 package com.android.server.telecom.callfiltering;
 
 import android.content.Context;
+import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.BlockedNumberContract;
 import android.telecom.Log;
 import android.telecom.Logging.Session;
+import android.telecom.TelecomManager;
 
+import com.android.internal.telephony.CallerInfo;
 import com.android.server.telecom.Call;
+import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.LogUtils;
+import com.android.server.telecom.settings.BlockedNumbersUtil;
 
 /**
  * An {@link AsyncTask} that checks if a call needs to be blocked.
@@ -37,10 +44,13 @@
     private Session mBackgroundTaskSubsession;
     private Session mPostExecuteSubsession;
     private CallFilterResultCallback mCallback;
+    private CallerInfoLookupHelper mCallerInfoLookupHelper;
 
-    public AsyncBlockCheckFilter(Context context, BlockCheckerAdapter blockCheckerAdapter) {
+    public AsyncBlockCheckFilter(Context context, BlockCheckerAdapter blockCheckerAdapter,
+            CallerInfoLookupHelper callerInfoLookupHelper) {
         mContext = context;
         mBlockCheckerAdapter = blockCheckerAdapter;
+        mCallerInfoLookupHelper = callerInfoLookupHelper;
     }
 
     @Override
@@ -49,7 +59,29 @@
         mIncomingCall = call;
         String number = call.getHandle() == null ?
                 null : call.getHandle().getSchemeSpecificPart();
-        this.execute(number);
+        if (BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(mContext)) {
+            int presentation = mIncomingCall.getHandlePresentation();
+            if (presentation == TelecomManager.PRESENTATION_ALLOWED) {
+                mCallerInfoLookupHelper.startLookup(call.getHandle(),
+                        new CallerInfoLookupHelper.OnQueryCompleteListener() {
+                            @Override
+                            public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) {
+                                boolean contactExists = info == null ? false : info.contactExists;
+                                execute(number, String.valueOf(presentation),
+                                        String.valueOf(contactExists));
+                            }
+
+                            @Override
+                            public void onContactPhotoQueryComplete(Uri handle, CallerInfo info) {
+                                // ignore
+                            }
+                        });
+            } else {
+                this.execute(number, String.valueOf(presentation));
+            }
+        } else {
+            this.execute(number);
+        }
     }
 
     @Override
@@ -63,7 +95,16 @@
         try {
             Log.continueSession(mBackgroundTaskSubsession, "ABCF.dIB");
             Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_INITIATED);
-            return mBlockCheckerAdapter.isBlocked(mContext, params[0]);
+            Bundle extras = new Bundle();
+            if (params.length > 1) {
+                extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION,
+                        Integer.valueOf(params[1]));
+            }
+            if (params.length > 2) {
+                extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST,
+                        Boolean.valueOf(params[2]));
+            }
+            return mBlockCheckerAdapter.isBlocked(mContext, params[0], extras);
         } finally {
             Log.endSession();
         }
diff --git a/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java b/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
index f15a507..8c74fa9 100644
--- a/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
+++ b/src/com/android/server/telecom/callfiltering/BlockCheckerAdapter.java
@@ -17,13 +17,22 @@
 package com.android.server.telecom.callfiltering;
 
 import android.content.Context;
+import android.os.Bundle;
 
 import com.android.internal.telephony.BlockChecker;
 
 public class BlockCheckerAdapter {
     public BlockCheckerAdapter() { }
 
-    public boolean isBlocked(Context context, String number) {
-        return BlockChecker.isBlocked(context, number);
+    /**
+     * Check whether the number is blocked.
+     *
+     * @param context the context of the caller.
+     * @param number the number to check.
+     * @param extras the extra attribute of the number.
+     * @return {@code true} if the number is blocked. {@code false} otherwise.
+     */
+    public boolean isBlocked(Context context, String number, Bundle extras) {
+        return BlockChecker.isBlocked(context, number, extras);
     }
 }
diff --git a/src/com/android/server/telecom/components/NonScrollListView.java b/src/com/android/server/telecom/components/NonScrollListView.java
new file mode 100644
index 0000000..ce6e638
--- /dev/null
+++ b/src/com/android/server/telecom/components/NonScrollListView.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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.components;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+public class NonScrollListView extends ListView {
+
+    public NonScrollListView(Context context) {
+        super(context);
+    }
+
+    public NonScrollListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int customizedHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+        super.onMeasure(widthMeasureSpec, customizedHeightMeasureSpec);
+        ViewGroup.LayoutParams params = getLayoutParams();
+        params.height = getMeasuredHeight();
+    }
+}
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
index 7090adb..ae7e661 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
@@ -19,7 +19,9 @@
 import android.annotation.Nullable;
 import android.app.ActionBar;
 import android.app.AlertDialog;
+import android.app.Fragment;
 import android.app.FragmentManager;
+import android.app.FragmentTransaction;
 import android.app.ListActivity;
 import android.app.LoaderManager;
 import android.content.BroadcastReceiver;
@@ -137,6 +139,9 @@
 
         updateButterBar();
 
+        updateEnhancedCallBlockingFragment(
+                BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(this));
+
         mBlockingStatusReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
@@ -176,6 +181,30 @@
         }
     }
 
+    /**
+     * Update the visibility of {@link EnhancedCallBlockingFragment}.
+     */
+    private void updateEnhancedCallBlockingFragment(boolean show) {
+        FragmentManager fragmentManager = getFragmentManager();
+        Fragment fragment = fragmentManager.findFragmentById(R.id.enhanced_call_blocking_container);
+        if (!show && fragment == null) {
+            // Nothing to show, so bail early.
+            return;
+        }
+        final FragmentTransaction transaction = fragmentManager.beginTransaction();
+        if (show) {
+            if (fragment == null) {
+                fragment = new EnhancedCallBlockingFragment();
+                transaction.add(R.id.enhanced_call_blocking_container, fragment);
+            } else {
+                transaction.show(fragment);
+            }
+        } else {
+            transaction.hide(fragment);
+        }
+        transaction.commit();
+    }
+
     @Override
     public Loader<Cursor> onCreateLoader(int id, Bundle args) {
         return new CursorLoader(this, BlockedNumberContract.BlockedNumbers.CONTENT_URI,
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersUtil.java b/src/com/android/server/telecom/settings/BlockedNumbersUtil.java
index b75c4b3..4f45720 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersUtil.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersUtil.java
@@ -16,18 +16,32 @@
 
 package com.android.server.telecom.settings;
 
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.provider.BlockedNumberContract.SystemContract;
+import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneNumberUtils;
 import android.text.BidiFormatter;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextDirectionHeuristics;
 import android.widget.Toast;
+
+import com.android.server.telecom.R;
+import com.android.server.telecom.ui.NotificationChannelManager;
+
 import java.util.Locale;
 
 public final class BlockedNumbersUtil {
     private BlockedNumbersUtil() {}
 
+    private static final int EMERGENCY_CALL_NOTIFICATION = 150;
+
     /**
      * @return locale and default to US if no locale was returned.
      */
@@ -67,4 +81,82 @@
                 messageSpannable,
                 Toast.LENGTH_SHORT).show();
     }
+
+    /**
+     * Updates an emergency call notification
+     *
+     * @param context context to start CallBlockDisabledActivity.
+     * @param showNotification if {@code true} show notification, {@code false} cancel notification.
+     */
+    public static void updateEmergencyCallNotification(Context context, boolean showNotification) {
+        NotificationManager notificationManager =
+                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        if (showNotification) {
+            Intent intent = new Intent(context, CallBlockDisabledActivity.class);
+            PendingIntent pendingIntent = PendingIntent.getActivity(
+                    context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+            String title = context.getString(
+                    R.string.phone_strings_call_blocking_turned_off_notification_title_txt);
+            String message = context.getString(
+                    R.string.phone_strings_call_blocking_turned_off_notification_text_txt);
+            Notification.Builder builder = new Notification.Builder(context);
+            Notification notification = builder.setSmallIcon(android.R.drawable.stat_sys_warning)
+                    .setTicker(message)
+                    .setContentTitle(title)
+                    .setContentText(message)
+                    .setContentIntent(pendingIntent)
+                    .setShowWhen(true)
+                    .setChannel(NotificationChannelManager.CHANNEL_ID_CALL_BLOCKING)
+                    .build();
+
+            notification.flags |= Notification.FLAG_NO_CLEAR;
+            notificationManager.notifyAsUser(null /* tag */ , EMERGENCY_CALL_NOTIFICATION,
+                    notification, new UserHandle(UserHandle.USER_OWNER));
+        } else {
+            notificationManager.cancelAsUser(null /* tag */ , EMERGENCY_CALL_NOTIFICATION,
+                    new UserHandle(UserHandle.USER_OWNER));
+        }
+    }
+
+    /**
+     * Returns the platform configuration for whether to enable enhanced call blocking feature.
+     *
+     * @param context the application context
+     * @return If {@code true} means enhanced call blocking enabled by platform,
+     *            {@code false} otherwise.
+     */
+    public static boolean isEnhancedCallBlockingEnabledByPlatform(Context context) {
+        CarrierConfigManager configManager = (CarrierConfigManager) context.getSystemService(
+                Context.CARRIER_CONFIG_SERVICE);
+        PersistableBundle carrierConfig = configManager.getConfig();
+        if (carrierConfig == null) {
+            carrierConfig = configManager.getDefaultConfig();
+        }
+        return carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL);
+    }
+
+    /**
+     * Get the blocking setting status from {@link BlockedNumberProvider} SharedPreferences.
+     *
+     * @param context the application context
+     * @param key preference key of SharedPreferences.
+     * @return If {@code true} means the key enabled in the SharedPreferences,
+     *            {@code false} otherwise.
+     */
+    public static boolean getEnhancedBlockSetting(Context context, String key) {
+        return SystemContract.getEnhancedBlockSetting(context, key);
+    }
+
+    /**
+     * Set the blocking setting status to {@link BlockedNumberProvider} SharedPreferences.
+     *
+     * @param context the application context
+     * @param key preference key of SharedPreferences.
+     * @param value the register value to the SharedPreferences.
+     */
+    public static void setEnhancedBlockSetting(Context context, String key, boolean value) {
+        SystemContract.setEnhancedBlockSetting(context, key, value);
+    }
 }
diff --git a/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java b/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java
new file mode 100644
index 0000000..5f42b37
--- /dev/null
+++ b/src/com/android/server/telecom/settings/CallBlockDisabledActivity.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.settings;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.provider.BlockedNumberContract;
+
+import com.android.server.telecom.R;
+
+/**
+ * Shows a dialog when user taps an notification in notification tray.
+ */
+public class CallBlockDisabledActivity extends Activity {
+    private AlertDialog mDialog;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        showCallBlockingOffDialog();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        dismissCallBlockingOffDialog();
+    }
+
+    /**
+     * Shows the dialog that notifies user that [Call Blocking] has been turned off.
+     */
+    private void showCallBlockingOffDialog() {
+        if (isShowingCallBlockingOffDialog()) {
+            return;
+        }
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        mDialog = builder
+                .setTitle(R.string.phone_strings_emergency_call_made_dialog_title_txt)
+                .setMessage(R.string
+                        .phone_strings_emergency_call_made_dialog_call_blocking_text_txt)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        BlockedNumbersUtil.setEnhancedBlockSetting(
+                                CallBlockDisabledActivity.this,
+                                BlockedNumberContract.SystemContract
+                                        .ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION,
+                                false);
+                        BlockedNumbersUtil.updateEmergencyCallNotification(
+                                CallBlockDisabledActivity.this, false);
+                        finish();
+                    }
+                })
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        finish();
+                    }
+                })
+                .create();
+        mDialog.setCanceledOnTouchOutside(false);
+        mDialog.show();
+    }
+
+    /**
+     * Dismisses the dialog that notifies user that [Call Blocking] has been turned off.
+     */
+    private void dismissCallBlockingOffDialog() {
+        if (isShowingCallBlockingOffDialog()) {
+            mDialog.dismiss();
+        }
+        mDialog = null;
+    }
+
+    /**
+     * Checks whether the dialog is currently showing.
+     *
+     * @return true if the dialog is currently showing, false otherwise.
+     */
+    private boolean isShowingCallBlockingOffDialog() {
+        return (mDialog != null && mDialog.isShowing());
+    }
+}
diff --git a/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java b/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java
new file mode 100644
index 0000000..219c3e9
--- /dev/null
+++ b/src/com/android/server/telecom/settings/EnhancedCallBlockingFragment.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 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.settings;
+
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.BlockedNumberContract.SystemContract;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.server.telecom.R;
+
+public class EnhancedCallBlockingFragment extends PreferenceFragment
+        implements Preference.OnPreferenceChangeListener {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.enhanced_call_blocking_settings);
+
+        setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED);
+        setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE);
+        setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE);
+        setOnPreferenceChangeListener(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN);
+    }
+
+    /**
+     * Set OnPreferenceChangeListener for the preference.
+     */
+    private void setOnPreferenceChangeListener(String key) {
+        SwitchPreference pref = (SwitchPreference) findPreference(key);
+        if (pref != null) {
+            pref.setOnPreferenceChangeListener(this);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED);
+        updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PRIVATE);
+        updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_PAYPHONE);
+        updateEnhancedBlockPref(SystemContract.ENHANCED_SETTING_KEY_BLOCK_UNKNOWN);
+    }
+
+    /**
+     * Update preference checked status.
+     */
+    private void updateEnhancedBlockPref(String key) {
+        SwitchPreference pref = (SwitchPreference) findPreference(key);
+        if (pref != null) {
+            pref.setChecked(BlockedNumbersUtil.getEnhancedBlockSetting(getActivity(), key));
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object objValue) {
+        BlockedNumbersUtil.setEnhancedBlockSetting(getActivity(), preference.getKey(),
+                (boolean) objValue);
+        return true;
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.xml.layout_customized_listview,
+                container, false);
+    }
+}
diff --git a/src/com/android/server/telecom/ui/NotificationChannelManager.java b/src/com/android/server/telecom/ui/NotificationChannelManager.java
index 46b6c28..70d4d0d 100644
--- a/src/com/android/server/telecom/ui/NotificationChannelManager.java
+++ b/src/com/android/server/telecom/ui/NotificationChannelManager.java
@@ -36,6 +36,7 @@
 
     public static final String CHANNEL_ID_MISSED_CALLS = "TelecomMissedCalls";
     public static final String CHANNEL_ID_INCOMING_CALLS = "TelecomIncomingCalls";
+    public static final String CHANNEL_ID_CALL_BLOCKING = "TelecomCallBlocking";
 
     private BroadcastReceiver mLocaleChangeReceiver = new BroadcastReceiver() {
         @Override
@@ -55,6 +56,7 @@
     private void createOrUpdateAll(Context context) {
         createOrUpdateChannel(context, CHANNEL_ID_MISSED_CALLS);
         createOrUpdateChannel(context, CHANNEL_ID_INCOMING_CALLS);
+        createOrUpdateChannel(context, CHANNEL_ID_CALL_BLOCKING);
     }
 
     private void createOrUpdateChannel(Context context, String channelId) {
@@ -88,6 +90,14 @@
                 vibration = true;
                 sound = silentRingtone;
                 break;
+            case CHANNEL_ID_CALL_BLOCKING:
+                name = context.getText(R.string.notification_channel_call_blocking);
+                importance = NotificationManager.IMPORTANCE_LOW;
+                canShowBadge = false;
+                lights = false;
+                vibration = false;
+                sound = null;
+                break;
         }
 
         NotificationChannel channel = new NotificationChannel(channelId, name, importance);
diff --git a/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java b/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
index 66ae17d..9b2b3fb 100644
--- a/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
+++ b/tests/src/com/android/server/telecom/tests/AsyncBlockCheckFilterTest.java
@@ -18,9 +18,14 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.Call;
+import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
 import com.android.server.telecom.callfiltering.BlockCheckerAdapter;
 import com.android.server.telecom.callfiltering.CallFilterResultCallback;
@@ -30,6 +35,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 
 import java.util.concurrent.CountDownLatch;
@@ -47,6 +53,8 @@
     @Mock private BlockCheckerAdapter mBlockCheckerAdapter;
     @Mock private Call mCall;
     @Mock private CallFilterResultCallback mCallback;
+    @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper;
+    @Mock private CarrierConfigManager mCarrierConfigManager;
 
     private AsyncBlockCheckFilter mFilter;
     private static final CallFilteringResult BLOCK_RESULT = new CallFilteringResult(
@@ -71,7 +79,8 @@
     public void setUp() throws Exception {
         super.setUp();
         when(mCall.getHandle()).thenReturn(TEST_HANDLE);
-        mFilter = new AsyncBlockCheckFilter(mContext, mBlockCheckerAdapter);
+        mFilter = new AsyncBlockCheckFilter(mContext, mBlockCheckerAdapter,
+                mCallerInfoLookupHelper);
     }
 
     @SmallTest
@@ -82,8 +91,32 @@
             latch.countDown();
             return true;
         }).when(mBlockCheckerAdapter)
-                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()));
+                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                        any(Bundle.class));
+
+        setEnhancedBlockingEnabled(false);
         mFilter.startFilterLookup(mCall, mCallback);
+
+        waitOnLatch(latch);
+        verify(mCallback, timeout(TEST_TIMEOUT))
+                .onCallFilteringComplete(eq(mCall), eq(BLOCK_RESULT));
+    }
+
+    @SmallTest
+    @Test
+    public void testBlockNumber_enhancedBlockingEnabled() {
+        final CountDownLatch latch = new CountDownLatch(1);
+        doAnswer(invocation -> {
+            latch.countDown();
+            return true;
+        }).when(mBlockCheckerAdapter)
+                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                        any(Bundle.class));
+
+        setEnhancedBlockingEnabled(true);
+        CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyEnhancedLookupStart();
+        queryListener.onCallerInfoQueryComplete(TEST_HANDLE, null);
+
         waitOnLatch(latch);
         verify(mCallback, timeout(TEST_TIMEOUT))
                 .onCallFilteringComplete(eq(mCall), eq(BLOCK_RESULT));
@@ -97,13 +130,57 @@
             latch.countDown();
             return false;
         }).when(mBlockCheckerAdapter)
-                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()));
+                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                        any(Bundle.class));
+
+        setEnhancedBlockingEnabled(false);
         mFilter.startFilterLookup(mCall, mCallback);
+
         waitOnLatch(latch);
         verify(mCallback, timeout(TEST_TIMEOUT))
                 .onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
     }
 
+    @SmallTest
+    @Test
+    public void testDontBlockNumber_enhancedBlockingEnabled() {
+        final CountDownLatch latch = new CountDownLatch(1);
+        doAnswer(invocation -> {
+            latch.countDown();
+            return false;
+        }).when(mBlockCheckerAdapter)
+                .isBlocked(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()),
+                        any(Bundle.class));
+
+        setEnhancedBlockingEnabled(true);
+        CallerInfoLookupHelper.OnQueryCompleteListener queryListener = verifyEnhancedLookupStart();
+        queryListener.onCallerInfoQueryComplete(TEST_HANDLE, null);
+
+        waitOnLatch(latch);
+        verify(mCallback, timeout(TEST_TIMEOUT))
+                .onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
+    }
+
+    private void setEnhancedBlockingEnabled(Boolean value) {
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL,
+                value);
+        when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
+                .thenReturn(mCarrierConfigManager);
+        when(mCarrierConfigManager.getConfig()).thenReturn(bundle);
+    }
+
+    private CallerInfoLookupHelper.OnQueryCompleteListener verifyEnhancedLookupStart() {
+        // The enhanced lookup will only be excuted when enhanced blocking enabled and the
+        // presentation is PRESENTATION_ALLOWED.
+        when(mCall.getHandlePresentation()).thenReturn(TelecomManager.PRESENTATION_ALLOWED);
+        mFilter.startFilterLookup(mCall, mCallback);
+        ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> captor =
+                ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class);
+        verify(mCallerInfoLookupHelper).startLookup(eq(TEST_HANDLE), captor.capture());
+        return captor.getValue();
+    }
+
     private void waitOnLatch(CountDownLatch latch) {
         while (latch.getCount() > 0) {
             try {