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