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