Merge "Remove unnecessary log statement" into ub-contactsdialer-a-dev
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/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..43f734d 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
@@ -44,7 +44,8 @@
         super.onActivityCreated(savedInstanceState);
 
         if (mAdapter == null) {
-            mAdapter = new BlockedNumberAdapter(getContext());
+            mAdapter = BlockedNumberAdapter.newBlockedNumberAdapter(
+                    getContext(), getActivity().getFragmentManager());
         }
         setListAdapter(mAdapter);
 
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;
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;
+    }
+}