summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/layout/blocked_number_fragment.xml25
-rw-r--r--res/layout/blocked_number_header.xml9
-rw-r--r--res/values/strings.xml7
-rw-r--r--src/com/android/dialer/CallDetailActivity.java142
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java4
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViewHolder.java36
-rw-r--r--src/com/android/dialer/calllog/DefaultVoicemailNotifier.java49
-rw-r--r--src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java8
-rw-r--r--src/com/android/dialer/filterednumber/BlockedNumberFragment.java82
-rw-r--r--src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java40
-rw-r--r--src/com/android/dialer/filterednumber/FilteredNumbersUtil.java232
-rw-r--r--src/com/android/dialer/list/BlockedListSearchFragment.java29
-rw-r--r--tests/src/com/android/dialer/filterednumber/FilteredNumbersUtilTest.java66
13 files changed, 530 insertions, 199 deletions
diff --git a/res/layout/blocked_number_fragment.xml b/res/layout/blocked_number_fragment.xml
index e86ccb596..bb4b7f20f 100644
--- a/res/layout/blocked_number_fragment.xml
+++ b/res/layout/blocked_number_fragment.xml
@@ -27,23 +27,22 @@
android:layout_height="wrap_content"
card_view:cardCornerRadius="0dp">
- <ListView android:id="@id/android:list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/background_dialer_white"
- android:layout_weight="1"
- android:drawSelectorOnTop="false"
- android:headerDividersEnabled="false" />
-
<LinearLayout
- android:id="@android:id/empty"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/background_dialer_white">
<include layout="@layout/blocked_number_header" />
- <TextView android:id="@id/android:empty"
+ <ListView android:id="@id/android:list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"
+ android:headerDividersEnabled="false" />
+
+ <TextView android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="@dimen/blocked_number_horizontal_margin"
diff --git a/res/layout/blocked_number_header.xml b/res/layout/blocked_number_header.xml
index 95880a7c0..39f532281 100644
--- a/res/layout/blocked_number_header.xml
+++ b/res/layout/blocked_number_header.xml
@@ -13,10 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/textView"
android:layout_width="wrap_content"
@@ -26,7 +23,7 @@
android:padding="@dimen/blocked_number_container_padding"
style="@android:style/TextAppearance.Material.Subhead" />
- <RelativeLayout android:id="@+id/importsettings"
+ <RelativeLayout android:id="@+id/import_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
@@ -77,4 +74,4 @@
android:layout_marginTop="8dp"
android:text="@string/blockNumber" />
-</LinearLayout>
+</merge>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cd7ce8fa8..0b7d82c61 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -833,7 +833,7 @@
You previously marked some callers to be automatically sent to voicemail via other apps.
</string>
- <!-- Labe for button to view numbers of contacts previous marked to be sent to voicemail.
+ <!-- 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>
@@ -841,6 +841,9 @@
list. [CHAR_LIMIT=20] -->
<string name="blocked_call_settings_import_button">Import</string>
+ <!-- Error toast message for when send to voicemail import fails. [CHAR LIMIT=40] -->
+ <string name="send_to_voicemail_import_failed">Import failed</string>
+
<!-- String describing the delete icon on a blocked number list item.
When tapped, it will show a dialog confirming the unblocking of the number.
[CHAR LIMIT=NONE]-->
@@ -853,7 +856,7 @@
<!-- Button to bring up UI to add a number to the blocked call list. [CHAR LIMIT=40] -->
<string name="blockNumber">Add number</string>
- <!-- Heading for the block list in the "Spam and blocked calls" settings. [CHAR LIMIT=64] -->
+ <!-- Heading for the block list in the "Spam and blocked cal)ls" settings. [CHAR LIMIT=64] -->
<string name="blockList">Block list</string>
<!-- Label for progress dialog when validating a number to be added to the block list.
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 654a96fcf..ef219800f 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -49,14 +49,15 @@ import com.android.contacts.common.testing.NeededForTesting;
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;
@@ -106,17 +107,9 @@ public class CallDetailActivity extends AppCompatActivity
// All calls are from the same number and same contact, so pick the first detail.
mDetails = details[0];
- mNumber = TextUtils.isEmpty(mDetails.number) ?
- null : mDetails.number.toString();
+ mNumber = TextUtils.isEmpty(mDetails.number) ? null : mDetails.number.toString();
mDisplayNumber = mDetails.displayNumber;
final int numberPresentation = mDetails.numberPresentation;
- final Uri contactUri = mDetails.contactUri;
- final Uri photoUri = mDetails.photoUri;
- final PhoneAccountHandle accountHandle = mDetails.accountHandle;
-
- // Cache the details about the phone number.
- mIsVoicemailNumber =
- PhoneNumberUtil.isVoicemailNumber(mContext, accountHandle, mNumber);
final CharSequence callLocationOrType = getNumberTypeOrLocation(mDetails);
@@ -137,7 +130,8 @@ public class CallDetailActivity extends AppCompatActivity
}
}
- String accountLabel = PhoneAccountUtils.getAccountLabel(mContext, accountHandle);
+ String accountLabel =
+ PhoneAccountUtils.getAccountLabel(mContext, mDetails.accountHandle);
if (!TextUtils.isEmpty(accountLabel)) {
mAccountLabel.setText(accountLabel);
mAccountLabel.setVisibility(View.VISIBLE);
@@ -150,8 +144,10 @@ public class CallDetailActivity extends AppCompatActivity
mCallButton.setVisibility(canPlaceCallsTo ? View.VISIBLE : View.GONE);
final boolean isSipNumber = PhoneNumberUtil.isSipNumber(mNumber);
+ final boolean isVoicemailNumber =
+ PhoneNumberUtil.isVoicemailNumber(mContext, mDetails.accountHandle, mNumber);
final boolean showEditNumberBeforeCallAction =
- canPlaceCallsTo && !isSipNumber && !mIsVoicemailNumber;
+ canPlaceCallsTo && !isSipNumber && !isVoicemailNumber;
mEditBeforeCallActionItem.setVisibility(
showEditNumberBeforeCallAction ? View.VISIBLE : View.GONE);
@@ -160,31 +156,13 @@ public class CallDetailActivity extends AppCompatActivity
mReportActionItem.setVisibility(
showReportAction ? View.VISIBLE : View.GONE);
- updateBlockActionItem();
invalidateOptionsMenu();
mHistoryList.setAdapter(
new CallDetailHistoryAdapter(mContext, mInflater, mCallTypeHelper, details));
- String lookupKey = contactUri == null ? null
- : UriUtils.getLookupKeyFromUri(contactUri);
-
- final boolean isBusiness = mContactInfoHelper.isBusiness(mDetails.sourceType);
+ updatePhotoAndBlockActionItem();
- final int contactType =
- mIsVoicemailNumber ? ContactPhotoManager.TYPE_VOICEMAIL :
- isBusiness ? ContactPhotoManager.TYPE_BUSINESS :
- ContactPhotoManager.TYPE_DEFAULT;
-
- String nameForDefaultImage;
- if (TextUtils.isEmpty(mDetails.name)) {
- nameForDefaultImage = mDetails.displayNumber;
- } else {
- nameForDefaultImage = mDetails.name.toString();
- }
-
- loadContactPhotos(
- contactUri, photoUri, nameForDefaultImage, lookupKey, contactType);
findViewById(R.id.call_detail).setVisibility(View.VISIBLE);
}
@@ -217,7 +195,6 @@ public class CallDetailActivity extends AppCompatActivity
private PhoneCallDetails mDetails;
protected String mNumber;
private Uri mVoicemailUri;
- private boolean mIsVoicemailNumber;
private String mDefaultCountryIso;
private String mDisplayNumber;
@@ -275,6 +252,9 @@ public class CallDetailActivity extends AppCompatActivity
mCallButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
+ if (TextUtils.isEmpty(mNumber)) {
+ return;
+ }
mContext.startActivity(
new CallIntentBuilder(mNumber)
.setCallInitiationType(LogState.INITIATION_CALL_DETAILS)
@@ -339,21 +319,6 @@ public class CallDetailActivity extends AppCompatActivity
return uris;
}
- /** Load the contact photos and places them in the corresponding views. */
- private void loadContactPhotos(Uri contactUri, Uri photoUri, String displayName,
- String lookupKey, int contactType) {
-
- final DefaultImageRequest request = new DefaultImageRequest(displayName, lookupKey,
- contactType, true /* isCircular */);
-
- mQuickContactBadge.assignContactUri(contactUri);
- mQuickContactBadge.setContentDescription(
- mResources.getString(R.string.description_contact_details, displayName));
-
- mContactPhotoManager.loadDirectoryPhoto(mQuickContactBadge, photoUri,
- false /* darkTheme */, true /* isCircular */, request);
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
final MenuItem deleteMenuItem = menu.add(
@@ -399,7 +364,7 @@ public class CallDetailActivity extends AppCompatActivity
mBlockedNumberId,
null /* normalizedNumber */,
mNumber,
- null /* countryIso */,
+ mDetails.countryIso,
mDisplayNumber,
R.id.call_detail,
getFragmentManager(),
@@ -420,32 +385,81 @@ public class CallDetailActivity extends AppCompatActivity
@Override
public void onChangeFilteredNumberSuccess() {
- updateBlockActionItem();
+ updatePhotoAndBlockActionItem();
}
@Override
public void onChangeFilteredNumberUndo() {
- updateBlockActionItem();
+ updatePhotoAndBlockActionItem();
}
- private void updateBlockActionItem() {
+ private void updatePhotoAndBlockActionItem() {
+ if (mDetails == null || !FilteredNumbersUtil.canBlockNumber(this, mNumber)) {
+ return;
+ }
+
+ boolean failed = mFilteredNumberAsyncQueryHandler.startBlockedQuery(
+ new OnCheckBlockedListener() {
+ @Override
+ public void onCheckComplete(Integer id) {
+ mBlockedNumberId = id;
+
+ updateContactPhoto();
+ updateBlockActionItem();
+ }
+ }, null, mNumber, mDetails.countryIso);
+
+ if (failed) {
+ updateContactPhoto();
+ updateBlockActionItem();
+ }
+ }
+
+ // Loads and displays the contact photo.
+ private void updateContactPhoto() {
if (mDetails == null) {
return;
}
- mFilteredNumberAsyncQueryHandler.startBlockedQuery(new OnCheckBlockedListener() {
- @Override
- public void onCheckComplete(Integer id) {
- mBlockedNumberId = id;
- if (mBlockedNumberId == null) {
- mBlockNumberActionItem.setText(R.string.action_block_number);
- } else {
- mBlockNumberActionItem.setText(R.string.action_unblock_number);
- }
+ if (mBlockedNumberId != null) {
+ mQuickContactBadge.setImageDrawable(mContext.getDrawable(R.drawable.blocked_contact));
+ return;
+ }
- mBlockNumberActionItem.setVisibility(View.VISIBLE);
- }
- }, null, mNumber, mDetails.countryIso);
+ final boolean isVoicemailNumber =
+ PhoneNumberUtil.isVoicemailNumber(mContext, mDetails.accountHandle, mNumber);
+ final boolean isBusiness = mContactInfoHelper.isBusiness(mDetails.sourceType);
+ int contactType = ContactPhotoManager.TYPE_DEFAULT;
+ if (isVoicemailNumber) {
+ contactType = ContactPhotoManager.TYPE_VOICEMAIL;
+ } else if (isBusiness) {
+ contactType = ContactPhotoManager.TYPE_BUSINESS;
+ }
+
+ final String displayName = TextUtils.isEmpty(mDetails.name)
+ ? mDetails.displayNumber : mDetails.name.toString();
+ final String lookupKey = mDetails.contactUri == null
+ ? null : UriUtils.getLookupKeyFromUri(mDetails.contactUri);
+
+ final DefaultImageRequest request =
+ new DefaultImageRequest(displayName, lookupKey, contactType, true /* isCircular */);
+
+ mQuickContactBadge.assignContactUri(mDetails.contactUri);
+ mQuickContactBadge.setContentDescription(
+ mResources.getString(R.string.description_contact_details, displayName));
+
+ mContactPhotoManager.loadDirectoryPhoto(mQuickContactBadge, mDetails.photoUri,
+ false /* darkTheme */, true /* isCircular */, request);
+ }
+
+ private void updateBlockActionItem() {
+ if (mBlockedNumberId == null) {
+ mBlockNumberActionItem.setText(R.string.action_block_number);
+ } else {
+ mBlockNumberActionItem.setText(R.string.action_unblock_number);
+ }
+
+ mBlockNumberActionItem.setVisibility(View.VISIBLE);
}
private void closeSystemDialogs() {
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 7f3a779ea..0ee7e935d 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -314,6 +314,10 @@ public class CallLogAdapter extends GroupingListAdapter
public void onPause() {
pauseCache();
+
+ // Clear blocked id cache so that changes in blocked status will be reflected in the UI.
+ mBlockedIdCache.clear();
+
if (mHiddenItemUri != null) {
CallLogAsyncTaskUtil.deleteVoicemail(mContext, mHiddenItemUri, null);
}
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index 8f2f4ba45..23c77d383 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -27,6 +27,7 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
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.DialtactsActivity;
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 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
.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/DefaultVoicemailNotifier.java b/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java
index 4eb74bd29..594ceebee 100644
--- a/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java
+++ b/src/com/android/dialer/calllog/DefaultVoicemailNotifier.java
@@ -39,9 +39,13 @@ import com.android.contacts.common.util.PermissionsUtil;
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 class DefaultVoicemailNotifier {
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 @@ public class DefaultVoicemailNotifier {
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 @@ public class DefaultVoicemailNotifier {
}
}
+ 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 @@ public class DefaultVoicemailNotifier {
// 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 class DefaultVoicemailNotifier {
public final String accountComponentName;
public final String accountId;
public final String transcription;
+ public final String countryIso;
public NewCall(
Uri callsUri,
@@ -226,7 +244,8 @@ public class DefaultVoicemailNotifier {
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 @@ public class DefaultVoicemailNotifier {
this.accountComponentName = accountComponentName;
this.accountId = accountId;
this.transcription = transcription;
+ this.countryIso = countryIso;
}
}
@@ -242,7 +262,7 @@ public class DefaultVoicemailNotifier {
/**
* 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 @@ public class DefaultVoicemailNotifier {
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 @@ public class DefaultVoicemailNotifier {
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 @@ public class DefaultVoicemailNotifier {
}
@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 @@ public class DefaultVoicemailNotifier {
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 @@ public class DefaultVoicemailNotifier {
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/FilteredNumberAsyncQueryHandler.java b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
index c5d2f6f70..25613a6f8 100644
--- a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
+++ b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
@@ -202,7 +202,9 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler {
new Listener() {
@Override
public void onInsertComplete(int token, Object cookie, Uri uri) {
- listener.onBlockComplete(uri);
+ if (listener != null ) {
+ listener.onBlockComplete(uri);
+ }
}
}, getContentUri(null), values);
}
@@ -241,7 +243,9 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler {
startDelete(NO_TOKEN, new Listener() {
@Override
public void onDeleteComplete(int token, Object cookie, int result) {
- listener.onUnblockComplete(result, values);
+ if (listener != null) {
+ listener.onUnblockComplete(result, values);
+ }
}
}, uri, null, null);
}
diff --git a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
index 10d6ff6ee..43f734d8d 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumberFragment.java
@@ -21,36 +21,28 @@ import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
-import android.os.AsyncTask;
import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.R;
import com.android.dialer.database.FilteredNumberContract;
+import com.android.dialer.filterednumber.FilteredNumbersUtil.CheckForSendToVoicemailContactListener;
+import com.android.dialer.filterednumber.FilteredNumbersUtil.ImportSendToVoicemailContactsListener;
public class BlockedNumberFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor>, View.OnClickListener {
- private static class SendToVoicemailContactQuery {
- static final String[] PROJECTION = {
- Contacts._ID
- };
-
- static final String SELECT_SEND_TO_VOICEMAIL_TRUE = Contacts.SEND_TO_VOICEMAIL + "=1";
- }
-
private BlockedNumberAdapter mAdapter;
+
private View mImportSettings;
+ private View mImportButton;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- LayoutInflater inflater = LayoutInflater.from(getContext());
- getListView().addHeaderView(inflater.inflate(R.layout.blocked_number_header, null));
if (mAdapter == null) {
mAdapter = BlockedNumberAdapter.newBlockedNumberAdapter(
getContext(), getActivity().getFragmentManager());
@@ -58,9 +50,21 @@ public class BlockedNumberFragment extends ListFragment implements
setListAdapter(mAdapter);
getActivity().findViewById(R.id.add_number_button).setOnClickListener(this);
- getListView().getEmptyView().findViewById(R.id.add_number_button).setOnClickListener(this);
- mImportSettings = getActivity().findViewById(R.id.importsettings);
+ mImportSettings = getActivity().findViewById(R.id.import_settings);
+ mImportButton = getActivity().findViewById(R.id.import_button);
+ mImportButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ FilteredNumbersUtil.importSendToVoicemailContacts(
+ getActivity(), new ImportSendToVoicemailContactsListener() {
+ @Override
+ public void onImportComplete() {
+ mImportSettings.setVisibility(View.GONE);
+ }
+ });
+ }
+ });
}
@Override
@@ -78,7 +82,15 @@ public class BlockedNumberFragment extends ListFragment implements
@Override
public void onResume() {
super.onResume();
- checkForSendToVoicemailContact();
+
+ FilteredNumbersUtil.checkForSendToVoicemailContact(
+ getActivity(), new CheckForSendToVoicemailContactListener() {
+ @Override
+ public void onComplete(boolean hasSendToVoicemailContact) {
+ final int visibility = hasSendToVoicemailContact ? View.VISIBLE : View.GONE;
+ mImportSettings.setVisibility(visibility);
+ }
+ });
}
@Override
@@ -122,44 +134,4 @@ public class BlockedNumberFragment extends ListFragment implements
manageBlockedNumbersActivity.enterSearchUi();
}
}
-
- /**
- * Checks if there exists a contact with {@code Contacts.SEND_TO_VOICEMAIL} set to true,
- * and updates the visibility of the import settings buttons accordingly.
- */
- private void checkForSendToVoicemailContact() {
- final AsyncTask task = new AsyncTask<Object, Void, Boolean>() {
- @Override
- public Boolean doInBackground(Object[] params) {
- if (getActivity() == null) {
- return false;
- }
-
- final Cursor cursor = getActivity().getContentResolver().query(
- Contacts.CONTENT_URI,
- SendToVoicemailContactQuery.PROJECTION,
- SendToVoicemailContactQuery.SELECT_SEND_TO_VOICEMAIL_TRUE,
- null,
- null);
-
- boolean hasSendToVoicemailContacts = false;
- if (cursor != null) {
- try {
- hasSendToVoicemailContacts = cursor.getCount() > 0;
- } finally {
- cursor.close();
- }
- }
-
- return hasSendToVoicemailContacts;
- }
-
- @Override
- public void onPostExecute(Boolean hasSendToVoicemailContact) {
- final int visibility = hasSendToVoicemailContact ? View.VISIBLE : View.GONE;
- mImportSettings.setVisibility(visibility);
- }
- };
- task.execute();
- }
}
diff --git a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
index a1260eebf..affb37b15 100644
--- a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
+++ b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
@@ -26,7 +26,9 @@ import android.content.res.Resources;
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 @@ public class FilterNumberDialogFragment extends DialogFragment {
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 class FilterNumberDialogFragment extends DialogFragment {
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 @@ public class FilterNumberDialogFragment extends DialogFragment {
}
@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();
@@ -159,13 +181,14 @@ public class FilterNumberDialogFragment extends DialogFragment {
private void blockNumber() {
final String message = getBlockedMessage();
final String undoMessage = getUnblockedMessage();
+ final Callback callback = mCallback;
final OnUnblockNumberListener onUndoListener = new OnUnblockNumberListener() {
@Override
public void onUnblockComplete(int rows, ContentValues values) {
Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
- if (mCallback != null) {
- mCallback.onChangeFilteredNumberUndo();
+ if (callback != null) {
+ callback.onChangeFilteredNumberUndo();
}
}
};
@@ -185,8 +208,8 @@ public class FilterNumberDialogFragment extends DialogFragment {
.setAction(R.string.block_number_undo, undoListener)
.show();
- if (mCallback != null) {
- mCallback.onChangeFilteredNumberSuccess();
+ if (callback != null) {
+ callback.onChangeFilteredNumberSuccess();
}
}
};
@@ -201,13 +224,14 @@ public class FilterNumberDialogFragment extends DialogFragment {
private void unblockNumber() {
final String message = getUnblockedMessage();
final String undoMessage = getBlockedMessage();
+ final Callback callback = mCallback;
final OnBlockNumberListener onUndoListener = new OnBlockNumberListener() {
@Override
public void onBlockComplete(final Uri uri) {
Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
- if (mCallback != null) {
- mCallback.onChangeFilteredNumberUndo();
+ if (callback != null) {
+ callback.onChangeFilteredNumberUndo();
}
}
};
@@ -227,8 +251,8 @@ public class FilterNumberDialogFragment extends DialogFragment {
.setAction(R.string.block_number_undo, undoListener)
.show();
- if (mCallback != null) {
- mCallback.onChangeFilteredNumberSuccess();
+ if (callback != null) {
+ callback.onChangeFilteredNumberSuccess();
}
}
}, getArguments().getInt(ARG_BLOCK_ID));
diff --git a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
new file mode 100644
index 000000000..68f262cf9
--- /dev/null
+++ b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
@@ -0,0 +1,232 @@
+/*
+ * 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.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.AsyncTask;
+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;
+import java.util.List;
+
+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.
+ */
+public class FilteredNumbersUtil {
+
+ public interface CheckForSendToVoicemailContactListener {
+ public void onComplete(boolean hasSendToVoicemailContact);
+ }
+
+ public interface ImportSendToVoicemailContactsListener {
+ public void onImportComplete();
+ }
+
+ private static class ContactsQuery {
+ static final String[] PROJECTION = {
+ Contacts._ID
+ };
+
+ static final String SELECT_SEND_TO_VOICEMAIL_TRUE = Contacts.SEND_TO_VOICEMAIL + "=1";
+
+ static final int ID_COLUMN_INDEX = 0;
+ }
+
+ private static class PhoneQuery {
+ static final String[] PROJECTION = {
+ Phone.NORMALIZED_NUMBER,
+ Phone.NUMBER
+ };
+
+ static final int NORMALIZED_NUMBER_COLUMN_INDEX = 0;
+ static final int NUMBER_COLUMN_INDEX = 1;
+
+ static final String SELECT_SEND_TO_VOICEMAIL_TRUE = Contacts.SEND_TO_VOICEMAIL + "=1";
+ }
+
+ /**
+ * Checks if there exists a contact with {@code Contacts.SEND_TO_VOICEMAIL} set to true.
+ */
+ public static void checkForSendToVoicemailContact(
+ final Context context, final CheckForSendToVoicemailContactListener listener) {
+ final AsyncTask task = new AsyncTask<Object, Void, Boolean>() {
+ @Override
+ public Boolean doInBackground(Object[] params) {
+ if (context == null) {
+ return false;
+ }
+
+ final Cursor cursor = context.getContentResolver().query(
+ Contacts.CONTENT_URI,
+ ContactsQuery.PROJECTION,
+ ContactsQuery.SELECT_SEND_TO_VOICEMAIL_TRUE,
+ null,
+ null);
+
+ boolean hasSendToVoicemailContacts = false;
+ if (cursor != null) {
+ try {
+ hasSendToVoicemailContacts = cursor.getCount() > 0;
+ } finally {
+ cursor.close();
+ }
+ }
+
+ return hasSendToVoicemailContacts;
+ }
+
+ @Override
+ public void onPostExecute(Boolean hasSendToVoicemailContact) {
+ if (listener != null) {
+ listener.onComplete(hasSendToVoicemailContact);
+ }
+ }
+ };
+ task.execute();
+ }
+
+ /**
+ * Blocks all the phone numbers of any contacts marked as SEND_TO_VOICEMAIL, then clears the
+ * SEND_TO_VOICEMAIL flag on those contacts.
+ */
+ public static void importSendToVoicemailContacts(
+ final Context context, final ImportSendToVoicemailContactsListener listener) {
+ final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler =
+ new FilteredNumberAsyncQueryHandler(context.getContentResolver());
+
+ final AsyncTask task = new AsyncTask<Object, Void, Boolean>() {
+ @Override
+ public Boolean doInBackground(Object[] params) {
+ if (context == null) {
+ return false;
+ }
+
+ // Get the phone number of contacts marked as SEND_TO_VOICEMAIL.
+ final Cursor phoneCursor = context.getContentResolver().query(
+ Phone.CONTENT_URI,
+ PhoneQuery.PROJECTION,
+ PhoneQuery.SELECT_SEND_TO_VOICEMAIL_TRUE,
+ null,
+ null);
+
+ if (phoneCursor == null) {
+ return false;
+ }
+
+ try {
+ while (phoneCursor.moveToNext()) {
+ final String normalizedNumber = phoneCursor.getString(
+ PhoneQuery.NORMALIZED_NUMBER_COLUMN_INDEX);
+ final String number = phoneCursor.getString(
+ PhoneQuery.NUMBER_COLUMN_INDEX);
+ if (normalizedNumber != null) {
+ // Block the phone number of the contact.
+ mFilteredNumberAsyncQueryHandler.blockNumber(
+ null, normalizedNumber, number, null);
+ }
+ }
+ } finally {
+ phoneCursor.close();
+ }
+
+ // Clear SEND_TO_VOICEMAIL on all contacts. The setting has been imported to Dialer.
+ ContentValues newValues = new ContentValues();
+ newValues.put(Contacts.SEND_TO_VOICEMAIL, 0);
+ context.getContentResolver().update(
+ Contacts.CONTENT_URI,
+ newValues,
+ ContactsQuery.SELECT_SEND_TO_VOICEMAIL_TRUE,
+ null);
+
+ return true;
+ }
+
+ @Override
+ public void onPostExecute(Boolean success) {
+ if (success) {
+ if (listener != null) {
+ listener.onImportComplete();
+ }
+ } else if (context != null) {
+ String toastStr = context.getString(R.string.send_to_voicemail_import_failed);
+ Toast.makeText(context, toastStr, Toast.LENGTH_SHORT).show();
+ }
+ }
+ };
+ 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;
+ }
+
+ 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 ae64057da..498994f55 100644
--- a/src/com/android/dialer/list/BlockedListSearchFragment.java
+++ b/src/com/android/dialer/list/BlockedListSearchFragment.java
@@ -87,20 +87,13 @@ public class BlockedListSearchFragment extends RegularSearchFragment
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 @@ public class BlockedListSearchFragment extends RegularSearchFragment
}
}
};
- 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 @@ public class BlockedListSearchFragment extends RegularSearchFragment
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 @@ public class BlockedListSearchFragment extends RegularSearchFragment
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 000000000..801175596
--- /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));
+ }
+}