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