Disable VM notification for blocked numbers.

+ Added a utility to do a synchronous lookup for whether a number is
blocked, but it should not be used normally from the UI thread.
+ Change voicemail notifier code to obtain countryIso, and pass back
list of calls to notify as list (to make it easier to remove elements).

Bug: 23944007
Change-Id: Iad1f8ee200b8f8734be3db0504482fcdee61e412
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/filterednumber/FilteredNumbersUtil.java b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
index 4a50a49..68f262c 100644
--- a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
+++ b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
@@ -26,6 +26,7 @@
 import android.telecom.TelecomManager;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
+import android.util.Log;
 import android.widget.Toast;
 
 import java.util.LinkedList;
@@ -33,6 +34,8 @@
 
 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 filtered numbers.
@@ -181,6 +184,35 @@
         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 canBlockNumber(Context context, String number) {
         if (PhoneNumberUtils.isEmergencyNumber(number)) {
             return false;