Loading src/com/android/server/telecom/callfiltering/BlockCheckerFilter.java 0 → 100644 +175 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.server.telecom.callfiltering; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.provider.BlockedNumberContract; import android.provider.CallLog; import android.telecom.Log; import android.telecom.TelecomManager; import android.telephony.CallerInfo; import com.android.server.telecom.Call; import com.android.server.telecom.CallerInfoLookupHelper; import com.android.server.telecom.LogUtils; import com.android.server.telecom.LoggedHandlerExecutor; import com.android.server.telecom.settings.BlockedNumbersUtil; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; public class BlockCheckerFilter extends CallFilter { private final Call mCall; private final Context mContext; private final CallerInfoLookupHelper mCallerInfoLookupHelper; private final BlockCheckerAdapter mBlockCheckerAdapter; private final String TAG = "BlockCheckerFilter"; private boolean mContactExists; private HandlerThread mHandlerThread; private Handler mHandler; public static final long CALLER_INFO_QUERY_TIMEOUT = 5000; public BlockCheckerFilter(Context context, Call call, CallerInfoLookupHelper callerInfoLookupHelper, BlockCheckerAdapter blockCheckerAdapter) { mCall = call; mContext = context; mCallerInfoLookupHelper = callerInfoLookupHelper; mBlockCheckerAdapter = blockCheckerAdapter; mContactExists = false; mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); } @Override public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult result) { Log.addEvent(mCall, LogUtils.Events.BLOCK_CHECK_INITIATED); CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); Bundle extras = new Bundle(); if (BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(mContext)) { int presentation = mCall.getHandlePresentation(); extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); if (presentation == TelecomManager.PRESENTATION_ALLOWED) { mCallerInfoLookupHelper.startLookup(mCall.getHandle(), new CallerInfoLookupHelper.OnQueryCompleteListener() { @Override public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) { if (info != null && info.contactExists) { mContactExists = true; } getBlockStatus(resultFuture); } @Override public void onContactPhotoQueryComplete(Uri handle, CallerInfo info) { // Ignore } }); } else { getBlockStatus(resultFuture); } } else { getBlockStatus(resultFuture); } return resultFuture; } private void getBlockStatus( CompletableFuture<CallFilteringResult> resultFuture) { // Set extras Bundle extras = new Bundle(); if (BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(mContext)) { int presentation = mCall.getHandlePresentation(); extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); if (presentation == TelecomManager.PRESENTATION_ALLOWED) { extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST, mContactExists); } } // Set number final String number = mCall.getHandle() == null ? null : mCall.getHandle().getSchemeSpecificPart(); CompletableFuture.supplyAsync( () -> mBlockCheckerAdapter.getBlockStatus(mContext, number, extras), new LoggedHandlerExecutor(mHandler, "BCF.gBS", null)) .thenApplyAsync((x) -> completeResult(resultFuture, x), new LoggedHandlerExecutor(mHandler, "BCF.gBS", null)); } private int completeResult(CompletableFuture<CallFilteringResult> resultFuture, int blockStatus) { CallFilteringResult result; if (blockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED) { result = new CallFilteringResult.Builder() .setShouldAllowCall(false) .setShouldReject(true) .setShouldAddToCallLog(true) .setShouldShowNotification(false) .setCallBlockReason(getBlockReason(blockStatus)) .setCallScreeningAppName(null) .setCallScreeningComponentName(null) .setContactExists(mContactExists) .build(); } else { result = new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldSilence(false) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .setContactExists(mContactExists) .build(); } Log.addEvent(mCall, LogUtils.Events.BLOCK_CHECK_FINISHED, BlockedNumberContract.SystemContract.blockStatusToString(blockStatus) + " " + result); resultFuture.complete(result); mHandlerThread.quitSafely(); return blockStatus; } private int getBlockReason(int blockStatus) { switch (blockStatus) { case BlockedNumberContract.STATUS_BLOCKED_IN_LIST: return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER: return CallLog.Calls.BLOCK_REASON_UNKNOWN_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED: return CallLog.Calls.BLOCK_REASON_RESTRICTED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE: return CallLog.Calls.BLOCK_REASON_PAY_PHONE; case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS: return CallLog.Calls.BLOCK_REASON_NOT_IN_CONTACTS; default: Log.w(this, "There's no call log block reason can be converted"); return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; } } } tests/src/com/android/server/telecom/tests/BlockCheckerFilterTest.java 0 → 100644 +163 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.server.telecom.tests; import static android.provider.BlockedNumberContract.STATUS_BLOCKED_IN_LIST; import static android.provider.BlockedNumberContract.STATUS_NOT_BLOCKED; import static junit.framework.TestCase.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.os.PersistableBundle; import android.provider.CallLog; import android.telephony.CallerInfo; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; import com.android.server.telecom.Call; import com.android.server.telecom.CallerInfoLookupHelper; import com.android.server.telecom.callfiltering.BlockCheckerAdapter; import com.android.server.telecom.callfiltering.BlockCheckerFilter; import com.android.server.telecom.callfiltering.CallFilteringResult; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) public class BlockCheckerFilterTest extends TelecomTestCase { @Mock Call mCall; @Mock private BlockCheckerAdapter mBlockCheckerAdapter; @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper; @Mock private CarrierConfigManager mCarrierConfigManager; private BlockCheckerFilter mFilter; private static final CallFilteringResult PASS_RESULT = new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .build(); private static final CallFilteringResult BLOCK_RESULT = new CallFilteringResult.Builder() .setShouldAllowCall(false) .setShouldReject(true) .setShouldAddToCallLog(true) .setShouldShowNotification(false) .setCallBlockReason(CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER) .setCallScreeningAppName(null) .setCallScreeningComponentName(null) .build(); private static final Uri TEST_HANDLE = Uri.parse("tel:1235551234"); @Override @Before public void setUp() throws Exception { super.setUp(); when(mCall.getHandle()).thenReturn(TEST_HANDLE); mFilter = new BlockCheckerFilter(mContext, mCall, mCallerInfoLookupHelper, mBlockCheckerAdapter); } @SmallTest @Test public void testBlockNumber() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_BLOCKED_IN_LIST); setEnhancedBlockingEnabled(false); assertEquals(BLOCK_RESULT, mFilter.startFilterLookup(PASS_RESULT).toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest @Test public void testBlockNumberWhenEnhancedBlockingEnabled() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_BLOCKED_IN_LIST); setEnhancedBlockingEnabled(true); CompletionStage<CallFilteringResult> resultFuture = mFilter.startFilterLookup(PASS_RESULT); verifyEnhancedLookupStart(); assertEquals(BLOCK_RESULT, resultFuture.toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest @Test public void testDontBlockNumber() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_NOT_BLOCKED); setEnhancedBlockingEnabled(false); assertEquals(PASS_RESULT, mFilter.startFilterLookup(PASS_RESULT).toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest @Test public void testDontBlockNumberWhenEnhancedBlockingEnabled() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_NOT_BLOCKED); setEnhancedBlockingEnabled(true); CompletionStage<CallFilteringResult> resultFuture = mFilter.startFilterLookup(PASS_RESULT); verifyEnhancedLookupStart(); assertEquals(PASS_RESULT, resultFuture.toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } private void setEnhancedBlockingEnabled(boolean value) { PersistableBundle bundle = new PersistableBundle(); bundle.putBoolean(CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, value); when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) .thenReturn(mCarrierConfigManager); when(mCarrierConfigManager.getConfig()).thenReturn(bundle); if (value) { when(mCall.getHandlePresentation()).thenReturn(TelecomManager.PRESENTATION_ALLOWED); } } private void verifyEnhancedLookupStart() { ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> captor = ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class); verify(mCallerInfoLookupHelper, timeout(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT)) .startLookup(eq(TEST_HANDLE), captor.capture()); captor.getValue().onCallerInfoQueryComplete(TEST_HANDLE, null); } } Loading
src/com/android/server/telecom/callfiltering/BlockCheckerFilter.java 0 → 100644 +175 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.server.telecom.callfiltering; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.provider.BlockedNumberContract; import android.provider.CallLog; import android.telecom.Log; import android.telecom.TelecomManager; import android.telephony.CallerInfo; import com.android.server.telecom.Call; import com.android.server.telecom.CallerInfoLookupHelper; import com.android.server.telecom.LogUtils; import com.android.server.telecom.LoggedHandlerExecutor; import com.android.server.telecom.settings.BlockedNumbersUtil; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; public class BlockCheckerFilter extends CallFilter { private final Call mCall; private final Context mContext; private final CallerInfoLookupHelper mCallerInfoLookupHelper; private final BlockCheckerAdapter mBlockCheckerAdapter; private final String TAG = "BlockCheckerFilter"; private boolean mContactExists; private HandlerThread mHandlerThread; private Handler mHandler; public static final long CALLER_INFO_QUERY_TIMEOUT = 5000; public BlockCheckerFilter(Context context, Call call, CallerInfoLookupHelper callerInfoLookupHelper, BlockCheckerAdapter blockCheckerAdapter) { mCall = call; mContext = context; mCallerInfoLookupHelper = callerInfoLookupHelper; mBlockCheckerAdapter = blockCheckerAdapter; mContactExists = false; mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); } @Override public CompletionStage<CallFilteringResult> startFilterLookup(CallFilteringResult result) { Log.addEvent(mCall, LogUtils.Events.BLOCK_CHECK_INITIATED); CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); Bundle extras = new Bundle(); if (BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(mContext)) { int presentation = mCall.getHandlePresentation(); extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); if (presentation == TelecomManager.PRESENTATION_ALLOWED) { mCallerInfoLookupHelper.startLookup(mCall.getHandle(), new CallerInfoLookupHelper.OnQueryCompleteListener() { @Override public void onCallerInfoQueryComplete(Uri handle, CallerInfo info) { if (info != null && info.contactExists) { mContactExists = true; } getBlockStatus(resultFuture); } @Override public void onContactPhotoQueryComplete(Uri handle, CallerInfo info) { // Ignore } }); } else { getBlockStatus(resultFuture); } } else { getBlockStatus(resultFuture); } return resultFuture; } private void getBlockStatus( CompletableFuture<CallFilteringResult> resultFuture) { // Set extras Bundle extras = new Bundle(); if (BlockedNumbersUtil.isEnhancedCallBlockingEnabledByPlatform(mContext)) { int presentation = mCall.getHandlePresentation(); extras.putInt(BlockedNumberContract.EXTRA_CALL_PRESENTATION, presentation); if (presentation == TelecomManager.PRESENTATION_ALLOWED) { extras.putBoolean(BlockedNumberContract.EXTRA_CONTACT_EXIST, mContactExists); } } // Set number final String number = mCall.getHandle() == null ? null : mCall.getHandle().getSchemeSpecificPart(); CompletableFuture.supplyAsync( () -> mBlockCheckerAdapter.getBlockStatus(mContext, number, extras), new LoggedHandlerExecutor(mHandler, "BCF.gBS", null)) .thenApplyAsync((x) -> completeResult(resultFuture, x), new LoggedHandlerExecutor(mHandler, "BCF.gBS", null)); } private int completeResult(CompletableFuture<CallFilteringResult> resultFuture, int blockStatus) { CallFilteringResult result; if (blockStatus != BlockedNumberContract.STATUS_NOT_BLOCKED) { result = new CallFilteringResult.Builder() .setShouldAllowCall(false) .setShouldReject(true) .setShouldAddToCallLog(true) .setShouldShowNotification(false) .setCallBlockReason(getBlockReason(blockStatus)) .setCallScreeningAppName(null) .setCallScreeningComponentName(null) .setContactExists(mContactExists) .build(); } else { result = new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldSilence(false) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .setContactExists(mContactExists) .build(); } Log.addEvent(mCall, LogUtils.Events.BLOCK_CHECK_FINISHED, BlockedNumberContract.SystemContract.blockStatusToString(blockStatus) + " " + result); resultFuture.complete(result); mHandlerThread.quitSafely(); return blockStatus; } private int getBlockReason(int blockStatus) { switch (blockStatus) { case BlockedNumberContract.STATUS_BLOCKED_IN_LIST: return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_UNKNOWN_NUMBER: return CallLog.Calls.BLOCK_REASON_UNKNOWN_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_RESTRICTED: return CallLog.Calls.BLOCK_REASON_RESTRICTED_NUMBER; case BlockedNumberContract.STATUS_BLOCKED_PAYPHONE: return CallLog.Calls.BLOCK_REASON_PAY_PHONE; case BlockedNumberContract.STATUS_BLOCKED_NOT_IN_CONTACTS: return CallLog.Calls.BLOCK_REASON_NOT_IN_CONTACTS; default: Log.w(this, "There's no call log block reason can be converted"); return CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER; } } }
tests/src/com/android/server/telecom/tests/BlockCheckerFilterTest.java 0 → 100644 +163 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.server.telecom.tests; import static android.provider.BlockedNumberContract.STATUS_BLOCKED_IN_LIST; import static android.provider.BlockedNumberContract.STATUS_NOT_BLOCKED; import static junit.framework.TestCase.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.os.PersistableBundle; import android.provider.CallLog; import android.telephony.CallerInfo; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.test.suitebuilder.annotation.SmallTest; import android.util.Pair; import com.android.server.telecom.Call; import com.android.server.telecom.CallerInfoLookupHelper; import com.android.server.telecom.callfiltering.BlockCheckerAdapter; import com.android.server.telecom.callfiltering.BlockCheckerFilter; import com.android.server.telecom.callfiltering.CallFilteringResult; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) public class BlockCheckerFilterTest extends TelecomTestCase { @Mock Call mCall; @Mock private BlockCheckerAdapter mBlockCheckerAdapter; @Mock private CallerInfoLookupHelper mCallerInfoLookupHelper; @Mock private CarrierConfigManager mCarrierConfigManager; private BlockCheckerFilter mFilter; private static final CallFilteringResult PASS_RESULT = new CallFilteringResult.Builder() .setShouldAllowCall(true) .setShouldReject(false) .setShouldAddToCallLog(true) .setShouldShowNotification(true) .build(); private static final CallFilteringResult BLOCK_RESULT = new CallFilteringResult.Builder() .setShouldAllowCall(false) .setShouldReject(true) .setShouldAddToCallLog(true) .setShouldShowNotification(false) .setCallBlockReason(CallLog.Calls.BLOCK_REASON_BLOCKED_NUMBER) .setCallScreeningAppName(null) .setCallScreeningComponentName(null) .build(); private static final Uri TEST_HANDLE = Uri.parse("tel:1235551234"); @Override @Before public void setUp() throws Exception { super.setUp(); when(mCall.getHandle()).thenReturn(TEST_HANDLE); mFilter = new BlockCheckerFilter(mContext, mCall, mCallerInfoLookupHelper, mBlockCheckerAdapter); } @SmallTest @Test public void testBlockNumber() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_BLOCKED_IN_LIST); setEnhancedBlockingEnabled(false); assertEquals(BLOCK_RESULT, mFilter.startFilterLookup(PASS_RESULT).toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest @Test public void testBlockNumberWhenEnhancedBlockingEnabled() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_BLOCKED_IN_LIST); setEnhancedBlockingEnabled(true); CompletionStage<CallFilteringResult> resultFuture = mFilter.startFilterLookup(PASS_RESULT); verifyEnhancedLookupStart(); assertEquals(BLOCK_RESULT, resultFuture.toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest @Test public void testDontBlockNumber() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_NOT_BLOCKED); setEnhancedBlockingEnabled(false); assertEquals(PASS_RESULT, mFilter.startFilterLookup(PASS_RESULT).toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } @SmallTest @Test public void testDontBlockNumberWhenEnhancedBlockingEnabled() throws Exception { when(mBlockCheckerAdapter.getBlockStatus(any(Context.class), eq(TEST_HANDLE.getSchemeSpecificPart()), any(Bundle.class))) .thenReturn(STATUS_NOT_BLOCKED); setEnhancedBlockingEnabled(true); CompletionStage<CallFilteringResult> resultFuture = mFilter.startFilterLookup(PASS_RESULT); verifyEnhancedLookupStart(); assertEquals(PASS_RESULT, resultFuture.toCompletableFuture() .get(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT, TimeUnit.MILLISECONDS)); } private void setEnhancedBlockingEnabled(boolean value) { PersistableBundle bundle = new PersistableBundle(); bundle.putBoolean(CarrierConfigManager.KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, value); when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) .thenReturn(mCarrierConfigManager); when(mCarrierConfigManager.getConfig()).thenReturn(bundle); if (value) { when(mCall.getHandlePresentation()).thenReturn(TelecomManager.PRESENTATION_ALLOWED); } } private void verifyEnhancedLookupStart() { ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> captor = ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class); verify(mCallerInfoLookupHelper, timeout(BlockCheckerFilter.CALLER_INFO_QUERY_TIMEOUT)) .startLookup(eq(TEST_HANDLE), captor.capture()); captor.getValue().onCallerInfoQueryComplete(TEST_HANDLE, null); } }