InCallControllerTests.java revision 782f91109ff869a6078bb8dd9294d3172d2a6903
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;
18
19import android.Manifest;
20import android.content.ComponentName;
21import android.content.ContentResolver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.ServiceConnection;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
27import android.content.pm.ServiceInfo;
28import android.content.res.Resources;
29import android.os.Bundle;
30import android.os.IBinder;
31import android.os.Handler;
32import android.os.Looper;
33import android.os.UserHandle;
34import android.telecom.InCallService;
35import android.telecom.ParcelableCall;
36import android.telecom.PhoneAccountHandle;
37import android.telecom.TelecomManager;
38import android.test.mock.MockContext;
39import android.test.suitebuilder.annotation.MediumTest;
40import android.text.TextUtils;
41
42import com.android.internal.telecom.IInCallAdapter;
43import com.android.internal.telecom.IInCallService;
44import com.android.server.telecom.Analytics;
45import com.android.server.telecom.BluetoothHeadsetProxy;
46import com.android.server.telecom.Call;
47import com.android.server.telecom.CallsManager;
48import com.android.server.telecom.DefaultDialerCache;
49import com.android.server.telecom.EmergencyCallHelper;
50import com.android.server.telecom.InCallController;
51import com.android.server.telecom.PhoneAccountRegistrar;
52import com.android.server.telecom.R;
53import com.android.server.telecom.SystemStateProvider;
54import com.android.server.telecom.TelecomSystem;
55import com.android.server.telecom.Timeouts;
56
57import org.mockito.ArgumentCaptor;
58import org.mockito.Mock;
59import org.mockito.MockitoAnnotations;
60import org.mockito.invocation.InvocationOnMock;
61import org.mockito.stubbing.Answer;
62
63import java.util.Collections;
64import java.util.LinkedList;
65
66import static org.mockito.ArgumentMatchers.nullable;
67import static org.mockito.Matchers.any;
68import static org.mockito.Matchers.anyInt;
69import static org.mockito.Matchers.anyString;
70import static org.mockito.Matchers.eq;
71import static org.mockito.Mockito.doAnswer;
72import static org.mockito.Mockito.doReturn;
73import static org.mockito.Mockito.mock;
74import static org.mockito.Mockito.never;
75import static org.mockito.Mockito.times;
76import static org.mockito.Mockito.when;
77import static org.mockito.Mockito.verify;
78
79public class InCallControllerTests extends TelecomTestCase {
80    @Mock CallsManager mMockCallsManager;
81    @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar;
82    @Mock BluetoothHeadsetProxy mMockBluetoothHeadset;
83    @Mock SystemStateProvider mMockSystemStateProvider;
84    @Mock PackageManager mMockPackageManager;
85    @Mock Call mMockCall;
86    @Mock Resources mMockResources;
87    @Mock MockContext mMockContext;
88    @Mock Timeouts.Adapter mTimeoutsAdapter;
89    @Mock DefaultDialerCache mDefaultDialerCache;
90
91    private static final int CURRENT_USER_ID = 900973;
92    private static final String DEF_PKG = "defpkg";
93    private static final String DEF_CLASS = "defcls";
94    private static final String SYS_PKG = "syspkg";
95    private static final String SYS_CLASS = "syscls";
96    private static final PhoneAccountHandle PA_HANDLE =
97            new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"), "pa_id");
98
99    private UserHandle mUserHandle = UserHandle.of(CURRENT_USER_ID);
100    private InCallController mInCallController;
101    private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {};
102    private EmergencyCallHelper mEmergencyCallHelper;
103
104    @Override
105    public void setUp() throws Exception {
106        super.setUp();
107        MockitoAnnotations.initMocks(this);
108        when(mMockCall.getAnalytics()).thenReturn(new Analytics.CallInfo());
109        doReturn(mMockResources).when(mMockContext).getResources();
110        doReturn(SYS_PKG).when(mMockResources).getString(R.string.ui_default_package);
111        doReturn(SYS_CLASS).when(mMockResources).getString(R.string.incall_default_class);
112        doReturn(true).when(mMockResources).getBoolean(R.bool.grant_location_permission_enabled);
113        mEmergencyCallHelper = new EmergencyCallHelper(mMockContext, SYS_PKG,
114                mTimeoutsAdapter);
115        mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
116                mMockSystemStateProvider, mDefaultDialerCache, mTimeoutsAdapter,
117                mEmergencyCallHelper);
118    }
119
120    @Override
121    public void tearDown() throws Exception {
122        super.tearDown();
123    }
124
125    @MediumTest
126    public void testBindToService_NoServicesFound_IncomingCall() throws Exception {
127        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
128        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
129        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
130        when(mMockCall.isIncoming()).thenReturn(true);
131        when(mMockCall.isExternalCall()).thenReturn(false);
132        when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
133                .thenReturn(300_000L);
134
135        setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
136        mInCallController.bindToServices(mMockCall);
137
138        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
139        verify(mMockContext).bindServiceAsUser(
140                bindIntentCaptor.capture(),
141                any(ServiceConnection.class),
142                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
143                eq(UserHandle.CURRENT));
144
145        Intent bindIntent = bindIntentCaptor.getValue();
146        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
147        assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
148        assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
149        assertNull(bindIntent.getExtras());
150    }
151
152    @MediumTest
153    public void testBindToService_NoServicesFound_OutgoingCall() throws Exception {
154        Bundle callExtras = new Bundle();
155        callExtras.putBoolean("whatever", true);
156
157        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
158        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
159        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
160        when(mMockCall.isIncoming()).thenReturn(false);
161        when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
162        when(mMockCall.getIntentExtras()).thenReturn(callExtras);
163        when(mMockCall.isExternalCall()).thenReturn(false);
164        when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
165                .thenReturn(300_000L);
166
167        Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
168        setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
169        mInCallController.bindToServices(mMockCall);
170
171        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
172        verify(mMockContext).bindServiceAsUser(
173                bindIntentCaptor.capture(),
174                any(ServiceConnection.class),
175                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
176                eq(UserHandle.CURRENT));
177
178        Intent bindIntent = bindIntentCaptor.getValue();
179        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
180        assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
181        assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
182        assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
183                TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
184        assertEquals(callExtras, bindIntent.getExtras().getParcelable(
185                TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
186    }
187
188    @MediumTest
189    public void testBindToService_DefaultDialer_NoEmergency() throws Exception {
190        Bundle callExtras = new Bundle();
191        callExtras.putBoolean("whatever", true);
192
193        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
194        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
195        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
196        when(mMockCall.isIncoming()).thenReturn(false);
197        when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
198        when(mMockCall.getIntentExtras()).thenReturn(callExtras);
199        when(mMockCall.isExternalCall()).thenReturn(false);
200        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
201                .thenReturn(DEF_PKG);
202        when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
203                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
204
205        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
206        mInCallController.bindToServices(mMockCall);
207
208        // Query for the different InCallServices
209        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
210        verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
211                queryIntentCaptor.capture(),
212                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
213
214        // Verify call for default dialer InCallService
215        assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
216        // Verify call for car-mode InCallService
217        assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
218        // Verify call for non-UI InCallServices
219        assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
220
221        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
222        verify(mMockContext, times(1)).bindServiceAsUser(
223                bindIntentCaptor.capture(),
224                any(ServiceConnection.class),
225                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
226                eq(UserHandle.CURRENT));
227
228        Intent bindIntent = bindIntentCaptor.getValue();
229        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
230        assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
231        assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
232        assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
233                TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
234        assertEquals(callExtras, bindIntent.getExtras().getParcelable(
235                TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
236    }
237
238    @MediumTest
239    public void testBindToService_SystemDialer_Emergency() throws Exception {
240        Bundle callExtras = new Bundle();
241        callExtras.putBoolean("whatever", true);
242
243        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
244        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
245        when(mMockCallsManager.hasEmergencyCall()).thenReturn(true);
246        when(mMockCall.isEmergencyCall()).thenReturn(true);
247        when(mMockCall.isIncoming()).thenReturn(false);
248        when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
249        when(mMockCall.getIntentExtras()).thenReturn(callExtras);
250        when(mMockCall.isExternalCall()).thenReturn(false);
251        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
252                .thenReturn(DEF_PKG);
253        when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
254                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
255                eq(UserHandle.CURRENT))).thenReturn(true);
256        when(mTimeoutsAdapter.getEmergencyCallbackWindowMillis(any(ContentResolver.class)))
257                .thenReturn(300_000L);
258
259        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
260        setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
261
262        mInCallController.bindToServices(mMockCall);
263
264        // Query for the different InCallServices
265        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
266        verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
267                queryIntentCaptor.capture(),
268                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
269
270        // Verify call for default dialer InCallService
271        assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
272        // Verify call for car-mode InCallService
273        assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
274        // Verify call for non-UI InCallServices
275        assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
276
277        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
278        verify(mMockContext, times(1)).bindServiceAsUser(
279                bindIntentCaptor.capture(),
280                any(ServiceConnection.class),
281                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
282                eq(UserHandle.CURRENT));
283
284        Intent bindIntent = bindIntentCaptor.getValue();
285        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
286        assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
287        assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
288        assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
289                TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
290        assertEquals(callExtras, bindIntent.getExtras().getParcelable(
291                TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
292
293        verify(mMockPackageManager).grantRuntimePermission(eq(SYS_PKG),
294                eq(Manifest.permission.ACCESS_FINE_LOCATION), eq(mUserHandle));
295
296        // Pretend that the call has gone away.
297        when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
298        mInCallController.onCallRemoved(mMockCall);
299        waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT);
300
301        verify(mMockPackageManager).revokeRuntimePermission(eq(SYS_PKG),
302                eq(Manifest.permission.ACCESS_FINE_LOCATION), eq(mUserHandle));
303    }
304
305    @MediumTest
306    public void testBindToService_DefaultDialer_FallBackToSystem() throws Exception {
307        Bundle callExtras = new Bundle();
308        callExtras.putBoolean("whatever", true);
309
310        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
311        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
312        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
313        when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
314        when(mMockCallsManager.getAudioState()).thenReturn(null);
315        when(mMockCallsManager.canAddCall()).thenReturn(false);
316        when(mMockCall.isIncoming()).thenReturn(false);
317        when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
318        when(mMockCall.getIntentExtras()).thenReturn(callExtras);
319        when(mMockCall.isExternalCall()).thenReturn(false);
320        when(mMockCall.getConferenceableCalls()).thenReturn(Collections.emptyList());
321        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID))
322                .thenReturn(DEF_PKG);
323        when(mMockContext.bindServiceAsUser(
324                any(Intent.class), any(ServiceConnection.class), anyInt(), any(UserHandle.class)))
325                .thenReturn(true);
326
327        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
328        mInCallController.bindToServices(mMockCall);
329
330        // Query for the different InCallServices
331        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
332        verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
333                queryIntentCaptor.capture(),
334                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
335
336        // Verify call for default dialer InCallService
337        assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
338        // Verify call for car-mode InCallService
339        assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
340        // Verify call for non-UI InCallServices
341        assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
342
343        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
344        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
345                ArgumentCaptor.forClass(ServiceConnection.class);
346        verify(mMockContext, times(1)).bindServiceAsUser(
347                bindIntentCaptor.capture(),
348                serviceConnectionCaptor.capture(),
349                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
350                eq(UserHandle.CURRENT));
351
352        Intent bindIntent = bindIntentCaptor.getValue();
353        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
354        assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
355        assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
356        assertEquals(PA_HANDLE, bindIntent.getExtras().getParcelable(
357                TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE));
358        assertEquals(callExtras, bindIntent.getExtras().getParcelable(
359                TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS));
360
361        // We have a ServiceConnection for the default dialer, lets start the connection, and then
362        // simulate a crash so that we fallback to system.
363        ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
364        ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
365        IBinder mockBinder = mock(IBinder.class);
366        IInCallService mockInCallService = mock(IInCallService.class);
367        when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
368
369
370        // Start the connection with IInCallService
371        serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
372        verify(mockInCallService).setInCallAdapter(any(IInCallAdapter.class));
373
374        // Now crash the damn thing!
375        serviceConnection.onServiceDisconnected(defDialerComponentName);
376
377        ArgumentCaptor<Intent> bindIntentCaptor2 = ArgumentCaptor.forClass(Intent.class);
378        verify(mMockContext, times(2)).bindServiceAsUser(
379                bindIntentCaptor2.capture(),
380                any(ServiceConnection.class),
381                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
382                eq(UserHandle.CURRENT));
383
384        bindIntent = bindIntentCaptor2.getValue();
385        assertEquals(SYS_PKG, bindIntent.getComponent().getPackageName());
386        assertEquals(SYS_CLASS, bindIntent.getComponent().getClassName());
387    }
388
389    /**
390     * Ensures that the {@link InCallController} will bind to an {@link InCallService} which
391     * supports external calls.
392     */
393    @MediumTest
394    public void testBindToService_IncludeExternal() throws Exception {
395        setupMocks(true /* isExternalCall */);
396        setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
397        mInCallController.bindToServices(mMockCall);
398
399        // Query for the different InCallServices
400        ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
401        verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
402                queryIntentCaptor.capture(),
403                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
404
405        // Verify call for default dialer InCallService
406        assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
407        // Verify call for car-mode InCallService
408        assertEquals(null, queryIntentCaptor.getAllValues().get(1).getPackage());
409        // Verify call for non-UI InCallServices
410        assertEquals(null, queryIntentCaptor.getAllValues().get(2).getPackage());
411
412        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
413        verify(mMockContext, times(1)).bindServiceAsUser(
414                bindIntentCaptor.capture(),
415                any(ServiceConnection.class),
416                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
417                eq(UserHandle.CURRENT));
418
419        Intent bindIntent = bindIntentCaptor.getValue();
420        assertEquals(InCallService.SERVICE_INTERFACE, bindIntent.getAction());
421        assertEquals(DEF_PKG, bindIntent.getComponent().getPackageName());
422        assertEquals(DEF_CLASS, bindIntent.getComponent().getClassName());
423    }
424
425    /**
426     * Make sure that if a call goes away before the in-call service finishes binding and another
427     * call gets connected soon after, the new call will still be sent to the in-call service.
428     */
429    @MediumTest
430    public void testUnbindDueToCallDisconnect() throws Exception {
431        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
432        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
433        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
434        when(mMockCall.isIncoming()).thenReturn(true);
435        when(mMockCall.isExternalCall()).thenReturn(false);
436        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
437        when(mMockContext.bindServiceAsUser(nullable(Intent.class),
438                nullable(ServiceConnection.class), anyInt(), nullable(UserHandle.class)))
439                .thenReturn(true);
440        when(mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
441                nullable(ContentResolver.class))).thenReturn(500L);
442
443        when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
444        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
445        mInCallController.bindToServices(mMockCall);
446
447        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
448        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
449                ArgumentCaptor.forClass(ServiceConnection.class);
450        verify(mMockContext, times(1)).bindServiceAsUser(
451                bindIntentCaptor.capture(),
452                serviceConnectionCaptor.capture(),
453                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
454                eq(UserHandle.CURRENT));
455
456        // Pretend that the call has gone away.
457        when(mMockCallsManager.getCalls()).thenReturn(Collections.emptyList());
458        mInCallController.onCallRemoved(mMockCall);
459
460        // Start the connection, make sure we don't unbind, and make sure that we don't send
461        // anything to the in-call service yet.
462        ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
463        ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
464        IBinder mockBinder = mock(IBinder.class);
465        IInCallService mockInCallService = mock(IInCallService.class);
466        when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
467
468        serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
469        verify(mockInCallService).setInCallAdapter(nullable(IInCallAdapter.class));
470        verify(mMockContext, never()).unbindService(serviceConnection);
471        verify(mockInCallService, never()).addCall(any(ParcelableCall.class));
472
473        // Now, we add in the call again and make sure that it's sent to the InCallService.
474        when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
475        mInCallController.onCallAdded(mMockCall);
476        verify(mockInCallService).addCall(any(ParcelableCall.class));
477    }
478
479    private void setupMocks(boolean isExternalCall) {
480        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
481        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
482        when(mMockCallsManager.hasEmergencyCall()).thenReturn(false);
483        when(mMockCall.isIncoming()).thenReturn(false);
484        when(mMockCall.getTargetPhoneAccount()).thenReturn(PA_HANDLE);
485        when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
486        when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
487                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
488        when(mMockCall.isExternalCall()).thenReturn(isExternalCall);
489    }
490
491    private ResolveInfo getDefResolveInfo(final boolean includeExternalCalls) {
492        return new ResolveInfo() {{
493            serviceInfo = new ServiceInfo();
494            serviceInfo.packageName = DEF_PKG;
495            serviceInfo.name = DEF_CLASS;
496            serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
497            serviceInfo.metaData = new Bundle();
498            serviceInfo.metaData.putBoolean(
499                    TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
500            if (includeExternalCalls) {
501                serviceInfo.metaData.putBoolean(
502                        TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
503            }
504        }};
505    }
506
507    private ResolveInfo getSysResolveinfo() {
508        return new ResolveInfo() {{
509            serviceInfo = new ServiceInfo();
510            serviceInfo.packageName = SYS_PKG;
511            serviceInfo.name = SYS_CLASS;
512            serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
513        }};
514    }
515
516    private void setupMockPackageManager(final boolean useDefaultDialer,
517            final boolean useSystemDialer, final boolean includeExternalCalls) {
518
519        doAnswer(new Answer() {
520            @Override
521            public Object answer(InvocationOnMock invocation) throws Throwable {
522                Object[] args = invocation.getArguments();
523                Intent intent = (Intent) args[0];
524                String packageName = intent.getPackage();
525                ComponentName componentName = intent.getComponent();
526                if (componentName != null) {
527                    packageName = componentName.getPackageName();
528                }
529                LinkedList<ResolveInfo> resolveInfo = new LinkedList<ResolveInfo>();
530                if (!TextUtils.isEmpty(packageName)) {
531                    if ((TextUtils.isEmpty(packageName) || packageName.equals(DEF_PKG)) &&
532                            useDefaultDialer) {
533                        resolveInfo.add(getDefResolveInfo(includeExternalCalls));
534                    }
535
536                    if ((TextUtils.isEmpty(packageName) || packageName.equals(SYS_PKG)) &&
537                           useSystemDialer) {
538                        resolveInfo.add(getSysResolveinfo());
539                    }
540                }
541                return resolveInfo;
542            }
543        }).when(mMockPackageManager).queryIntentServicesAsUser(
544                any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
545    }
546
547    private void setupMockPackageManagerLocationPermission(final String pkg,
548            final boolean granted) {
549        when(mMockPackageManager.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, pkg))
550                .thenReturn(granted
551                        ? PackageManager.PERMISSION_GRANTED
552                        : PackageManager.PERMISSION_DENIED);
553  }
554}
555