Don't allow blocking of emergency or VM numbers.

Bug: 24680730
Bug: 24303461
Change-Id: Ibd7d431355ca97eb2ae7f29537809987a8d5f96d
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 54367b1..ef21980 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;
         }
 
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/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
index 1e5294c..affb37b 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..4a50a49 100644
--- a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
+++ b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
@@ -15,13 +15,16 @@
  */
 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.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.widget.Toast;
 
@@ -32,8 +35,7 @@
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
 
 /**
- * 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 {
 
@@ -178,4 +180,21 @@
         };
         task.execute();
     }
+
+    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/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/filterednumber/FilteredNumbersUtilTest.java b/tests/src/com/android/dialer/filterednumber/FilteredNumbersUtilTest.java
new file mode 100644
index 0000000..8011755
--- /dev/null
+++ b/tests/src/com/android/dialer/filterednumber/FilteredNumbersUtilTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.LinkedList;
+
+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));
+    }
+}