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