CallScreeningServiceFilterTest.java revision d7a57f03a21e507a6577c2229354e589658e8efe
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.telecom.tests;
18import android.Manifest;
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.ServiceConnection;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
25import android.content.pm.ServiceInfo;
26import android.os.IBinder;
27import android.os.RemoteException;
28import android.os.UserHandle;
29import android.telecom.CallScreeningService;
30import android.telecom.ParcelableCall;
31import android.test.suitebuilder.annotation.SmallTest;
32
33import com.android.internal.telecom.ICallScreeningAdapter;
34import com.android.internal.telecom.ICallScreeningService;
35import com.android.server.telecom.Call;
36import com.android.server.telecom.CallsManager;
37import com.android.server.telecom.DefaultDialerCache;
38import com.android.server.telecom.ParcelableCallUtils;
39import com.android.server.telecom.PhoneAccountRegistrar;
40import com.android.server.telecom.TelecomServiceImpl;
41import com.android.server.telecom.callfiltering.CallFilterResultCallback;
42import com.android.server.telecom.callfiltering.CallFilteringResult;
43import com.android.server.telecom.callfiltering.CallScreeningServiceFilter;
44import com.android.server.telecom.TelecomSystem;
45
46import org.mockito.ArgumentCaptor;
47import org.mockito.Mock;
48
49import java.util.Collections;
50
51import static org.mockito.ArgumentMatchers.nullable;
52import static org.mockito.Matchers.any;
53import static org.mockito.Matchers.anyBoolean;
54import static org.mockito.Matchers.anyInt;
55import static org.mockito.Matchers.anyString;
56import static org.mockito.Matchers.eq;
57import static org.mockito.Mockito.doReturn;
58import static org.mockito.Mockito.doThrow;
59import static org.mockito.Mockito.mock;
60import static org.mockito.Mockito.verify;
61import static org.mockito.Mockito.when;
62
63public class CallScreeningServiceFilterTest extends TelecomTestCase {
64    @Mock Context mContext;
65    @Mock CallsManager mCallsManager;
66    @Mock PhoneAccountRegistrar mPhoneAccountRegistrar;
67    @Mock DefaultDialerCache mDefaultDialerCache;
68    @Mock ParcelableCallUtils.Converter mParcelableCallUtilsConverter;
69    private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
70
71    @Mock Call mCall;
72    @Mock CallFilterResultCallback mCallback;
73
74    @Mock PackageManager mPackageManager;
75    @Mock IBinder mBinder;
76    @Mock ICallScreeningService mCallScreeningService;
77
78    private static final String PKG_NAME = "com.android.services.telecom.tests";
79    private static final String CLS_NAME = "CallScreeningService";
80    private static final ComponentName COMPONENT_NAME = new ComponentName(PKG_NAME, CLS_NAME);
81    private static final String CALL_ID = "u89prgt9ps78y5";
82
83    private ResolveInfo mResolveInfo;
84
85    private static final CallFilteringResult PASS_RESULT = new CallFilteringResult(
86            true, // shouldAllowCall
87            false, // shouldReject
88            true, // shouldAddToCallLog
89            true // shouldShowNotification
90    );
91
92    private CallScreeningServiceFilter mFilter;
93    @Override
94    public void setUp() throws Exception {
95        super.setUp();
96        when(mCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT);
97        when(mContext.getPackageManager()).thenReturn(mPackageManager);
98        when(mCall.getId()).thenReturn(CALL_ID);
99//        when(mBinder.queryLocalInterface(anyString())).thenReturn(mCallScreeningService);
100        doReturn(mCallScreeningService).when(mBinder).queryLocalInterface(anyString());
101
102        mResolveInfo =  new ResolveInfo() {{
103            serviceInfo = new ServiceInfo();
104            serviceInfo.packageName = PKG_NAME;
105            serviceInfo.name = CLS_NAME;
106            serviceInfo.permission = Manifest.permission.BIND_SCREENING_SERVICE;
107        }};
108
109        mFilter = new CallScreeningServiceFilter(mContext, mCallsManager, mPhoneAccountRegistrar,
110                mDefaultDialerCache, mParcelableCallUtilsConverter, mLock);
111
112        when(mDefaultDialerCache.getDefaultDialerApplication(eq(UserHandle.USER_CURRENT)))
113                .thenReturn(PKG_NAME);
114        when(mPackageManager.queryIntentServicesAsUser(nullable(Intent.class), anyInt(), anyInt()))
115                .thenReturn(Collections.singletonList(mResolveInfo));
116        when(mParcelableCallUtilsConverter.toParcelableCall(
117                eq(mCall), anyBoolean(), eq(mPhoneAccountRegistrar))).thenReturn(null);
118        when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
119                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
120    }
121
122    @SmallTest
123    public void testNoDefaultDialer() {
124        when(mDefaultDialerCache.getDefaultDialerApplication(eq(UserHandle.USER_CURRENT)))
125                .thenReturn(null);
126        mFilter.startFilterLookup(mCall, mCallback);
127        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
128    }
129
130    @SmallTest
131    public void testNoResolveEntries() {
132        when(mPackageManager.queryIntentServicesAsUser(nullable(Intent.class), anyInt(), anyInt()))
133                .thenReturn(Collections.emptyList());
134        mFilter.startFilterLookup(mCall, mCallback);
135        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
136    }
137
138    @SmallTest
139    public void testBadResolveEntry() {
140        mResolveInfo.serviceInfo = null;
141        mFilter.startFilterLookup(mCall, mCallback);
142        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
143    }
144
145    @SmallTest
146    public void testPermissionlessFilterService() {
147        mResolveInfo.serviceInfo.permission = null;
148        mFilter.startFilterLookup(mCall, mCallback);
149        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
150    }
151
152    @SmallTest
153    public void testContextFailToBind() {
154        when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
155                anyInt(), eq(UserHandle.CURRENT))).thenReturn(false);
156        mFilter.startFilterLookup(mCall, mCallback);
157        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
158    }
159
160    @SmallTest
161    public void testExceptionInScreeningService() throws Exception {
162        doThrow(new RemoteException()).when(mCallScreeningService).screenCall(
163                nullable(ICallScreeningAdapter.class), nullable(ParcelableCall.class));
164        mFilter.startFilterLookup(mCall, mCallback);
165        ServiceConnection serviceConnection = verifyBindingIntent();
166        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
167        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
168    }
169
170    @SmallTest
171    public void testAllowCall() throws Exception {
172        mFilter.startFilterLookup(mCall, mCallback);
173        ServiceConnection serviceConnection = verifyBindingIntent();
174        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
175        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
176        csAdapter.allowCall(CALL_ID);
177        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(PASS_RESULT));
178    }
179
180    @SmallTest
181    public void testDisallowCall() throws Exception {
182        mFilter.startFilterLookup(mCall, mCallback);
183        ServiceConnection serviceConnection = verifyBindingIntent();
184        serviceConnection.onServiceConnected(COMPONENT_NAME, mBinder);
185        ICallScreeningAdapter csAdapter = getCallScreeningAdapter();
186        csAdapter.disallowCall(CALL_ID,
187                true, // shouldReject
188                false, // shouldAddToCallLog
189                true // shouldShowNotification
190        );
191        verify(mCallback).onCallFilteringComplete(eq(mCall), eq(new CallFilteringResult(
192                false, // shouldAllowCall
193                true, // shouldReject
194                false, // shouldAddToCallLog
195                true // shouldShowNotification
196        )));
197    }
198
199    private ServiceConnection verifyBindingIntent() {
200        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
201        ArgumentCaptor<ServiceConnection> serviceCaptor =
202                ArgumentCaptor.forClass(ServiceConnection.class);
203        verify(mContext).bindServiceAsUser(intentCaptor.capture(), serviceCaptor.capture(),
204                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
205                eq(UserHandle.CURRENT));
206
207        Intent capturedIntent = intentCaptor.getValue();
208        assertEquals(CallScreeningService.SERVICE_INTERFACE, capturedIntent.getAction());
209        assertEquals(PKG_NAME, capturedIntent.getPackage());
210        assertEquals(COMPONENT_NAME, capturedIntent.getComponent());
211
212        return serviceCaptor.getValue();
213    }
214
215    private ICallScreeningAdapter getCallScreeningAdapter() throws Exception {
216        ArgumentCaptor<ICallScreeningAdapter> captor =
217                ArgumentCaptor.forClass(ICallScreeningAdapter.class);
218        verify(mCallScreeningService).screenCall(captor.capture(), nullable(ParcelableCall.class));
219        return captor.getValue();
220    }
221}
222