From 0e00f578d641440c5ddc4da48ab86eabbc21d403 Mon Sep 17 00:00:00 2001 From: twyen Date: Mon, 22 Jan 2018 16:08:08 -0800 Subject: Implement System blocked number This CL implements looking up blocked number in the Android system blocked number provider, which is available after N. Dialer and system blocked number will return empty if requirements are not made (N+ and migration completed is needed for system, otherwise dialer should not be used). Bug: 70989543 Test: Unit tests PiperOrigin-RevId: 182852672 Change-Id: I1360b7eed7c18f459292d769529ffcfceb61a7ed --- .../dialer/phonelookup/PhoneLookupModule.java | 9 +- .../DialerBlockedNumberPhoneLookup.java | 39 +---- .../blockednumber/MarkDirtyObserver.java | 47 ++++++ .../SystemBlockedNumberPhoneLookup.java | 181 +++++++++++++++++++++ .../consolidator/PhoneLookupInfoConsolidator.java | 21 ++- 5 files changed, 260 insertions(+), 37 deletions(-) create mode 100644 java/com/android/dialer/phonelookup/blockednumber/MarkDirtyObserver.java create mode 100644 java/com/android/dialer/phonelookup/blockednumber/SystemBlockedNumberPhoneLookup.java (limited to 'java/com/android/dialer/phonelookup') diff --git a/java/com/android/dialer/phonelookup/PhoneLookupModule.java b/java/com/android/dialer/phonelookup/PhoneLookupModule.java index e93ca0f77..8a78ba038 100644 --- a/java/com/android/dialer/phonelookup/PhoneLookupModule.java +++ b/java/com/android/dialer/phonelookup/PhoneLookupModule.java @@ -17,6 +17,7 @@ package com.android.dialer.phonelookup; import com.android.dialer.phonelookup.blockednumber.DialerBlockedNumberPhoneLookup; +import com.android.dialer.phonelookup.blockednumber.SystemBlockedNumberPhoneLookup; import com.android.dialer.phonelookup.composite.CompositePhoneLookup; import com.android.dialer.phonelookup.cp2.Cp2LocalPhoneLookup; import com.android.dialer.phonelookup.cp2.Cp2RemotePhoneLookup; @@ -33,9 +34,13 @@ public abstract class PhoneLookupModule { static ImmutableList providePhoneLookupList( Cp2LocalPhoneLookup cp2LocalPhoneLookup, Cp2RemotePhoneLookup cp2RemotePhoneLookup, - DialerBlockedNumberPhoneLookup dialerBlockedNumberPhoneLookup) { + DialerBlockedNumberPhoneLookup dialerBlockedNumberPhoneLookup, + SystemBlockedNumberPhoneLookup systemBlockedNumberPhoneLookup) { return ImmutableList.of( - cp2LocalPhoneLookup, cp2RemotePhoneLookup, dialerBlockedNumberPhoneLookup); + cp2LocalPhoneLookup, + cp2RemotePhoneLookup, + dialerBlockedNumberPhoneLookup, + systemBlockedNumberPhoneLookup); } @Provides diff --git a/java/com/android/dialer/phonelookup/blockednumber/DialerBlockedNumberPhoneLookup.java b/java/com/android/dialer/phonelookup/blockednumber/DialerBlockedNumberPhoneLookup.java index ce1217751..2271c7580 100644 --- a/java/com/android/dialer/phonelookup/blockednumber/DialerBlockedNumberPhoneLookup.java +++ b/java/com/android/dialer/phonelookup/blockednumber/DialerBlockedNumberPhoneLookup.java @@ -17,17 +17,14 @@ package com.android.dialer.phonelookup.blockednumber; import android.content.Context; -import android.database.ContentObserver; import android.database.Cursor; -import android.net.Uri; -import android.support.annotation.MainThread; import android.support.annotation.WorkerThread; import android.util.ArraySet; import com.android.dialer.DialerPhoneNumber; +import com.android.dialer.blocking.FilteredNumberCompat; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; -import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.common.database.Selection; import com.android.dialer.database.FilteredNumberContract.FilteredNumber; import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns; @@ -65,6 +62,9 @@ public final class DialerBlockedNumberPhoneLookup implements PhoneLookup lookup(DialerPhoneNumber dialerPhoneNumber) { + if (FilteredNumberCompat.useNewFiltering(appContext)) { + return Futures.immediateFuture(DialerBlockedNumberInfo.getDefaultInstance()); + } return executorService.submit( () -> queryNumbers(ImmutableSet.of(dialerPhoneNumber)).get(dialerPhoneNumber)); } @@ -79,6 +79,9 @@ public final class DialerBlockedNumberPhoneLookup implements PhoneLookup> getMostRecentInfo(ImmutableMap existingInfoMap) { + if (FilteredNumberCompat.useNewFiltering(appContext)) { + return Futures.immediateFuture(existingInfoMap); + } LogUtil.enterBlock("DialerBlockedNumberPhoneLookup.getMostRecentPhoneLookupInfo"); return executorService.submit(() -> queryNumbers(existingInfoMap.keySet())); } @@ -128,11 +131,7 @@ public final class DialerBlockedNumberPhoneLookup implements PhoneLookup { + + private final Context appContext; + private final ListeningExecutorService executorService; + + @Inject + SystemBlockedNumberPhoneLookup( + @ApplicationContext Context appContext, + @BackgroundExecutor ListeningExecutorService executorService) { + this.appContext = appContext; + this.executorService = executorService; + } + + @Override + public ListenableFuture lookup(@NonNull DialerPhoneNumber number) { + if (!FilteredNumberCompat.useNewFiltering(appContext)) { + return Futures.immediateFuture(SystemBlockedNumberInfo.getDefaultInstance()); + } + return executorService.submit( + () -> { + return queryNumbers(ImmutableSet.of(number)).get(number); + }); + } + + @Override + public ListenableFuture isDirty(ImmutableSet phoneNumbers) { + // Dirty state is recorded with PhoneLookupDataSource.markDirtyAndNotify(), which will force + // rebuild with the CallLogFramework + return Futures.immediateFuture(false); + } + + @Override + public ListenableFuture> + getMostRecentInfo(ImmutableMap existingInfoMap) { + LogUtil.enterBlock("SystemBlockedNumberPhoneLookup.getMostRecentPhoneLookupInfo"); + if (!FilteredNumberCompat.useNewFiltering(appContext)) { + return Futures.immediateFuture(existingInfoMap); + } + return executorService.submit(() -> queryNumbers(existingInfoMap.keySet())); + } + + @WorkerThread + @TargetApi(VERSION_CODES.N) + private ImmutableMap queryNumbers( + ImmutableSet numbers) { + Assert.isWorkerThread(); + PartitionedNumbers partitionedNumbers = new PartitionedNumbers(numbers); + + Set blockedNumbers = new ArraySet<>(); + + Selection normalizedSelection = + Selection.column(BlockedNumbers.COLUMN_E164_NUMBER) + .in(partitionedNumbers.validE164Numbers()); + try (Cursor cursor = + appContext + .getContentResolver() + .query( + BlockedNumbers.CONTENT_URI, + new String[] {BlockedNumbers.COLUMN_E164_NUMBER}, + normalizedSelection.getSelection(), + normalizedSelection.getSelectionArgs(), + null)) { + while (cursor != null && cursor.moveToNext()) { + blockedNumbers.addAll( + partitionedNumbers.dialerPhoneNumbersForValidE164(cursor.getString(0))); + } + } + + Selection rawSelection = + Selection.column(BlockedNumbers.COLUMN_ORIGINAL_NUMBER) + .in(partitionedNumbers.invalidNumbers()); + try (Cursor cursor = + appContext + .getContentResolver() + .query( + BlockedNumbers.CONTENT_URI, + new String[] {BlockedNumbers.COLUMN_ORIGINAL_NUMBER}, + rawSelection.getSelection(), + rawSelection.getSelectionArgs(), + null)) { + while (cursor != null && cursor.moveToNext()) { + blockedNumbers.addAll(partitionedNumbers.dialerPhoneNumbersForInvalid(cursor.getString(0))); + } + } + + ImmutableMap.Builder result = + ImmutableMap.builder(); + + for (DialerPhoneNumber number : numbers) { + result.put( + number, + SystemBlockedNumberInfo.newBuilder() + .setBlockedState( + blockedNumbers.contains(number) ? BlockedState.BLOCKED : BlockedState.NOT_BLOCKED) + .build()); + } + + return result.build(); + } + + @Override + public void setSubMessage(Builder phoneLookupInfo, SystemBlockedNumberInfo subMessage) { + phoneLookupInfo.setSystemBlockedNumberInfo(subMessage); + } + + @Override + public SystemBlockedNumberInfo getSubMessage(PhoneLookupInfo phoneLookupInfo) { + return phoneLookupInfo.getSystemBlockedNumberInfo(); + } + + @Override + public ListenableFuture onSuccessfulBulkUpdate() { + return Futures.immediateFuture(null); + } + + @Override + public void registerContentObservers( + Context appContext, ContentObserverCallbacks contentObserverCallbacks) { + if (VERSION.SDK_INT < VERSION_CODES.N) { + return; + } + appContext + .getContentResolver() + .registerContentObserver( + BlockedNumbers.CONTENT_URI, + true, // BlockedNumbers notifies on the item + new MarkDirtyObserver(appContext, contentObserverCallbacks)); + } +} diff --git a/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java b/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java index ccad3e7bc..27f0d21ae 100644 --- a/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java +++ b/java/com/android/dialer/phonelookup/consolidator/PhoneLookupInfoConsolidator.java @@ -179,11 +179,7 @@ public final class PhoneLookupInfoConsolidator { * returned. */ public String getNumberLabel() { - if (phoneLookupInfo.hasDialerBlockedNumberInfo() - && phoneLookupInfo - .getDialerBlockedNumberInfo() - .getBlockedState() - .equals(BlockedState.BLOCKED)) { + if (isBlocked()) { return appContext.getString(R.string.blocked_number_new_call_log_label); } @@ -219,6 +215,21 @@ public final class PhoneLookupInfoConsolidator { return false; } + public boolean isBlocked() { + // If system blocking reported blocked state it always takes priority over the dialer blocking. + // It will be absent if dialer blocking should be used. + if (phoneLookupInfo.getSystemBlockedNumberInfo().hasBlockedState()) { + return phoneLookupInfo + .getSystemBlockedNumberInfo() + .getBlockedState() + .equals(BlockedState.BLOCKED); + } + return phoneLookupInfo + .getDialerBlockedNumberInfo() + .getBlockedState() + .equals(BlockedState.BLOCKED); + } + /** * Returns true if the {@link PhoneLookupInfo} passed to the constructor has incomplete CP2 local * info. -- cgit v1.2.3