| /* |
| * 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 android.content.ContentResolver; |
| import android.content.Context; |
| import android.os.Handler; |
| import android.os.HandlerThread; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import com.android.server.telecom.Call; |
| import com.android.server.telecom.TelecomSystem; |
| import com.android.server.telecom.Timeouts; |
| import com.android.server.telecom.callfiltering.CallFilter; |
| import com.android.server.telecom.callfiltering.CallFilterResultCallback; |
| import com.android.server.telecom.callfiltering.CallFilteringResult; |
| import com.android.server.telecom.callfiltering.IncomingCallFilterGraph; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.mockito.ArgumentMatchers.nullable; |
| import static org.mockito.Mockito.when; |
| |
| import org.junit.Before; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.mockito.Mock; |
| import org.junit.Test; |
| |
| import java.util.concurrent.CompletableFuture; |
| import java.util.concurrent.CompletionStage; |
| import java.util.concurrent.TimeUnit; |
| |
| @RunWith(JUnit4.class) |
| public class IncomingCallFilterGraphTest extends TelecomTestCase { |
| @Mock private Call mCall; |
| @Mock private Context mContext; |
| @Mock private Timeouts.Adapter mTimeoutsAdapter; |
| private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {}; |
| |
| private static final CallFilteringResult PASS_CALL_RESULT = new CallFilteringResult.Builder() |
| .setShouldAllowCall(true) |
| .setShouldReject(false) |
| .setShouldSilence(false) |
| .setShouldAddToCallLog(true) |
| .setShouldShowNotification(true).build(); |
| private static final CallFilteringResult REJECT_CALL_RESULT = new CallFilteringResult.Builder() |
| .setShouldAllowCall(false) |
| .setShouldReject(true) |
| .setShouldSilence(false) |
| .setShouldAddToCallLog(true) |
| .setShouldShowNotification(true).build(); |
| private final long FILTER_TIMEOUT = 5000; |
| private final long TEST_TIMEOUT = 7000; |
| private final long TIMEOUT_FILTER_SLEEP_TIME = 10000; |
| |
| private class AllowFilter extends CallFilter { |
| @Override |
| public CompletionStage<CallFilteringResult> startFilterLookup( |
| CallFilteringResult priorStageResult) { |
| return CompletableFuture.completedFuture(PASS_CALL_RESULT); |
| } |
| } |
| |
| private class DisallowFilter extends CallFilter { |
| @Override |
| public CompletionStage<CallFilteringResult> startFilterLookup( |
| CallFilteringResult priorStageResult) { |
| return CompletableFuture.completedFuture(REJECT_CALL_RESULT); |
| } |
| } |
| |
| private class TimeoutFilter extends CallFilter { |
| @Override |
| public CompletionStage<CallFilteringResult> startFilterLookup( |
| CallFilteringResult priorStageResult) { |
| HandlerThread handlerThread = new HandlerThread("TimeoutFilter"); |
| handlerThread.start(); |
| Handler handler = new Handler(handlerThread.getLooper()); |
| |
| CompletableFuture<CallFilteringResult> resultFuture = new CompletableFuture<>(); |
| handler.postDelayed(() -> resultFuture.complete(PASS_CALL_RESULT), |
| TIMEOUT_FILTER_SLEEP_TIME); |
| return CompletableFuture.completedFuture(PASS_CALL_RESULT); |
| } |
| } |
| |
| @Before |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| when(mContext.getContentResolver()).thenReturn(null); |
| when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(nullable(ContentResolver.class))) |
| .thenReturn(FILTER_TIMEOUT); |
| |
| } |
| |
| @SmallTest |
| @Test |
| public void testEmptyGraph() throws Exception { |
| CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>(); |
| CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result); |
| |
| IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext, |
| mTimeoutsAdapter, mLock); |
| graph.performFiltering(); |
| |
| assertEquals(PASS_CALL_RESULT, testResult.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testFiltersPerformOrder() throws Exception { |
| CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>(); |
| CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result); |
| |
| IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext, |
| mTimeoutsAdapter, mLock); |
| AllowFilter allowFilter = new AllowFilter(); |
| DisallowFilter disallowFilter = new DisallowFilter(); |
| graph.addFilter(allowFilter); |
| graph.addFilter(disallowFilter); |
| IncomingCallFilterGraph.addEdge(allowFilter, disallowFilter); |
| graph.performFiltering(); |
| |
| assertEquals(REJECT_CALL_RESULT, testResult.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testFiltersPerformInParallel() throws Exception { |
| CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>(); |
| CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result); |
| |
| IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext, |
| mTimeoutsAdapter, mLock); |
| AllowFilter allowFilter1 = new AllowFilter(); |
| AllowFilter allowFilter2 = new AllowFilter(); |
| DisallowFilter disallowFilter = new DisallowFilter(); |
| graph.addFilter(allowFilter1); |
| graph.addFilter(allowFilter2); |
| graph.addFilter(disallowFilter); |
| graph.performFiltering(); |
| |
| assertEquals(REJECT_CALL_RESULT, testResult.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS)); |
| } |
| |
| @SmallTest |
| @Test |
| public void testFiltersTimeout() throws Exception { |
| CompletableFuture<CallFilteringResult> testResult = new CompletableFuture<>(); |
| CallFilterResultCallback listener = (call, result, timeout) -> testResult.complete(result); |
| |
| IncomingCallFilterGraph graph = new IncomingCallFilterGraph(mCall, listener, mContext, |
| mTimeoutsAdapter, mLock); |
| DisallowFilter disallowFilter = new DisallowFilter(); |
| TimeoutFilter timeoutFilter = new TimeoutFilter(); |
| graph.addFilter(disallowFilter); |
| graph.addFilter(timeoutFilter); |
| IncomingCallFilterGraph.addEdge(disallowFilter, timeoutFilter); |
| graph.performFiltering(); |
| |
| assertEquals(REJECT_CALL_RESULT, testResult.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS)); |
| } |
| } |