summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/blocking
diff options
context:
space:
mode:
authorAndroid Dialer <noreply@google.com>2018-06-01 17:24:39 -0700
committerCopybara-Service <copybara-piper@google.com>2018-06-01 18:21:50 -0700
commita2aa5f3097fe3ca8e64a378095260448a29f5c5f (patch)
tree40c597ed4397c3687c807d21b30076c6c7d64fb1 /java/com/android/dialer/blocking
parent836b75d30853816739a0db0b69a34d03fd850b6b (diff)
Internal change
Bug: 79169954 Test: added tests in BlockingTest.java PiperOrigin-RevId: 198950042 Change-Id: I380bc93276223db74b87f94140bd6c5c29c3f3cb
Diffstat (limited to 'java/com/android/dialer/blocking')
-rw-r--r--java/com/android/dialer/blocking/Blocking.java177
1 files changed, 127 insertions, 50 deletions
diff --git a/java/com/android/dialer/blocking/Blocking.java b/java/com/android/dialer/blocking/Blocking.java
index e86d0a6ac..a1d8b4fb3 100644
--- a/java/com/android/dialer/blocking/Blocking.java
+++ b/java/com/android/dialer/blocking/Blocking.java
@@ -16,14 +16,27 @@
package com.android.dialer.blocking;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.os.RemoteException;
+import android.provider.BlockedNumberContract;
import android.provider.BlockedNumberContract.BlockedNumbers;
import android.support.annotation.Nullable;
import android.telephony.PhoneNumberUtils;
+import android.util.ArrayMap;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.database.Selection;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
/** Blocks and unblocks number. */
public final class Blocking {
@@ -47,7 +60,7 @@ public final class Blocking {
}
/**
- * Block a number.
+ * Block a list of numbers.
*
* @param countryIso the current location used to guess the country code of the number if not
* available. If {@code null} and {@code number} does not have a country code, only the
@@ -55,29 +68,31 @@ public final class Blocking {
* @throws BlockingFailedException in the returned future if the operation failed.
*/
public static ListenableFuture<Void> block(
- Context context,
- ListeningExecutorService executorService,
- String number,
- @Nullable String countryIso) {
- return executorService.submit(
- () -> {
- ContentValues values = new ContentValues();
- values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number);
- String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso);
- if (e164Number != null) {
- values.put(BlockedNumbers.COLUMN_E164_NUMBER, e164Number);
- }
- try {
- context.getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
- } catch (SecurityException e) {
- throw new BlockingFailedException(e);
- }
- return null;
- });
+ Context context, ImmutableCollection<String> numbers, @Nullable String countryIso) {
+ return DialerExecutorComponent.get(context)
+ .backgroundExecutor()
+ .submit(
+ () -> {
+ ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+ for (String number : numbers) {
+ ContentValues values = new ContentValues();
+ values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number);
+ String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso);
+ if (e164Number != null) {
+ values.put(BlockedNumbers.COLUMN_E164_NUMBER, e164Number);
+ }
+ operations.add(
+ ContentProviderOperation.newInsert(BlockedNumbers.CONTENT_URI)
+ .withValues(values)
+ .build());
+ }
+ applyBatchOps(context.getContentResolver(), operations);
+ return null;
+ });
}
/**
- * Unblock a number.
+ * Unblock a list of number.
*
* @param countryIso the current location used to guess the country code of the number if not
* available. If {@code null} and {@code number} does not have a country code, only the
@@ -85,33 +100,95 @@ public final class Blocking {
* @throws BlockingFailedException in the returned future if the operation failed.
*/
public static ListenableFuture<Void> unblock(
- Context context,
- ListeningExecutorService executorService,
- String number,
- @Nullable String countryIso) {
- return executorService.submit(
- () -> {
- Selection selection =
- Selection.column(BlockedNumbers.COLUMN_ORIGINAL_NUMBER).is("=", number);
- String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso);
- if (e164Number != null) {
- selection =
- selection
- .buildUpon()
- .or(Selection.column(BlockedNumbers.COLUMN_E164_NUMBER).is("=", e164Number))
- .build();
- }
- try {
- context
- .getContentResolver()
- .delete(
- BlockedNumbers.CONTENT_URI,
- selection.getSelection(),
- selection.getSelectionArgs());
- } catch (SecurityException e) {
- throw new BlockingFailedException(e);
- }
- return null;
- });
+ Context context, ImmutableCollection<String> numbers, @Nullable String countryIso) {
+ return DialerExecutorComponent.get(context)
+ .backgroundExecutor()
+ .submit(
+ () -> {
+ ArrayList<ContentProviderOperation> operations = new ArrayList<>();
+ for (String number : numbers) {
+ Selection selection =
+ Selection.column(BlockedNumbers.COLUMN_ORIGINAL_NUMBER).is("=", number);
+ String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso);
+ if (e164Number != null) {
+ selection =
+ selection
+ .buildUpon()
+ .or(
+ Selection.column(BlockedNumbers.COLUMN_E164_NUMBER)
+ .is("=", e164Number))
+ .build();
+ }
+ operations.add(
+ ContentProviderOperation.newDelete(BlockedNumbers.CONTENT_URI)
+ .withSelection(selection.getSelection(), selection.getSelectionArgs())
+ .build());
+ }
+ applyBatchOps(context.getContentResolver(), operations);
+ return null;
+ });
+ }
+
+ /**
+ * Get blocked numbers from a list of number.
+ *
+ * @param countryIso the current location used to guess the country code of the number if not
+ * available. If {@code null} and {@code number} does not have a country code, only the
+ * original number will be used to check blocked status.
+ * @throws BlockingFailedException in the returned future if the operation failed.
+ */
+ public static ListenableFuture<ImmutableMap<String, Boolean>> isBlocked(
+ Context context, ImmutableCollection<String> numbers, @Nullable String countryIso) {
+ return DialerExecutorComponent.get(context)
+ .backgroundExecutor()
+ .submit(
+ () -> {
+ Map<String, Boolean> blockedStatus = new ArrayMap<>();
+ List<String> e164Numbers = new ArrayList<>();
+
+ for (String number : numbers) {
+ // Initialize as unblocked
+ blockedStatus.put(number, false);
+ String e164Number = PhoneNumberUtils.formatNumberToE164(number, countryIso);
+ if (e164Number != null) {
+ e164Numbers.add(e164Number);
+ }
+ }
+
+ Selection selection =
+ Selection.builder()
+ .or(Selection.column(BlockedNumbers.COLUMN_ORIGINAL_NUMBER).in(numbers))
+ .or(Selection.column(BlockedNumbers.COLUMN_E164_NUMBER).in(e164Numbers))
+ .build();
+
+ try (Cursor cursor =
+ context
+ .getContentResolver()
+ .query(
+ BlockedNumbers.CONTENT_URI,
+ new String[] {BlockedNumbers.COLUMN_ORIGINAL_NUMBER},
+ selection.getSelection(),
+ selection.getSelectionArgs(),
+ null)) {
+ if (cursor == null) {
+ return ImmutableMap.copyOf(blockedStatus);
+ }
+ while (cursor.moveToNext()) {
+ // Update blocked status
+ blockedStatus.put(cursor.getString(0), true);
+ }
+ }
+ return ImmutableMap.copyOf(blockedStatus);
+ });
+ }
+
+ private static ContentProviderResult[] applyBatchOps(
+ ContentResolver resolver, ArrayList<ContentProviderOperation> ops)
+ throws BlockingFailedException {
+ try {
+ return resolver.applyBatch(BlockedNumberContract.AUTHORITY, ops);
+ } catch (RemoteException | OperationApplicationException | SecurityException e) {
+ throw new BlockingFailedException(e);
+ }
}
}