Merge "Set snackbar action text to blue." into ub-contactsdialer-a-dev
diff --git a/res/drawable-hdpi/ic_unblock.png b/res/drawable-hdpi/ic_unblock.png
new file mode 100644
index 0000000..03643b2
--- /dev/null
+++ b/res/drawable-hdpi/ic_unblock.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_unblock.png b/res/drawable-mdpi/ic_unblock.png
new file mode 100644
index 0000000..d80fb2f
--- /dev/null
+++ b/res/drawable-mdpi/ic_unblock.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_unblock.png b/res/drawable-xhdpi/ic_unblock.png
new file mode 100644
index 0000000..f7dfa21
--- /dev/null
+++ b/res/drawable-xhdpi/ic_unblock.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_unblock.png b/res/drawable-xxhdpi/ic_unblock.png
new file mode 100644
index 0000000..828a487
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_unblock.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_unblock.png b/res/drawable-xxxhdpi/ic_unblock.png
new file mode 100644
index 0000000..99a1842
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_unblock.png
Binary files differ
diff --git a/res/drawable/ic_call_detail_unblock.xml b/res/drawable/ic_call_detail_unblock.xml
new file mode 100644
index 0000000..ba5378b
--- /dev/null
+++ b/res/drawable/ic_call_detail_unblock.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2015 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_unblock"
+    android:tint="@color/call_detail_footer_icon_tint" />
diff --git a/res/layout/blocked_number_fragment.xml b/res/layout/blocked_number_fragment.xml
index bb4b7f2..906e8a1 100644
--- a/res/layout/blocked_number_fragment.xml
+++ b/res/layout/blocked_number_fragment.xml
@@ -25,6 +25,36 @@
     <android.support.v7.widget.CardView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_marginBottom="8dp"
+        card_view:cardCornerRadius="0dp">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:padding="16dp"
+            android:paddingEnd="8dp">
+
+            <TextView
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="@string/blocked_call_settings_hide_setting"
+                style="@style/BlockedNumbersDescriptionTextStyle" />
+
+            <Switch android:id="@+id/hide_blocked_calls_switch"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="40dp" />
+
+        </LinearLayout>
+
+    </android.support.v7.widget.CardView>
+
+    <android.support.v7.widget.CardView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
         card_view:cardCornerRadius="0dp">
 
         <LinearLayout
diff --git a/res/layout/blocked_number_header.xml b/res/layout/blocked_number_header.xml
index 39f5322..e16efbc 100644
--- a/res/layout/blocked_number_header.xml
+++ b/res/layout/blocked_number_header.xml
@@ -33,11 +33,9 @@
             android:layout_height="wrap_content"
             android:text="@string/blocked_call_settings_import_description"
             android:textSize="@dimen/blocked_number_settings_description_text_size"
-            android:lineSpacingMultiplier="1.2"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
             android:paddingStart="@dimen/blocked_number_container_padding"
-            android:paddingEnd="@dimen/blocked_number_container_padding" />
+            android:paddingEnd="@dimen/blocked_number_container_padding"
+            style="@style/BlockedNumbersDescriptionTextStyle" />
 
         <Button android:id="@+id/import_button"
             android:layout_width="wrap_content"
diff --git a/res/layout/call_detail_footer.xml b/res/layout/call_detail_footer.xml
index 048f803..6ee76e6 100644
--- a/res/layout/call_detail_footer.xml
+++ b/res/layout/call_detail_footer.xml
@@ -27,21 +27,21 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/action_block_number"
-        android:drawableLeft="@drawable/ic_call_detail_block"
+        android:drawableStart="@drawable/ic_call_detail_block"
         style="@style/CallDetailActionItemStyle" />
 
     <TextView android:id="@+id/call_detail_action_copy"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/action_copy_number_text"
-        android:drawableLeft="@drawable/ic_call_detail_content_copy"
+        android:drawableStart="@drawable/ic_call_detail_content_copy"
         style="@style/CallDetailActionItemStyle" />
 
     <TextView android:id="@+id/call_detail_action_edit_before_call"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/action_edit_number_before_call"
-        android:drawableLeft="@drawable/ic_call_detail_edit"
+        android:drawableStart="@drawable/ic_call_detail_edit"
         android:visibility="gone"
         style="@style/CallDetailActionItemStyle" />
 
@@ -49,7 +49,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/action_report_number"
-        android:drawableLeft="@drawable/ic_call_detail_report"
+        android:drawableStart="@drawable/ic_call_detail_report"
         android:visibility="gone"
         style="@style/CallDetailActionItemStyle" />
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0b7d82c..333a99b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -833,6 +833,12 @@
         You previously marked some callers to be automatically sent to voicemail via other apps.
     </string>
 
+    <!-- Text for a setting to hide blocked calls and automatically delete voicemail from block
+         numbers. [CHAR LIMIT=NONE] -->
+    <string name="blocked_call_settings_hide_setting">
+        Hide calls and delete voicemails from blocked numbers.
+    </string>
+
     <!-- Label for button to view numbers of contacts previous marked to be sent to voicemail.
          [CHAR_LIMIT=20] -->
     <string name="blocked_call_settings_view_numbers_button">View Numbers</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 7828a20..533b88e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -324,4 +324,11 @@
         <item name="android:paddingStart">@dimen/button_horizontal_padding</item>
         <item name="android:textColor">@color/dialer_flat_button_text_color</item>
     </style>
+
+    <style name="BlockedNumbersDescriptionTextStyle">
+        <item name="android:lineSpacingMultiplier">1.2</item>
+        <item name="android:paddingTop">8dp</item>
+        <item name="android:paddingBottom">8dp</item>
+        <item name="android:textSize">@dimen/blocked_number_settings_description_text_size</item>
+    </style>
 </resources>
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 54367b1..284a578 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -49,14 +49,15 @@
 import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.calllog.CallDetailHistoryAdapter;
 import com.android.dialer.calllog.CallLogAsyncTaskUtil.CallLogAsyncTaskListener;
-import com.android.dialer.onboard.OnboardingActivity;
 import com.android.dialer.calllog.CallLogAsyncTaskUtil;
 import com.android.dialer.calllog.CallTypeHelper;
 import com.android.dialer.calllog.ContactInfoHelper;
 import com.android.dialer.calllog.PhoneAccountUtils;
-import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
 import com.android.dialer.filterednumber.FilterNumberDialogFragment;
+import com.android.dialer.filterednumber.FilteredNumbersUtil;
+import com.android.dialer.onboard.OnboardingActivity;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.util.IntentUtil.CallIntentBuilder;
 import com.android.dialer.util.PhoneNumberUtil;
@@ -393,7 +394,7 @@
     }
 
     private void updatePhotoAndBlockActionItem() {
-        if (mDetails == null) {
+        if (mDetails == null || !FilteredNumbersUtil.canBlockNumber(this, mNumber)) {
             return;
         }
 
@@ -454,8 +455,12 @@
     private void updateBlockActionItem() {
         if (mBlockedNumberId == null) {
             mBlockNumberActionItem.setText(R.string.action_block_number);
+            mBlockNumberActionItem.setCompoundDrawablesWithIntrinsicBounds(
+                    R.drawable.ic_call_detail_block, 0, 0, 0);
         } else {
             mBlockNumberActionItem.setText(R.string.action_unblock_number);
+            mBlockNumberActionItem.setCompoundDrawablesWithIntrinsicBounds(
+                    R.drawable.ic_call_detail_unblock, 0, 0, 0);
         }
 
         mBlockNumberActionItem.setVisibility(View.VISIBLE);
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 0ee7e93..3dccf27 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -260,10 +260,11 @@
         mCallLogListItemHelper =
                 new CallLogListItemHelper(phoneCallDetailsHelper, resources, mTelecomCallLogCache);
         mCallLogGroupBuilder = new CallLogGroupBuilder(this);
-        mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
-        maybeShowVoicemailPromoCard();
         mFilteredNumberAsyncQueryHandler =
                 new FilteredNumberAsyncQueryHandler(mContext.getContentResolver());
+
+        mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+        maybeShowVoicemailPromoCard();
     }
 
     public void onSaveInstanceState(Bundle outState) {
@@ -306,7 +307,7 @@
         mBlockedIdCache.clear();
     }
 
-    public void startCache() {
+    public void onResume() {
         if (PermissionsUtil.hasPermission(mContext, android.Manifest.permission.READ_CONTACTS)) {
             mContactInfoCache.start();
         }
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index dff213b..369730d 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -42,6 +42,7 @@
 import com.android.contacts.common.GeoUtil;
 import com.android.contacts.common.util.PermissionsUtil;
 import com.android.dialer.R;
+import com.android.dialer.filterednumber.FilteredNumbersUtil;
 import com.android.dialer.util.EmptyLoader;
 import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
 import com.android.dialer.widget.EmptyContentView;
@@ -124,6 +125,7 @@
     private boolean mRefreshDataRequired = true;
 
     private boolean mHasReadCallLogPermission = false;
+    private boolean mShouldHideBlockedCalls = false;
 
     // Exactly same variable is in Fragment as a package private.
     private boolean mMenuVisible = true;
@@ -209,6 +211,8 @@
         resolver.registerContentObserver(Status.CONTENT_URI, true, mVoicemailStatusObserver);
         setHasOptionsMenu(true);
 
+        mShouldHideBlockedCalls = FilteredNumbersUtil.shouldHideBlockedCalls(getActivity());
+
         if (mCallTypeFilter == Calls.VOICEMAIL_TYPE) {
             mVoicemailPlaybackPresenter = VoicemailPlaybackPresenter
                     .getInstance(activity, state);
@@ -339,9 +343,14 @@
             mRefreshDataRequired = true;
             updateEmptyMessage(mCallTypeFilter);
         }
+        if (mShouldHideBlockedCalls != FilteredNumbersUtil.shouldHideBlockedCalls(getActivity())) {
+            mShouldHideBlockedCalls = !mShouldHideBlockedCalls;
+            mRefreshDataRequired = true;
+        }
+
         mHasReadCallLogPermission = hasReadCallLogPermission;
         refreshData();
-        mAdapter.startCache();
+        mAdapter.onResume();
 
         rescheduleDisplayUpdate();
 
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index 8f2f4ba..23c77d3 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -27,6 +27,7 @@
 import android.support.v7.widget.CardView;
 import android.support.v7.widget.RecyclerView;
 import android.telecom.PhoneAccountHandle;
+import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.view.ContextMenu;
 import android.view.MenuItem;
@@ -48,6 +49,7 @@
 import com.android.dialer.R;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
 import com.android.dialer.filterednumber.FilterNumberDialogFragment;
+import com.android.dialer.filterednumber.FilteredNumbersUtil;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.util.PhoneNumberUtil;
 import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
@@ -301,22 +303,24 @@
                     .setOnMenuItemClickListener(this);
         }
 
-        mFilteredNumberAsyncQueryHandler.startBlockedQuery(
-                new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() {
-                    @Override
-                    public void onCheckComplete(Integer id) {
-                        blockId = id;
-                        int blockTitleId = blockId == null ? R.string.action_block_number
-                                : R.string.action_unblock_number;
-                        final MenuItem blockItem = menu.add(
-                                ContextMenu.NONE,
-                                R.id.context_menu_block_number,
-                                ContextMenu.NONE,
-                                blockTitleId);
-                        blockItem.setOnMenuItemClickListener(
-                                CallLogListItemViewHolder.this);
-                    }
-            }, info.normalizedNumber, number, countryIso);
+        if (FilteredNumbersUtil.canBlockNumber(mContext, number)) {
+            mFilteredNumberAsyncQueryHandler.startBlockedQuery(
+                    new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() {
+                        @Override
+                        public void onCheckComplete(Integer id) {
+                            blockId = id;
+                            int blockTitleId = blockId == null ? R.string.action_block_number
+                                    : R.string.action_unblock_number;
+                            final MenuItem blockItem = menu.add(
+                                    ContextMenu.NONE,
+                                    R.id.context_menu_block_number,
+                                    ContextMenu.NONE,
+                                    blockTitleId);
+                            blockItem.setOnMenuItemClickListener(
+                                    CallLogListItemViewHolder.this);
+                        }
+                    }, info.normalizedNumber, number, countryIso);
+        }
     }
 
     @Override
diff --git a/src/com/android/dialer/calllog/CallLogQueryHandler.java b/src/com/android/dialer/calllog/CallLogQueryHandler.java
index 81e49d2..01489c1 100644
--- a/src/com/android/dialer/calllog/CallLogQueryHandler.java
+++ b/src/com/android/dialer/calllog/CallLogQueryHandler.java
@@ -36,6 +36,7 @@
 
 import com.android.contacts.common.database.NoNullCursorAsyncQueryHandler;
 import com.android.contacts.common.util.PermissionsUtil;
+import com.android.dialer.filterednumber.FilteredNumbersUtil;
 import com.android.dialer.util.AppCompatConstants;
 import com.android.dialer.util.TelecomUtil;
 import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
@@ -177,7 +178,7 @@
 
         if (callType > CALL_TYPE_ALL) {
             where.append(" AND ");
-            where.append(String.format("(%s = ?)", Calls.TYPE));
+            where.append("(" + Calls.TYPE + " = ?)");
             selectionArgs.add(Integer.toString(callType));
         } else {
             where.append(" AND NOT ");
@@ -186,10 +187,18 @@
 
         if (newerThan > 0) {
             where.append(" AND ");
-            where.append(String.format("(%s > ?)", Calls.DATE));
+            where.append("(" + Calls.DATE + " > ?)");
             selectionArgs.add(Long.toString(newerThan));
         }
 
+        final boolean shouldHideBlockedCalls =
+                FilteredNumbersUtil.shouldHideBlockedCalls(mContext);
+        if (shouldHideBlockedCalls) {
+            where.append(" AND ");
+            where.append("(" + Calls.TYPE + " != ?)");
+            selectionArgs.add(Integer.toString(AppCompatConstants.CALLS_BLOCKED_TYPE));
+        }
+
         final int limit = (mLogLimit == -1) ? NUM_LOGS_TO_DISPLAY : mLogLimit;
         final String selection = where.length() > 0 ? where.toString() : null;
         Uri uri = TelecomUtil.getCallLogUri(mContext).buildUpon()
diff --git a/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java b/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java
index 4eb74bd..594ceeb 100644
--- a/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java
+++ b/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java
@@ -39,9 +39,13 @@
 import com.android.dialer.DialtactsActivity;
 import com.android.dialer.R;
 import com.android.dialer.calllog.PhoneAccountUtils;
+import com.android.dialer.filterednumber.FilteredNumbersUtil;
 import com.android.dialer.list.ListsFragment;
 import com.google.common.collect.Maps;
 
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -96,14 +100,14 @@
     public void updateNotification(Uri newCallUri) {
         // Lookup the list of new voicemails to include in the notification.
         // TODO: Move this into a service, to avoid holding the receiver up.
-        final NewCall[] newCalls = mNewCallsQuery.query();
+        final List<NewCall> newCalls = mNewCallsQuery.query();
 
         if (newCalls == null) {
             // Query failed, just return.
             return;
         }
 
-        if (newCalls.length == 0) {
+        if (newCalls.size() == 0) {
             // No voicemails to notify about: clear the notification.
             clearNotification();
             return;
@@ -122,7 +126,16 @@
         NewCall callToNotify = null;
 
         // Iterate over the new voicemails to determine all the information above.
-        for (NewCall newCall : newCalls) {
+        Iterator<NewCall> itr = newCalls.iterator();
+        while (itr.hasNext()) {
+            NewCall newCall = itr.next();
+
+            // Skip notifying for numbers which are blocked.
+            if (FilteredNumbersUtil.isBlocked(mContext, newCall.number, newCall.countryIso)) {
+                itr.remove();
+                continue;
+            }
+
             // Check if we already know the name associated with this number.
             String name = names.get(newCall.number);
             if (name == null) {
@@ -155,10 +168,14 @@
             }
         }
 
+        if (newCalls.isEmpty()) {
+            return;
+        }
+
         // If there is only one voicemail, set its transcription as the "long text".
         String transcription = null;
-        if (newCalls.length == 1) {
-            transcription = newCalls[0].transcription;
+        if (newCalls.size() == 1) {
+            transcription = newCalls.get(0).transcription;
         }
 
         if (newCallUri != null && callToNotify == null) {
@@ -167,7 +184,7 @@
 
         // Determine the title of the notification and the icon for it.
         final String title = resources.getQuantityString(
-                R.plurals.notification_voicemail_title, newCalls.length, newCalls.length);
+                R.plurals.notification_voicemail_title, newCalls.size(), newCalls.size());
         // TODO: Use the photo of contact if all calls are from the same person.
         final int icon = android.R.drawable.stat_notify_voicemail;
 
@@ -218,6 +235,7 @@
         public final String accountComponentName;
         public final String accountId;
         public final String transcription;
+        public final String countryIso;
 
         public NewCall(
                 Uri callsUri,
@@ -226,7 +244,8 @@
                 int numberPresentation,
                 String accountComponentName,
                 String accountId,
-                String transcription) {
+                String transcription,
+                String countryIso) {
             this.callsUri = callsUri;
             this.voicemailUri = voicemailUri;
             this.number = number;
@@ -234,6 +253,7 @@
             this.accountComponentName = accountComponentName;
             this.accountId = accountId;
             this.transcription = transcription;
+            this.countryIso = countryIso;
         }
     }
 
@@ -242,7 +262,7 @@
         /**
          * Returns the new calls for which a notification should be generated.
          */
-        public NewCall[] query();
+        public List<NewCall> query();
     }
 
     /** Create a new instance of {@link NewCallsQuery}. */
@@ -263,7 +283,8 @@
             Calls.NUMBER_PRESENTATION,
             Calls.PHONE_ACCOUNT_COMPONENT_NAME,
             Calls.PHONE_ACCOUNT_ID,
-            Calls.TRANSCRIPTION
+            Calls.TRANSCRIPTION,
+            Calls.COUNTRY_ISO
         };
         private static final int ID_COLUMN_INDEX = 0;
         private static final int NUMBER_COLUMN_INDEX = 1;
@@ -272,6 +293,7 @@
         private static final int PHONE_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX = 4;
         private static final int PHONE_ACCOUNT_ID_COLUMN_INDEX = 5;
         private static final int TRANSCRIPTION_COLUMN_INDEX = 6;
+        private static final int COUNTRY_ISO_COLUMN_INDEX = 7;
 
         private final ContentResolver mContentResolver;
         private final Context mContext;
@@ -282,7 +304,7 @@
         }
 
         @Override
-        public NewCall[] query() {
+        public List<NewCall> query() {
             if (!PermissionsUtil.hasPermission(mContext, READ_CALL_LOG)) {
                 Log.w(TAG, "No READ_CALL_LOG permission, returning null for calls lookup.");
                 return null;
@@ -296,9 +318,9 @@
                 if (cursor == null) {
                     return null;
                 }
-                NewCall[] newCalls = new NewCall[cursor.getCount()];
+                List<NewCall> newCalls = new LinkedList<NewCall>();
                 while (cursor.moveToNext()) {
-                    newCalls[cursor.getPosition()] = createNewCallsFromCursor(cursor);
+                    newCalls.add(createNewCallsFromCursor(cursor));
                 }
                 return newCalls;
             } catch (RuntimeException e) {
@@ -322,7 +344,8 @@
                     cursor.getInt(NUMBER_PRESENTATION_COLUMN_INDEX),
                     cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME_COLUMN_INDEX),
                     cursor.getString(PHONE_ACCOUNT_ID_COLUMN_INDEX),
-                    cursor.getString(TRANSCRIPTION_COLUMN_INDEX));
+                    cursor.getString(TRANSCRIPTION_COLUMN_INDEX),
+                    cursor.getString(COUNTRY_ISO_COLUMN_INDEX));
         }
     }
 
diff --git a/src/com/android/dialer/database/FilteredNumberProvider.java b/src/com/android/dialer/database/FilteredNumberProvider.java
index acb5e7f..3b63d4b 100644
--- a/src/com/android/dialer/database/FilteredNumberProvider.java
+++ b/src/com/android/dialer/database/FilteredNumberProvider.java
@@ -80,10 +80,6 @@
     @Override
     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                         String sortOrder) {
-        Log.d(TAG, "query: uri=" + uri + "  projection=" + Arrays.toString(projection) +
-                "  selection=[" + selection + "]  args=" + Arrays.toString(selectionArgs) +
-                "  order=[" + sortOrder + "] CPID=" + Binder.getCallingPid());
-
         final SQLiteDatabase db = mDialerDatabaseHelper.getReadableDatabase();
         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
         qb.setTables(DialerDatabaseHelper.Tables.FILTERED_NUMBER_TABLE);
diff --git a/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java b/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java
index 1f5ecd6..93b99b4 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumberAdapter.java
@@ -16,69 +16,48 @@
 package com.android.dialer.filterednumber;
 
 import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
+import android.app.FragmentManager;
 import android.database.Cursor;
-import android.provider.ContactsContract;
-import android.text.BidiFormatter;
-import android.text.TextDirectionHeuristics;
-import android.text.TextUtils;
+import android.content.Context;
 import android.view.View;
-import android.widget.QuickContactBadge;
-import android.widget.SimpleCursorAdapter;
-import android.widget.TextView;
 
 import com.android.contacts.common.ContactPhotoManager;
-import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
 import com.android.contacts.common.GeoUtil;
-import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.R;
-import com.android.dialer.calllog.ContactInfo;
 import com.android.dialer.calllog.ContactInfoHelper;
 import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
-import com.android.dialer.util.PhoneNumberUtil;
 
-public class BlockedNumberAdapter extends SimpleCursorAdapter {
+public class BlockedNumberAdapter extends NumberAdapter {
 
-    private Context mContext;
-    private ContactInfoHelper mContactInfoHelper;
-    private Resources mResources;
-    private BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
-    private ContactPhotoManager mContactPhotoManager;
+    public BlockedNumberAdapter(
+            Context context,
+            FragmentManager fragmentManager,
+            ContactInfoHelper contactInfoHelper,
+            ContactPhotoManager contactPhotoManager) {
+        super(context, fragmentManager, contactInfoHelper, contactPhotoManager);
+    }
 
-    public BlockedNumberAdapter(Context context) {
-        super(context, R.layout.blocked_number_item, null, new String[]{}, new int[]{}, 0);
-        mContext = context;
-        mContactInfoHelper = new ContactInfoHelper(context, GeoUtil.getCurrentCountryIso(context));
-        mContactPhotoManager = ContactPhotoManager.getInstance(context);
-        mResources = context.getResources();
+    public static BlockedNumberAdapter newBlockedNumberAdapter(
+            Context context, FragmentManager fragmentManager) {
+        return new BlockedNumberAdapter(
+                context,
+                fragmentManager,
+                new ContactInfoHelper(context, GeoUtil.getCurrentCountryIso(context)),
+                ContactPhotoManager.getInstance(context));
     }
 
     @Override
     public void bindView(View view, Context context, Cursor cursor) {
         super.bindView(view, context, cursor);
-        final TextView callerName = (TextView) view.findViewById(R.id.caller_name);
-        final TextView callerNumber = (TextView) view.findViewById(R.id.caller_number);
-        final View deleteNumber = view.findViewById(R.id.delete_button);
-        final QuickContactBadge quickContactBadge =
-                (QuickContactBadge) view.findViewById(R.id.quick_contact_photo);
-        quickContactBadge.setOverlay(null);
-        quickContactBadge.setPrioritizedMimeType(
-                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
-
         final Integer id = cursor.getInt(cursor.getColumnIndex(FilteredNumberColumns._ID));
         final String countryIso = cursor.getString(cursor.getColumnIndex(
                 FilteredNumberColumns.COUNTRY_ISO));
         final String number = cursor.getString(cursor.getColumnIndex(FilteredNumberColumns.NUMBER));
         final String normalizedNumber = cursor.getString(cursor.getColumnIndex(
                 FilteredNumberColumns.NORMALIZED_NUMBER));
-        final ContactInfo info = mContactInfoHelper.lookupNumber(number, countryIso);
-        final CharSequence locationOrType = getNumberTypeOrLocation(info);
-        final String displayNumber = getDisplayNumber(info);
-        final String displayNumberStr = mBidiFormatter.unicodeWrap(
-                displayNumber.toString(), TextDirectionHeuristics.LTR);
 
-        deleteNumber.setOnClickListener(new View.OnClickListener() {
+        final View deleteButton = view.findViewById(R.id.delete_button);
+        deleteButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 FilterNumberDialogFragment.show(
@@ -86,61 +65,13 @@
                         normalizedNumber,
                         number,
                         countryIso,
-                        displayNumber,
+                        null,
                         R.id.blocked_number_fragment,
-                        ((Activity) mContext).getFragmentManager(),
+                        getFragmentManager(),
                         null /* callback */);
             }
         });
 
-        String nameForDefaultImage;
-        if (!TextUtils.isEmpty(info.name)) {
-            nameForDefaultImage = info.name;
-            callerName.setText(info.name);
-            callerNumber.setText(locationOrType + " " + displayNumberStr);
-        } else {
-            nameForDefaultImage = displayNumber;
-            callerName.setText(displayNumberStr);
-            if (!TextUtils.isEmpty(locationOrType)) {
-                callerNumber.setText(locationOrType);
-                callerNumber.setVisibility(View.VISIBLE);
-            } else {
-                callerNumber.setVisibility(View.GONE);
-            }
-        }
-        loadContactPhoto(info, nameForDefaultImage, quickContactBadge);
-    }
-
-    private void loadContactPhoto(ContactInfo info, String displayName, QuickContactBadge badge) {
-        final String lookupKey = info.lookupUri == null
-                ? null : UriUtils.getLookupKeyFromUri(info.lookupUri);
-        final int contactType = mContactInfoHelper.isBusiness(info.sourceType)
-                ? ContactPhotoManager.TYPE_BUSINESS : ContactPhotoManager.TYPE_DEFAULT;
-        final DefaultImageRequest request = new DefaultImageRequest(displayName, lookupKey,
-                contactType, true /* isCircular */);
-        badge.assignContactUri(info.lookupUri);
-        badge.setContentDescription(
-                mResources.getString(R.string.description_contact_details, displayName));
-        mContactPhotoManager.loadDirectoryPhoto(badge, info.photoUri,
-                false /* darkTheme */, true /* isCircular */, request);
-    }
-
-    private String getDisplayNumber(ContactInfo info) {
-        if (!TextUtils.isEmpty(info.formattedNumber)) {
-            return info.formattedNumber;
-        } else if (!TextUtils.isEmpty(info.number)) {
-            return info.number;
-        } else {
-            return "";
-        }
-    }
-
-    private CharSequence getNumberTypeOrLocation(ContactInfo info) {
-        if (!TextUtils.isEmpty(info.name)) {
-            return ContactsContract.CommonDataKinds.Phone.getTypeLabel(mResources, info.type,
-                    info.label);
-        } else {
-            return PhoneNumberUtil.getGeoDescription(mContext, info.number);
-        }
+        updateView(view, number, countryIso);
     }
 }
diff --git a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
index 60c35ab..728d8b2 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
@@ -22,6 +22,8 @@
 import android.content.Loader;
 import android.database.Cursor;
 import android.os.Bundle;
+import android.widget.CompoundButton;
+import android.widget.Switch;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -36,6 +38,7 @@
 
     private BlockedNumberAdapter mAdapter;
 
+    private Switch mHideSettingSwitch;
     private View mImportSettings;
     private View mImportButton;
 
@@ -44,11 +47,18 @@
         super.onActivityCreated(savedInstanceState);
 
         if (mAdapter == null) {
-            mAdapter = new BlockedNumberAdapter(getContext());
+            mAdapter = BlockedNumberAdapter.newBlockedNumberAdapter(
+                    getContext(), getActivity().getFragmentManager());
         }
         setListAdapter(mAdapter);
 
-        getActivity().findViewById(R.id.add_number_button).setOnClickListener(this);
+        mHideSettingSwitch = (Switch) getActivity().findViewById(R.id.hide_blocked_calls_switch);
+        mHideSettingSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                FilteredNumbersUtil.setShouldHideBlockedCalls(getActivity(), isChecked);
+            }
+        });
 
         mImportSettings = getActivity().findViewById(R.id.import_settings);
         mImportButton = getActivity().findViewById(R.id.import_button);
@@ -64,6 +74,8 @@
                         });
             }
         });
+
+        getActivity().findViewById(R.id.add_number_button).setOnClickListener(this);
     }
 
     @Override
@@ -90,6 +102,8 @@
                         mImportSettings.setVisibility(visibility);
                     }
                 });
+
+        mHideSettingSwitch.setChecked(FilteredNumbersUtil.shouldHideBlockedCalls(getActivity()));
     }
 
     @Override
diff --git a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
index ebf212f..8473e32 100644
--- a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
+++ b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
@@ -26,7 +26,9 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.design.widget.Snackbar;
+import android.text.TextUtils;
 import android.view.View;
+import android.widget.Toast;
 
 import com.android.dialer.R;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
@@ -57,6 +59,7 @@
     private static final String ARG_PARENT_VIEW_ID = "parentViewId";
 
     private String mDisplayNumber;
+    private String mNormalizedNumber;
 
     private FilteredNumberAsyncQueryHandler mHandler;
     private View mParentView;
@@ -105,7 +108,14 @@
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         super.onCreateDialog(savedInstanceState);
         final boolean isBlocked = getArguments().containsKey(ARG_BLOCK_ID);
+
         mDisplayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
+        if (TextUtils.isEmpty(mNormalizedNumber)) {
+            String number = getArguments().getString(ARG_NUMBER);
+            String countryIso = getArguments().getString(ARG_COUNTRY_ISO);
+            mNormalizedNumber =
+                    FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
+        }
 
         mHandler = new FilteredNumberAsyncQueryHandler(getContext().getContentResolver());
         mParentView = getActivity().findViewById(getArguments().getInt(ARG_PARENT_VIEW_ID));
@@ -136,6 +146,18 @@
     }
 
     @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        String number = getArguments().getString(ARG_NUMBER);
+        if (TextUtils.isEmpty(mNormalizedNumber) ||
+                !FilteredNumbersUtil.canBlockNumber(getActivity(), number)) {
+            dismiss();
+            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
+                    Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    @Override
     public void onPause() {
         // Dismiss on rotation.
         dismiss();
diff --git a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
index 56417e1..0e162ac 100644
--- a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
+++ b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
@@ -15,14 +15,19 @@
  */
 package com.android.dialer.filterednumber;
 
-import android.content.Context;
 import android.content.ContentValues;
+import android.content.Context;
 import android.database.Cursor;
 import android.os.AsyncTask;
-import android.provider.ContactsContract.Data;
+import android.preference.PreferenceManager;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
+import android.util.Log;
 import android.widget.Toast;
 
 import java.util.LinkedList;
@@ -30,13 +35,16 @@
 
 import com.android.dialer.R;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberContract.FilteredNumber;
+import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
 
 /**
- * Utility to help with tasks related to importing filtered numbers, namely migrating the
- * SEND_TO_VOICEMAIL from Contacts.
+ * Utility to help with tasks related to filtered numbers.
  */
 public class FilteredNumbersUtil {
 
+    private static final String HIDE_BLOCKED_CALLS_PREF_KEY = "hide_blocked_calls";
+
     public interface CheckForSendToVoicemailContactListener {
         public void onComplete(boolean hasSendToVoicemailContact);
     }
@@ -178,4 +186,68 @@
         };
         task.execute();
     }
+
+     /**
+     * WARNING: This method should NOT be executed on the UI thread.
+     * Use {@code FilteredNumberAsyncQueryHandler} to asynchronously check if a number is blocked.
+     */
+    public static boolean isBlocked(Context context, String number, String countryIso) {
+        final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
+        if (TextUtils.isEmpty(normalizedNumber)) {
+            return false;
+        }
+
+        final Cursor cursor = context.getContentResolver().query(
+                FilteredNumber.CONTENT_URI,
+                new String[] { FilteredNumberColumns._ID },
+                FilteredNumberColumns.NORMALIZED_NUMBER + "=?",
+                new String[] { normalizedNumber },
+                null);
+
+        boolean isBlocked = false;
+        if (cursor != null) {
+            try {
+                isBlocked = cursor.getCount() > 0;
+            } finally {
+                cursor.close();
+            }
+        }
+
+        return isBlocked;
+    }
+
+    public static boolean shouldHideBlockedCalls(Context context) {
+        if (context == null) {
+            return false;
+        }
+        return PreferenceManager.getDefaultSharedPreferences(context)
+                .getBoolean(FilteredNumbersUtil.HIDE_BLOCKED_CALLS_PREF_KEY, false);
+    }
+
+    public static void setShouldHideBlockedCalls(Context context, boolean shouldHide) {
+        if (context == null) {
+            return;
+        }
+        PreferenceManager.getDefaultSharedPreferences(context)
+                .edit()
+                .putBoolean(FilteredNumbersUtil.HIDE_BLOCKED_CALLS_PREF_KEY, shouldHide)
+                .apply();
+    }
+
+    public static boolean canBlockNumber(Context context, String number) {
+        if (PhoneNumberUtils.isEmergencyNumber(number)) {
+            return false;
+        }
+
+        TelecomManager telecomManager =
+                (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
+        List<PhoneAccountHandle> phoneAccountHandles = telecomManager.getCallCapablePhoneAccounts();
+        for (PhoneAccountHandle phoneAccountHandle : phoneAccountHandles) {
+            if (telecomManager.isVoiceMailNumber(phoneAccountHandle, number)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
 }
diff --git a/src/com/android/dialer/filterednumber/NumberAdapter.java b/src/com/android/dialer/filterednumber/NumberAdapter.java
new file mode 100644
index 0000000..b212fa3
--- /dev/null
+++ b/src/com/android/dialer/filterednumber/NumberAdapter.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 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.dialer.filterednumber;
+
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.ContactsContract;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.QuickContactBadge;
+import android.widget.SimpleCursorAdapter;
+import android.widget.TextView;
+
+import com.android.contacts.common.ContactPhotoManager;
+import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
+import com.android.contacts.common.util.UriUtils;
+import com.android.dialer.R;
+import com.android.dialer.calllog.ContactInfo;
+import com.android.dialer.calllog.ContactInfoHelper;
+import com.android.dialer.util.PhoneNumberUtil;
+
+public class NumberAdapter extends SimpleCursorAdapter {
+
+    private Context mContext;
+    private FragmentManager mFragmentManager;
+    private ContactInfoHelper mContactInfoHelper;
+    private Resources mResources;
+    private BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
+    private ContactPhotoManager mContactPhotoManager;
+
+    public NumberAdapter(
+            Context context,
+            FragmentManager fragmentManager,
+            ContactInfoHelper contactInfoHelper,
+            ContactPhotoManager contactPhotoManager) {
+        super(context, R.layout.blocked_number_item, null, new String[]{}, new int[]{}, 0);
+        mContext = context;
+        mFragmentManager = fragmentManager;
+        mContactInfoHelper = contactInfoHelper;
+        mContactPhotoManager = contactPhotoManager;
+    }
+
+    public void updateView(View view, String number, String countryIso) {
+        final TextView callerName = (TextView) view.findViewById(R.id.caller_name);
+        final TextView callerNumber = (TextView) view.findViewById(R.id.caller_number);
+        final QuickContactBadge quickContactBadge =
+                (QuickContactBadge) view.findViewById(R.id.quick_contact_photo);
+        quickContactBadge.setOverlay(null);
+        quickContactBadge.setPrioritizedMimeType(
+                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
+
+        final ContactInfo info = mContactInfoHelper.lookupNumber(number, countryIso);
+        final CharSequence locationOrType = getNumberTypeOrLocation(info);
+        final String displayNumber = getDisplayNumber(info);
+        final String displayNumberStr = mBidiFormatter.unicodeWrap(
+                displayNumber.toString(), TextDirectionHeuristics.LTR);
+
+        String nameForDefaultImage;
+        if (!TextUtils.isEmpty(info.name)) {
+            nameForDefaultImage = info.name;
+            callerName.setText(info.name);
+            callerNumber.setText(locationOrType + " " + displayNumberStr);
+        } else {
+            nameForDefaultImage = displayNumber;
+            callerName.setText(displayNumberStr);
+            if (!TextUtils.isEmpty(locationOrType)) {
+                callerNumber.setText(locationOrType);
+                callerNumber.setVisibility(View.VISIBLE);
+            } else {
+                callerNumber.setVisibility(View.GONE);
+            }
+        }
+        loadContactPhoto(info, nameForDefaultImage, quickContactBadge);
+    }
+
+    private void loadContactPhoto(ContactInfo info, String displayName, QuickContactBadge badge) {
+        final String lookupKey = info.lookupUri == null
+                ? null : UriUtils.getLookupKeyFromUri(info.lookupUri);
+        final int contactType = mContactInfoHelper.isBusiness(info.sourceType)
+                ? ContactPhotoManager.TYPE_BUSINESS : ContactPhotoManager.TYPE_DEFAULT;
+        final DefaultImageRequest request = new DefaultImageRequest(displayName, lookupKey,
+                contactType, true /* isCircular */);
+        badge.assignContactUri(info.lookupUri);
+        badge.setContentDescription(
+                mContext.getResources().getString(R.string.description_contact_details, displayName));
+        mContactPhotoManager.loadDirectoryPhoto(badge, info.photoUri,
+                false /* darkTheme */, true /* isCircular */, request);
+    }
+
+    private String getDisplayNumber(ContactInfo info) {
+        if (!TextUtils.isEmpty(info.formattedNumber)) {
+            return info.formattedNumber;
+        } else if (!TextUtils.isEmpty(info.number)) {
+            return info.number;
+        } else {
+            return "";
+        }
+    }
+
+    private CharSequence getNumberTypeOrLocation(ContactInfo info) {
+        if (!TextUtils.isEmpty(info.name)) {
+            return ContactsContract.CommonDataKinds.Phone.getTypeLabel(
+                    mContext.getResources(), info.type, info.label);
+        } else {
+            return PhoneNumberUtil.getGeoDescription(mContext, info.number);
+        }
+    }
+
+    protected Context getContext() {
+        return mContext;
+    }
+
+    protected FragmentManager getFragmentManager() {
+        return mFragmentManager;
+    }
+}
diff --git a/src/com/android/dialer/list/BlockedListSearchFragment.java b/src/com/android/dialer/list/BlockedListSearchFragment.java
index ae64057..498994f 100644
--- a/src/com/android/dialer/list/BlockedListSearchFragment.java
+++ b/src/com/android/dialer/list/BlockedListSearchFragment.java
@@ -87,20 +87,13 @@
 
     private void blockNumber(final String number) {
         final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
-        final String normalizedNumber =
-                FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
-        if (normalizedNumber == null) {
-            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
-                    Toast.LENGTH_SHORT).show();
-            return;
-        }
         final OnCheckBlockedListener onCheckListener = new OnCheckBlockedListener() {
             @Override
             public void onCheckComplete(Integer id) {
                 if (id == null) {
                     FilterNumberDialogFragment.show(
                             id,
-                            normalizedNumber,
+                            null,
                             number,
                             countryIso,
                             number,
@@ -113,8 +106,12 @@
                 }
             }
         };
-        mFilteredNumberAsyncQueryHandler.startBlockedQuery(
-                onCheckListener, normalizedNumber, number, countryIso);
+        boolean failed = mFilteredNumberAsyncQueryHandler.startBlockedQuery(
+                onCheckListener, null, number, countryIso);
+        if (failed) {
+            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
+                    Toast.LENGTH_SHORT).show();
+        }
     }
 
     @Override
@@ -137,14 +134,6 @@
             final ContactListItemView view,
             final String number,
             final Integer blockId) {
-        final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
-        final String normalizedNumber =
-                FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
-        if (normalizedNumber == null) {
-            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
-                    Toast.LENGTH_SHORT).show();
-            return;
-        }
         if (blockId != null) {
             Toast.makeText(getContext(), getString(R.string.alreadyBlocked, number),
                     Toast.LENGTH_SHORT).show();
@@ -153,9 +142,9 @@
 
         FilterNumberDialogFragment.show(
                 blockId,
-                normalizedNumber,
+                null,
                 number,
-                countryIso,
+                GeoUtil.getCurrentCountryIso(getContext()),
                 number,
                 R.id.blocked_numbers_activity_container,
                 getFragmentManager(),
diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
index 3a79695..bdd5dc5 100644
--- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
@@ -134,6 +134,9 @@
 
         assertEquals(Calls.PRESENTATION_RESTRICTED, mViewHolder.numberPresentation);
         assertNull(mViewHolder.primaryActionButtonView.getTag());
+        // QC should be disabled since there are no actions to be performed on this
+        // call.
+        assertFalse(mViewHolder.quickContactView.isEnabled());
     }
 
     @MediumTest
@@ -145,6 +148,9 @@
 
         assertEquals(Calls.PRESENTATION_UNKNOWN, mViewHolder.numberPresentation);
         assertNull(mViewHolder.primaryActionButtonView.getTag());
+        // QC should be disabled since there are no actions to be performed on this
+        // call.
+        assertFalse(mViewHolder.quickContactView.isEnabled());
     }
 
     @MediumTest
@@ -154,7 +160,7 @@
         mAdapter.changeCursor(mCursor);
         mAdapter.onBindViewHolder(mViewHolder, 0);
 
-        assertFalse(mViewHolder.quickContactView.isEnabled());
+        //assertFalse(mViewHolder.quickContactView.isEnabled());
     }
 
     @MediumTest
diff --git a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
index d554ad4..12f32ce 100644
--- a/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogListItemHelperTest.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 
 import com.android.contacts.common.CallUtil;
@@ -30,6 +31,7 @@
 /**
  * Unit tests for {@link CallLogListItemHelper}.
  */
+@MediumTest
 public class CallLogListItemHelperTest extends AndroidTestCase {
     /** A test phone number for phone calls. */
     private static final String TEST_NUMBER = "14125555555";
@@ -273,7 +275,7 @@
 
     /** Asserts that the primary action view does not have a call intent. */
     private void assertNoCallIntent() {
-        Object intentProvider = (IntentProvider)mViewHolder.primaryActionView.getTag();
+        Object intentProvider = mViewHolder.primaryActionView.getTag();
         // The intent provider should be null as there is no ability to make a call.
         assertNull(intentProvider);
     }
diff --git a/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java b/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java
index 45bc598..4d51f72 100644
--- a/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java
+++ b/tests/src/com/android/dialer/calllog/GroupingListAdapterTests.java
@@ -21,6 +21,7 @@
 import android.database.MatrixCursor;
 import android.support.v7.widget.RecyclerView;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
@@ -33,6 +34,7 @@
  *   adb shell am instrument -e class com.android.dialer.calllog.GroupingListAdapterTests \
  *     -w com.android.dialer.tests/android.test.InstrumentationTestRunner
  */
+@MediumTest
 public class GroupingListAdapterTests extends AndroidTestCase {
 
     static private final String[] PROJECTION = new String[] {
@@ -161,6 +163,6 @@
     private void assertMetadata(int listPosition, int groupSize, String objectValue) {
         assertEquals(groupSize, mAdapter.getGroupSize(listPosition));
         MatrixCursor cursor = (MatrixCursor) mAdapter.getItem(listPosition);
-        assertEquals(objectValue, (String) cursor.getString(GROUPING_COLUMN_INDEX));
+        assertEquals(objectValue, cursor.getString(GROUPING_COLUMN_INDEX));
     }
 }
diff --git a/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java b/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java
index b255edf..ecbb898 100644
--- a/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/dialer/calllog/PhoneCallDetailsHelperTest.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.text.Html;
 import android.text.Spanned;
 import android.view.View;
@@ -34,8 +35,9 @@
 import java.util.Locale;
 
 /**
- * Unit tests for {@link PhoneCallDetailsHelper}.m
+ * Unit tests for {@link PhoneCallDetailsHelper}.
  */
+@MediumTest
 public class PhoneCallDetailsHelperTest extends AndroidTestCase {
     /** The number to be used to access the voicemail. */
     private static final String TEST_VOICEMAIL_NUMBER = "125";
diff --git a/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java b/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java
index c8d6403..1191560 100644
--- a/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java
+++ b/tests/src/com/android/dialer/database/FilteredNumberProviderTest.java
@@ -24,7 +24,9 @@
 import android.database.DatabaseUtils;
 import android.net.Uri;
 import android.test.ProviderTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
 
+@MediumTest
 public class FilteredNumberProviderTest extends
         ProviderTestCase2<FilteredNumberProviderTest.TestFilteredNumberProvider> {
     private ContentResolver mResolver;
diff --git a/tests/src/com/android/dialer/filterednumber/FilteredNumbersUtilTest.java b/tests/src/com/android/dialer/filterednumber/FilteredNumbersUtilTest.java
new file mode 100644
index 0000000..a212e0f
--- /dev/null
+++ b/tests/src/com/android/dialer/filterednumber/FilteredNumbersUtilTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.dialer.filterednumber;
+
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.LinkedList;
+
+@SmallTest
+public class FilteredNumbersUtilTest extends AndroidTestCase {
+
+    private static final String NORMAL_PHONE_NUMBER = "555-555-5555";
+    private static final String VOICEMAIL_NUMBER = "*555";
+
+    @Mock private Context mContext;
+    @Mock private TelecomManager mTelecomManager;
+    private PhoneAccountHandle mHandle;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager);
+
+        LinkedList<PhoneAccountHandle> handles = new LinkedList<PhoneAccountHandle>();
+        mHandle = new PhoneAccountHandle(new ComponentName(getContext(), "TestCase"), "0");
+        handles.add(mHandle);
+
+        when(mTelecomManager.getCallCapablePhoneAccounts()).thenReturn(handles);
+    }
+
+    public void testCanBlockNormalNumber() {
+        assertTrue(FilteredNumbersUtil.canBlockNumber(mContext, NORMAL_PHONE_NUMBER));
+    }
+
+    public void testCannotBlockVoicemailNumber() {
+        when(mTelecomManager.isVoiceMailNumber(Matchers.eq(mHandle), Matchers.anyString()))
+                .thenReturn(true);
+        assertFalse(FilteredNumbersUtil.canBlockNumber(mContext, VOICEMAIL_NUMBER));
+    }
+}
diff --git a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
index c2069bd..d0547bd 100644
--- a/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
+++ b/tests/src/com/android/dialer/list/PhoneFavoritesTileAdapterTest.java
@@ -4,6 +4,7 @@
 import android.database.MatrixCursor;
 import android.provider.ContactsContract.PinnedPositions;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.contacts.common.ContactTileLoaderFactory;
 import com.android.contacts.common.list.ContactEntry;
@@ -11,6 +12,7 @@
 
 import java.util.ArrayList;
 
+@SmallTest
 public class PhoneFavoritesTileAdapterTest extends AndroidTestCase {
     private PhoneFavoritesTileAdapter mAdapter;
     private static final OnDataSetChangedForAnimationListener
diff --git a/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java b/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java
index 26e513f..5e6544f 100644
--- a/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java
+++ b/tests/src/com/android/dialer/onboard/DefaultDialerOnboardScreenTest.java
@@ -18,12 +18,14 @@
 import static org.mockito.Mockito.when;
 
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.dialer.onboard.OnboardingActivity.DefaultDialerOnboardingScreen;
 
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+@SmallTest
 public class DefaultDialerOnboardScreenTest extends AndroidTestCase {
     private DefaultDialerOnboardingScreen mScreen;
     @Mock private PermissionsChecker mPermissionsChecker;
diff --git a/tests/src/com/android/dialer/onboard/OnboardingControllerTest.java b/tests/src/com/android/dialer/onboard/OnboardingControllerTest.java
index 3ca39a7..d634855 100644
--- a/tests/src/com/android/dialer/onboard/OnboardingControllerTest.java
+++ b/tests/src/com/android/dialer/onboard/OnboardingControllerTest.java
@@ -17,8 +17,10 @@
 
 import android.app.Activity;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.test.suitebuilder.annotation.Suppress;
 
+@SmallTest
 public class OnboardingControllerTest extends AndroidTestCase {
     private MockOnboardUi mOnboardUi;
     private OnboardingController mController;
diff --git a/tests/src/com/android/dialer/onboard/PermissionsOnboardScreenTest.java b/tests/src/com/android/dialer/onboard/PermissionsOnboardScreenTest.java
index ff5e3d5..4c5ea33 100644
--- a/tests/src/com/android/dialer/onboard/PermissionsOnboardScreenTest.java
+++ b/tests/src/com/android/dialer/onboard/PermissionsOnboardScreenTest.java
@@ -18,12 +18,14 @@
 import static org.mockito.Mockito.when;
 
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.dialer.onboard.OnboardingActivity.PermissionsOnboardingScreen;
 
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+@SmallTest
 public class PermissionsOnboardScreenTest extends AndroidTestCase {
     private PermissionsOnboardingScreen mScreen;
     @Mock private PermissionsChecker mPermissionsChecker;