diff options
author | Android Dialer <noreply@google.com> | 2018-06-01 17:24:39 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-06-01 18:21:50 -0700 |
commit | a2aa5f3097fe3ca8e64a378095260448a29f5c5f (patch) | |
tree | 40c597ed4397c3687c807d21b30076c6c7d64fb1 | |
parent | 836b75d30853816739a0db0b69a34d03fd850b6b (diff) |
Internal change
Bug: 79169954
Test: added tests in BlockingTest.java
PiperOrigin-RevId: 198950042
Change-Id: I380bc93276223db74b87f94140bd6c5c29c3f3cb
4 files changed, 134 insertions, 56 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); + } } } diff --git a/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java b/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java index fb0399d9a..28ac7bfcc 100644 --- a/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java +++ b/java/com/android/dialer/blockreportspam/ShowBlockReportSpamDialogReceiver.java @@ -40,6 +40,7 @@ import com.android.dialer.protos.ProtoParsers; import com.android.dialer.spam.Spam; import com.android.dialer.spam.SpamComponent; import com.android.dialer.spam.SpamSettings; +import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -225,8 +226,7 @@ public final class ShowBlockReportSpamDialogReceiver extends BroadcastReceiver { Futures.addCallback( Blocking.block( context, - DialerExecutorComponent.get(context).backgroundExecutor(), - dialogInfo.getNormalizedNumber(), + ImmutableList.of(dialogInfo.getNormalizedNumber()), dialogInfo.getCountryIso()), new FutureCallback<Void>() { @Override @@ -252,8 +252,7 @@ public final class ShowBlockReportSpamDialogReceiver extends BroadcastReceiver { Futures.addCallback( Blocking.unblock( context, - DialerExecutorComponent.get(context).backgroundExecutor(), - dialogInfo.getNormalizedNumber(), + ImmutableList.of(dialogInfo.getNormalizedNumber()), dialogInfo.getCountryIso()), new FutureCallback<Void>() { @Override diff --git a/java/com/android/dialer/commandline/impl/BlockingCommand.java b/java/com/android/dialer/commandline/impl/BlockingCommand.java index f06e240ae..d06450513 100644 --- a/java/com/android/dialer/commandline/impl/BlockingCommand.java +++ b/java/com/android/dialer/commandline/impl/BlockingCommand.java @@ -28,6 +28,7 @@ import com.android.dialer.phonelookup.PhoneLookupComponent; import com.android.dialer.phonelookup.PhoneLookupInfo; import com.android.dialer.phonelookup.consolidator.PhoneLookupInfoConsolidator; import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil; +import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; @@ -71,7 +72,7 @@ public class BlockingCommand implements Command { if ("block".equals(command)) { String number = args.getPositionals().get(1); return Futures.transform( - Blocking.block(appContext, executorService, number, null), + Blocking.block(appContext, ImmutableList.of(number), null), (unused) -> "blocked " + number, MoreExecutors.directExecutor()); } @@ -79,7 +80,7 @@ public class BlockingCommand implements Command { if ("unblock".equals(command)) { String number = args.getPositionals().get(1); return Futures.transform( - Blocking.unblock(appContext, executorService, number, null), + Blocking.unblock(appContext, ImmutableList.of(number), null), (unused) -> "unblocked " + number, MoreExecutors.directExecutor()); } diff --git a/java/com/android/dialer/logging/reporting_location.proto b/java/com/android/dialer/logging/reporting_location.proto index b9912be75..1d6ba4752 100644 --- a/java/com/android/dialer/logging/reporting_location.proto +++ b/java/com/android/dialer/logging/reporting_location.proto @@ -15,5 +15,6 @@ message ReportingLocation { CALL_LOG_HISTORY = 1; FEEDBACK_PROMPT = 2; VOICEMAIL_HISTORY = 3; + CONTACT_DETAILS = 4; } } |