1 /* 2 * Copyright (C) 2015 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 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.mockito.ArgumentMatchers.nullable; 25 import static org.mockito.Matchers.any; 26 import static org.mockito.Matchers.anyBoolean; 27 import static org.mockito.Matchers.anyInt; 28 import static org.mockito.Matchers.anyString; 29 import static org.mockito.Matchers.eq; 30 import static org.mockito.Mockito.doAnswer; 31 import static org.mockito.Mockito.doNothing; 32 import static org.mockito.Mockito.doReturn; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.reset; 35 import static org.mockito.Mockito.spy; 36 import static org.mockito.Mockito.timeout; 37 import static org.mockito.Mockito.times; 38 import static org.mockito.Mockito.verify; 39 import static org.mockito.Mockito.when; 40 41 import android.content.BroadcastReceiver; 42 import android.content.ComponentName; 43 import android.content.ContentResolver; 44 import android.content.Context; 45 import android.content.Intent; 46 import android.media.AudioManager; 47 import android.media.IAudioService; 48 import android.media.ToneGenerator; 49 import android.net.Uri; 50 import android.os.Bundle; 51 import android.os.Handler; 52 import android.os.HandlerThread; 53 import android.os.Looper; 54 import android.os.Process; 55 import android.os.UserHandle; 56 import android.telecom.Call; 57 import android.telecom.ConnectionRequest; 58 import android.telecom.DisconnectCause; 59 import android.telecom.Log; 60 import android.telecom.ParcelableCall; 61 import android.telecom.PhoneAccount; 62 import android.telecom.PhoneAccountHandle; 63 import android.telecom.TelecomManager; 64 import android.telecom.VideoProfile; 65 import android.telephony.TelephonyManager; 66 import android.telephony.TelephonyRegistryManager; 67 import android.text.TextUtils; 68 69 import com.android.internal.telecom.IInCallAdapter; 70 import com.android.server.telecom.AsyncRingtonePlayer; 71 import com.android.server.telecom.BluetoothPhoneServiceImpl; 72 import com.android.server.telecom.CallAudioManager; 73 import com.android.server.telecom.CallAudioModeStateMachine; 74 import com.android.server.telecom.CallAudioRouteStateMachine; 75 import com.android.server.telecom.CallerInfoLookupHelper; 76 import com.android.server.telecom.CallsManager; 77 import com.android.server.telecom.CallsManagerListenerBase; 78 import com.android.server.telecom.ClockProxy; 79 import com.android.server.telecom.ConnectionServiceFocusManager; 80 import com.android.server.telecom.ContactsAsyncHelper; 81 import com.android.server.telecom.HeadsetMediaButton; 82 import com.android.server.telecom.HeadsetMediaButtonFactory; 83 import com.android.server.telecom.InCallWakeLockController; 84 import com.android.server.telecom.InCallWakeLockControllerFactory; 85 import com.android.server.telecom.MissedCallNotifier; 86 import com.android.server.telecom.PhoneAccountRegistrar; 87 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl; 88 import com.android.server.telecom.ProximitySensorManager; 89 import com.android.server.telecom.ProximitySensorManagerFactory; 90 import com.android.server.telecom.RoleManagerAdapter; 91 import com.android.server.telecom.StatusBarNotifier; 92 import com.android.server.telecom.SystemStateHelper; 93 import com.android.server.telecom.TelecomSystem; 94 import com.android.server.telecom.Timeouts; 95 import com.android.server.telecom.WiredHeadsetManager; 96 import com.android.server.telecom.bluetooth.BluetoothRouteManager; 97 import com.android.server.telecom.callfiltering.CallFilterResultCallback; 98 import com.android.server.telecom.callfiltering.IncomingCallFilter; 99 import com.android.server.telecom.components.UserCallIntentProcessor; 100 import com.android.server.telecom.ui.IncomingCallNotifier; 101 102 import com.google.common.base.Predicate; 103 104 import org.mockito.ArgumentCaptor; 105 import org.mockito.Mock; 106 import org.mockito.invocation.InvocationOnMock; 107 import org.mockito.stubbing.Answer; 108 109 import java.io.File; 110 import java.util.ArrayList; 111 import java.util.Collections; 112 import java.util.LinkedList; 113 import java.util.List; 114 import java.util.concurrent.CountDownLatch; 115 import java.util.concurrent.TimeUnit; 116 117 /** 118 * Implements mocks and functionality required to implement telecom system tests. 119 */ 120 public class TelecomSystemTest extends TelecomTestCase { 121 122 static final int TEST_POLL_INTERVAL = 10; // milliseconds 123 static final int TEST_TIMEOUT = 1000; // milliseconds 124 125 // Purposely keep the connect time (which is wall clock) and elapsed time (which is time since 126 // boot) different to test that wall clock time operations and elapsed time operations perform 127 // as they individually should. 128 static final long TEST_CREATE_TIME = 100; 129 static final long TEST_CREATE_ELAPSED_TIME = 200; 130 static final long TEST_CONNECT_TIME = 1000; 131 static final long TEST_CONNECT_ELAPSED_TIME = 2000; 132 static final long TEST_DISCONNECT_TIME = 8000; 133 static final long TEST_DISCONNECT_ELAPSED_TIME = 4000; 134 135 public class HeadsetMediaButtonFactoryF implements HeadsetMediaButtonFactory { 136 @Override create(Context context, CallsManager callsManager, TelecomSystem.SyncRoot lock)137 public HeadsetMediaButton create(Context context, CallsManager callsManager, 138 TelecomSystem.SyncRoot lock) { 139 return mHeadsetMediaButton; 140 } 141 } 142 143 public class ProximitySensorManagerFactoryF implements ProximitySensorManagerFactory { 144 @Override create(Context context, CallsManager callsManager)145 public ProximitySensorManager create(Context context, CallsManager callsManager) { 146 return mProximitySensorManager; 147 } 148 } 149 150 public class InCallWakeLockControllerFactoryF implements InCallWakeLockControllerFactory { 151 @Override create(Context context, CallsManager callsManager)152 public InCallWakeLockController create(Context context, CallsManager callsManager) { 153 return mInCallWakeLockController; 154 } 155 } 156 157 public static class MissedCallNotifierFakeImpl extends CallsManagerListenerBase 158 implements MissedCallNotifier { 159 List<CallInfo> missedCallsNotified = new ArrayList<>(); 160 161 @Override clearMissedCalls(UserHandle userHandle)162 public void clearMissedCalls(UserHandle userHandle) { 163 164 } 165 166 @Override showMissedCallNotification(CallInfo call)167 public void showMissedCallNotification(CallInfo call) { 168 missedCallsNotified.add(call); 169 } 170 171 @Override reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper, CallInfoFactory callInfoFactory)172 public void reloadAfterBootComplete(CallerInfoLookupHelper callerInfoLookupHelper, 173 CallInfoFactory callInfoFactory) { } 174 175 @Override reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper, CallInfoFactory callInfoFactory, UserHandle userHandle)176 public void reloadFromDatabase(CallerInfoLookupHelper callerInfoLookupHelper, 177 CallInfoFactory callInfoFactory, UserHandle userHandle) { } 178 179 @Override setCurrentUserHandle(UserHandle userHandle)180 public void setCurrentUserHandle(UserHandle userHandle) { 181 182 } 183 } 184 185 MissedCallNotifierFakeImpl mMissedCallNotifier = new MissedCallNotifierFakeImpl(); 186 187 private class IncomingCallAddedListener extends CallsManagerListenerBase { 188 189 private final CountDownLatch mCountDownLatch; 190 IncomingCallAddedListener(CountDownLatch latch)191 public IncomingCallAddedListener(CountDownLatch latch) { 192 mCountDownLatch = latch; 193 } 194 195 @Override onCallAdded(com.android.server.telecom.Call call)196 public void onCallAdded(com.android.server.telecom.Call call) { 197 mCountDownLatch.countDown(); 198 } 199 } 200 201 @Mock HeadsetMediaButton mHeadsetMediaButton; 202 @Mock ProximitySensorManager mProximitySensorManager; 203 @Mock InCallWakeLockController mInCallWakeLockController; 204 @Mock BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl; 205 @Mock AsyncRingtonePlayer mAsyncRingtonePlayer; 206 @Mock IncomingCallNotifier mIncomingCallNotifier; 207 @Mock ClockProxy mClockProxy; 208 @Mock RoleManagerAdapter mRoleManagerAdapter; 209 @Mock ToneGenerator mToneGenerator; 210 211 final ComponentName mInCallServiceComponentNameX = 212 new ComponentName( 213 "incall-service-package-X", 214 "incall-service-class-X"); 215 private static final int SERVICE_X_UID = 1; 216 final ComponentName mInCallServiceComponentNameY = 217 new ComponentName( 218 "incall-service-package-Y", 219 "incall-service-class-Y"); 220 private static final int SERVICE_Y_UID = 1; 221 InCallServiceFixture mInCallServiceFixtureX; 222 InCallServiceFixture mInCallServiceFixtureY; 223 224 final ComponentName mConnectionServiceComponentNameA = 225 new ComponentName( 226 "connection-service-package-A", 227 "connection-service-class-A"); 228 final ComponentName mConnectionServiceComponentNameB = 229 new ComponentName( 230 "connection-service-package-B", 231 "connection-service-class-B"); 232 233 final PhoneAccount mPhoneAccountA0 = 234 PhoneAccount.builder( 235 new PhoneAccountHandle( 236 mConnectionServiceComponentNameA, 237 "id A 0"), 238 "Phone account service A ID 0") 239 .addSupportedUriScheme("tel") 240 .setCapabilities( 241 PhoneAccount.CAPABILITY_CALL_PROVIDER | 242 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | 243 PhoneAccount.CAPABILITY_VIDEO_CALLING) 244 .build(); 245 final PhoneAccount mPhoneAccountA1 = 246 PhoneAccount.builder( 247 new PhoneAccountHandle( 248 mConnectionServiceComponentNameA, 249 "id A 1"), 250 "Phone account service A ID 1") 251 .addSupportedUriScheme("tel") 252 .setCapabilities( 253 PhoneAccount.CAPABILITY_CALL_PROVIDER | 254 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | 255 PhoneAccount.CAPABILITY_VIDEO_CALLING) 256 .build(); 257 final PhoneAccount mPhoneAccountA2 = 258 PhoneAccount.builder( 259 new PhoneAccountHandle( 260 mConnectionServiceComponentNameA, 261 "id A 2"), 262 "Phone account service A ID 2") 263 .addSupportedUriScheme("tel") 264 .setCapabilities( 265 PhoneAccount.CAPABILITY_CALL_PROVIDER | 266 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 267 .build(); 268 final PhoneAccount mPhoneAccountSelfManaged = 269 PhoneAccount.builder( 270 new PhoneAccountHandle( 271 mConnectionServiceComponentNameA, 272 "id SM"), 273 "Phone account service A SM") 274 .addSupportedUriScheme("tel") 275 .setCapabilities( 276 PhoneAccount.CAPABILITY_SELF_MANAGED) 277 .build(); 278 final PhoneAccount mPhoneAccountB0 = 279 PhoneAccount.builder( 280 new PhoneAccountHandle( 281 mConnectionServiceComponentNameB, 282 "id B 0"), 283 "Phone account service B ID 0") 284 .addSupportedUriScheme("tel") 285 .setCapabilities( 286 PhoneAccount.CAPABILITY_CALL_PROVIDER | 287 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | 288 PhoneAccount.CAPABILITY_VIDEO_CALLING) 289 .build(); 290 final PhoneAccount mPhoneAccountE0 = 291 PhoneAccount.builder( 292 new PhoneAccountHandle( 293 mConnectionServiceComponentNameA, 294 "id E 0"), 295 "Phone account service E ID 0") 296 .addSupportedUriScheme("tel") 297 .setCapabilities( 298 PhoneAccount.CAPABILITY_CALL_PROVIDER | 299 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | 300 PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) 301 .build(); 302 303 final PhoneAccount mPhoneAccountE1 = 304 PhoneAccount.builder( 305 new PhoneAccountHandle( 306 mConnectionServiceComponentNameA, 307 "id E 1"), 308 "Phone account service E ID 1") 309 .addSupportedUriScheme("tel") 310 .setCapabilities( 311 PhoneAccount.CAPABILITY_CALL_PROVIDER | 312 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | 313 PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) 314 .build(); 315 316 ConnectionServiceFixture mConnectionServiceFixtureA; 317 ConnectionServiceFixture mConnectionServiceFixtureB; 318 Timeouts.Adapter mTimeoutsAdapter; 319 320 CallerInfoAsyncQueryFactoryFixture mCallerInfoAsyncQueryFactoryFixture; 321 322 IAudioService mAudioService; 323 324 TelecomSystem mTelecomSystem; 325 326 Context mSpyContext; 327 328 ConnectionServiceFocusManager mConnectionServiceFocusManager; 329 330 private HandlerThread mHandlerThread; 331 332 private int mNumOutgoingCallsMade; 333 334 class IdPair { 335 final String mConnectionId; 336 final String mCallId; 337 IdPair(String connectionId, String callId)338 public IdPair(String connectionId, String callId) { 339 this.mConnectionId = connectionId; 340 this.mCallId = callId; 341 } 342 } 343 344 @Override setUp()345 public void setUp() throws Exception { 346 super.setUp(); 347 mSpyContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 348 doReturn(mSpyContext).when(mSpyContext).getApplicationContext(); 349 doNothing().when(mSpyContext).sendBroadcastAsUser(any(), any(), any()); 350 351 mHandlerThread = new HandlerThread("TelecomHandlerThread"); 352 mHandlerThread.start(); 353 354 mNumOutgoingCallsMade = 0; 355 356 doReturn(false).when(mComponentContextFixture.getTelephonyManager()) 357 .isEmergencyNumber(any()); 358 doReturn(false).when(mComponentContextFixture.getTelephonyManager()) 359 .isPotentialEmergencyNumber(any()); 360 361 // First set up information about the In-Call services in the mock Context, since 362 // Telecom will search for these as soon as it is instantiated 363 setupInCallServices(); 364 365 // Next, create the TelecomSystem, our system under test 366 setupTelecomSystem(); 367 // Need to reset teseting tag here 368 Log.setTag(TESTING_TAG); 369 370 // Finally, register the ConnectionServices with the PhoneAccountRegistrar of the 371 // now-running TelecomSystem 372 setupConnectionServices(); 373 374 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 375 } 376 377 @Override tearDown()378 public void tearDown() throws Exception { 379 mTelecomSystem.getCallsManager().waitOnHandlers(); 380 LinkedList<HandlerThread> handlerThreads = mTelecomSystem.getCallsManager() 381 .getGraphHandlerThreads(); 382 for (HandlerThread handlerThread : handlerThreads) { 383 handlerThread.quitSafely(); 384 } 385 handlerThreads.clear(); 386 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 387 waitForHandlerAction(mHandlerThread.getThreadHandler(), TEST_TIMEOUT); 388 // Bring down the threads that are active. 389 mHandlerThread.quit(); 390 try { 391 mHandlerThread.join(); 392 } catch (InterruptedException e) { 393 // don't do anything 394 } 395 396 mConnectionServiceFocusManager.getHandler().removeCallbacksAndMessages(null); 397 waitForHandlerAction(mConnectionServiceFocusManager.getHandler(), TEST_TIMEOUT); 398 mConnectionServiceFocusManager.getHandler().getLooper().quit(); 399 400 mConnectionServiceFixtureA.waitForHandlerToClear(); 401 mConnectionServiceFixtureB.waitForHandlerToClear(); 402 403 // Print out any incomplete sessions for debugging tests 404 String sessions = Log.getSessionManager().printActiveSessions(); 405 if (!TextUtils.isEmpty(sessions)) { 406 Log.w(this, "Active Sessions:\n" + sessions); 407 } 408 409 mTelecomSystem = null; 410 super.tearDown(); 411 } 412 makeConferenceCall()413 protected ParcelableCall makeConferenceCall() throws Exception { 414 IdPair callId1 = startAndMakeActiveOutgoingCall("650-555-1212", 415 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 416 417 IdPair callId2 = startAndMakeActiveOutgoingCall("650-555-1213", 418 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 419 420 IInCallAdapter inCallAdapter = mInCallServiceFixtureX.getInCallAdapter(); 421 inCallAdapter.conference(callId1.mCallId, callId2.mCallId); 422 // Wait for the handler in ConnectionService 423 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 424 ParcelableCall call1 = mInCallServiceFixtureX.getCall(callId1.mCallId); 425 ParcelableCall call2 = mInCallServiceFixtureX.getCall(callId2.mCallId); 426 // Check that the two calls end up with a parent in the end 427 assertNotNull(call1.getParentCallId()); 428 assertNotNull(call2.getParentCallId()); 429 assertEquals(call1.getParentCallId(), call2.getParentCallId()); 430 431 // Check to make sure that the parent call made it to the in-call service 432 String parentCallId = call1.getParentCallId(); 433 ParcelableCall conferenceCall = mInCallServiceFixtureX.getCall(parentCallId); 434 assertEquals(2, conferenceCall.getChildCallIds().size()); 435 assertTrue(conferenceCall.getChildCallIds().contains(callId1.mCallId)); 436 assertTrue(conferenceCall.getChildCallIds().contains(callId2.mCallId)); 437 return conferenceCall; 438 } 439 setupTelecomSystem()440 private void setupTelecomSystem() throws Exception { 441 // Remove any cached PhoneAccount xml 442 File phoneAccountFile = 443 new File(mComponentContextFixture.getTestDouble() 444 .getApplicationContext().getFilesDir(), 445 PhoneAccountRegistrar.FILE_NAME); 446 if (phoneAccountFile.exists()) { 447 phoneAccountFile.delete(); 448 } 449 450 // Use actual implementations instead of mocking the interface out. 451 HeadsetMediaButtonFactory headsetMediaButtonFactory = 452 spy(new HeadsetMediaButtonFactoryF()); 453 ProximitySensorManagerFactory proximitySensorManagerFactory = 454 spy(new ProximitySensorManagerFactoryF()); 455 InCallWakeLockControllerFactory inCallWakeLockControllerFactory = 456 spy(new InCallWakeLockControllerFactoryF()); 457 mAudioService = setupAudioService(); 458 459 mCallerInfoAsyncQueryFactoryFixture = new CallerInfoAsyncQueryFactoryFixture(); 460 461 ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory mConnServFMFactory = 462 requester -> { 463 mConnectionServiceFocusManager = new ConnectionServiceFocusManager(requester); 464 return mConnectionServiceFocusManager; 465 }; 466 467 mTimeoutsAdapter = mock(Timeouts.Adapter.class); 468 when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class))) 469 .thenReturn(TEST_TIMEOUT / 5L); 470 mIncomingCallNotifier = mock(IncomingCallNotifier.class); 471 mClockProxy = mock(ClockProxy.class); 472 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME); 473 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME); 474 when(mRoleManagerAdapter.getCallCompanionApps()).thenReturn(Collections.emptyList()); 475 when(mRoleManagerAdapter.getDefaultCallScreeningApp()).thenReturn(null); 476 mTelecomSystem = new TelecomSystem( 477 mComponentContextFixture.getTestDouble(), 478 (context, phoneAccountRegistrar, defaultDialerCache) -> mMissedCallNotifier, 479 mCallerInfoAsyncQueryFactoryFixture.getTestDouble(), 480 headsetMediaButtonFactory, 481 proximitySensorManagerFactory, 482 inCallWakeLockControllerFactory, 483 () -> mAudioService, 484 (context, lock, callsManager, phoneAccountRegistrar) -> mBluetoothPhoneServiceImpl, 485 mConnServFMFactory, 486 mTimeoutsAdapter, 487 mAsyncRingtonePlayer, 488 new PhoneNumberUtilsAdapterImpl(), 489 mIncomingCallNotifier, 490 (streamType, volume) -> mToneGenerator, 491 new CallAudioRouteStateMachine.Factory() { 492 @Override 493 public CallAudioRouteStateMachine create( 494 Context context, 495 CallsManager callsManager, 496 BluetoothRouteManager bluetoothManager, 497 WiredHeadsetManager wiredHeadsetManager, 498 StatusBarNotifier statusBarNotifier, 499 CallAudioManager.AudioServiceFactory audioServiceFactory, 500 int earpieceControl) { 501 return new CallAudioRouteStateMachine(context, 502 callsManager, 503 bluetoothManager, 504 wiredHeadsetManager, 505 statusBarNotifier, 506 audioServiceFactory, 507 // Force enable an earpiece for the end-to-end tests 508 CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED, 509 mHandlerThread.getLooper()); 510 } 511 }, 512 new CallAudioModeStateMachine.Factory() { 513 @Override 514 public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper, 515 AudioManager am) { 516 return new CallAudioModeStateMachine(systemStateHelper, am, 517 mHandlerThread.getLooper()); 518 } 519 }, 520 mClockProxy, 521 mRoleManagerAdapter, 522 new IncomingCallFilter.Factory() { 523 @Override 524 public IncomingCallFilter create(Context context, 525 CallFilterResultCallback listener, com.android.server.telecom.Call call, 526 TelecomSystem.SyncRoot lock, Timeouts.Adapter timeoutsAdapter, 527 List<IncomingCallFilter.CallFilter> filters) { 528 return new IncomingCallFilter(context, listener, call, lock, 529 timeoutsAdapter, filters, mHandlerThread.getThreadHandler()); 530 } 531 }, 532 new ContactsAsyncHelper.Factory() { 533 @Override 534 public ContactsAsyncHelper create( 535 ContactsAsyncHelper.ContentResolverAdapter adapter) { 536 return new ContactsAsyncHelper(adapter, mHandlerThread.getLooper()); 537 } 538 }); 539 540 mComponentContextFixture.setTelecomManager(new TelecomManager( 541 mComponentContextFixture.getTestDouble(), 542 mTelecomSystem.getTelecomServiceImpl().getBinder())); 543 544 verify(headsetMediaButtonFactory).create( 545 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 546 any(CallsManager.class), 547 any(TelecomSystem.SyncRoot.class)); 548 verify(proximitySensorManagerFactory).create( 549 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 550 any(CallsManager.class)); 551 verify(inCallWakeLockControllerFactory).create( 552 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 553 any(CallsManager.class)); 554 } 555 setupConnectionServices()556 private void setupConnectionServices() throws Exception { 557 mConnectionServiceFixtureA = new ConnectionServiceFixture(mContext); 558 mConnectionServiceFixtureB = new ConnectionServiceFixture(mContext); 559 560 mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameA, 561 mConnectionServiceFixtureA.getTestDouble()); 562 mComponentContextFixture.addConnectionService(mConnectionServiceComponentNameB, 563 mConnectionServiceFixtureB.getTestDouble()); 564 565 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0); 566 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1); 567 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA2); 568 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountSelfManaged); 569 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0); 570 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE0); 571 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE1); 572 573 mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount( 574 mPhoneAccountA0.getAccountHandle(), Process.myUserHandle()); 575 } 576 setupInCallServices()577 private void setupInCallServices() throws Exception { 578 mComponentContextFixture.putResource( 579 com.android.internal.R.string.config_defaultDialer, 580 mInCallServiceComponentNameX.getPackageName()); 581 mComponentContextFixture.putResource( 582 com.android.server.telecom.R.string.incall_default_class, 583 mInCallServiceComponentNameX.getClassName()); 584 585 doReturn(true).when(mComponentContextFixture.getTelephonyManager()) 586 .isVoiceCapable(); 587 588 mInCallServiceFixtureX = new InCallServiceFixture(); 589 mInCallServiceFixtureY = new InCallServiceFixture(); 590 591 mComponentContextFixture.addInCallService(mInCallServiceComponentNameX, 592 mInCallServiceFixtureX.getTestDouble(), SERVICE_X_UID); 593 mComponentContextFixture.addInCallService(mInCallServiceComponentNameY, 594 mInCallServiceFixtureY.getTestDouble(), SERVICE_Y_UID); 595 } 596 597 /** 598 * Helper method for setting up the fake audio service. 599 * Calls to the fake audio service need to toggle the return 600 * value of AudioManager#isMicrophoneMute. 601 * @return mock of IAudioService 602 */ setupAudioService()603 private IAudioService setupAudioService() { 604 IAudioService audioService = mock(IAudioService.class); 605 606 final AudioManager fakeAudioManager = 607 (AudioManager) mComponentContextFixture.getTestDouble() 608 .getApplicationContext().getSystemService(Context.AUDIO_SERVICE); 609 610 try { 611 doAnswer(new Answer() { 612 @Override 613 public Object answer(InvocationOnMock i) { 614 Object[] args = i.getArguments(); 615 doReturn(args[0]).when(fakeAudioManager).isMicrophoneMute(); 616 return null; 617 } 618 }).when(audioService) 619 .setMicrophoneMute(any(Boolean.class), any(String.class), any(Integer.class)); 620 621 } catch (android.os.RemoteException e) { 622 // Do nothing, leave the faked microphone state as-is 623 } 624 return audioService; 625 } 626 startOutgoingPhoneCallWithNoPhoneAccount(String number, ConnectionServiceFixture connectionServiceFixture)627 protected String startOutgoingPhoneCallWithNoPhoneAccount(String number, 628 ConnectionServiceFixture connectionServiceFixture) 629 throws Exception { 630 631 startOutgoingPhoneCallWaitForBroadcaster(number, null, 632 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY, 633 false /*isEmergency*/); 634 635 return mInCallServiceFixtureX.mLatestCallId; 636 } 637 outgoingCallPhoneAccountSelected(PhoneAccountHandle phoneAccountHandle, int startingNumConnections, int startingNumCalls, ConnectionServiceFixture connectionServiceFixture)638 protected IdPair outgoingCallPhoneAccountSelected(PhoneAccountHandle phoneAccountHandle, 639 int startingNumConnections, int startingNumCalls, 640 ConnectionServiceFixture connectionServiceFixture) throws Exception { 641 642 IdPair ids = outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls, 643 phoneAccountHandle, connectionServiceFixture); 644 645 connectionServiceFixture.sendSetDialing(ids.mConnectionId); 646 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 647 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 648 649 connectionServiceFixture.sendSetVideoState(ids.mConnectionId); 650 651 connectionServiceFixture.sendSetActive(ids.mConnectionId); 652 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 653 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 654 655 return ids; 656 } 657 startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser)658 protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, 659 ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser) 660 throws Exception { 661 662 return startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture, 663 initiatingUser, VideoProfile.STATE_AUDIO_ONLY); 664 } 665 startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState)666 protected IdPair startOutgoingPhoneCall(String number, PhoneAccountHandle phoneAccountHandle, 667 ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, 668 int videoState) throws Exception { 669 int startingNumConnections = connectionServiceFixture.mConnectionById.size(); 670 int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 671 672 startOutgoingPhoneCallPendingCreateConnection(number, phoneAccountHandle, 673 connectionServiceFixture, initiatingUser, videoState); 674 675 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT)) 676 .createConnectionComplete(anyString(), any()); 677 678 return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls, 679 phoneAccountHandle, connectionServiceFixture); 680 } 681 triggerEmergencyRedial(PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, IdPair emergencyIds)682 protected IdPair triggerEmergencyRedial(PhoneAccountHandle phoneAccountHandle, 683 ConnectionServiceFixture connectionServiceFixture, IdPair emergencyIds) 684 throws Exception { 685 int startingNumConnections = connectionServiceFixture.mConnectionById.size(); 686 int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 687 688 // Send the message to disconnect the Emergency call due to an error. 689 // CreateConnectionProcessor should now try the second SIM account 690 connectionServiceFixture.sendSetDisconnected(emergencyIds.mConnectionId, 691 DisconnectCause.ERROR); 692 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 693 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall( 694 emergencyIds.mCallId).getState()); 695 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall( 696 emergencyIds.mCallId).getState()); 697 698 return redialingCallCreateConnectionComplete(startingNumConnections, startingNumCalls, 699 phoneAccountHandle, connectionServiceFixture); 700 } 701 startOutgoingEmergencyCall(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState)702 protected IdPair startOutgoingEmergencyCall(String number, 703 PhoneAccountHandle phoneAccountHandle, 704 ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, 705 int videoState) throws Exception { 706 int startingNumConnections = connectionServiceFixture.mConnectionById.size(); 707 int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 708 709 doReturn(true).when(mComponentContextFixture.getTelephonyManager()) 710 .isEmergencyNumber(any()); 711 doReturn(true).when(mComponentContextFixture.getTelephonyManager()) 712 .isPotentialEmergencyNumber(any()); 713 714 // Call will not use the ordered broadcaster, since it is an Emergency Call 715 startOutgoingPhoneCallWaitForBroadcaster(number, phoneAccountHandle, 716 connectionServiceFixture, initiatingUser, videoState, true /*isEmergency*/); 717 718 return outgoingCallCreateConnectionComplete(startingNumConnections, startingNumCalls, 719 phoneAccountHandle, connectionServiceFixture); 720 } 721 startOutgoingPhoneCallWaitForBroadcaster(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState, boolean isEmergency)722 protected void startOutgoingPhoneCallWaitForBroadcaster(String number, 723 PhoneAccountHandle phoneAccountHandle, 724 ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, 725 int videoState, boolean isEmergency) throws Exception { 726 reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(), 727 mInCallServiceFixtureY.getTestDouble()); 728 729 assertEquals(mInCallServiceFixtureX.mCallById.size(), 730 mInCallServiceFixtureY.mCallById.size()); 731 assertEquals((mInCallServiceFixtureX.mInCallAdapter != null), 732 (mInCallServiceFixtureY.mInCallAdapter != null)); 733 734 mNumOutgoingCallsMade++; 735 736 boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null; 737 738 Intent actionCallIntent = new Intent(); 739 actionCallIntent.setData(Uri.parse("tel:" + number)); 740 actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); 741 if(isEmergency) { 742 actionCallIntent.setAction(Intent.ACTION_CALL_EMERGENCY); 743 } else { 744 actionCallIntent.setAction(Intent.ACTION_CALL); 745 } 746 if (phoneAccountHandle != null) { 747 actionCallIntent.putExtra( 748 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, 749 phoneAccountHandle); 750 } 751 if (videoState != VideoProfile.STATE_AUDIO_ONLY) { 752 actionCallIntent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState); 753 } 754 755 final UserHandle userHandle = initiatingUser; 756 Context localAppContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 757 new UserCallIntentProcessor(localAppContext, userHandle).processIntent( 758 actionCallIntent, null, true /* hasCallAppOp*/, false /* isLocal */); 759 // Wait for handler to start CallerInfo lookup. 760 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 761 // Send the CallerInfo lookup reply. 762 mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach( 763 CallerInfoAsyncQueryFactoryFixture.Request::reply); 764 if (phoneAccountHandle != null) { 765 mTelecomSystem.getCallsManager().getLatestPostSelectionProcessingFuture().join(); 766 } 767 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 768 769 boolean isSelfManaged = phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle(); 770 if (!hasInCallAdapter && !isSelfManaged) { 771 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 772 .setInCallAdapter( 773 any(IInCallAdapter.class)); 774 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 775 .setInCallAdapter( 776 any(IInCallAdapter.class)); 777 } 778 } 779 startOutgoingPhoneCallPendingCreateConnection(String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, int videoState)780 protected String startOutgoingPhoneCallPendingCreateConnection(String number, 781 PhoneAccountHandle phoneAccountHandle, 782 ConnectionServiceFixture connectionServiceFixture, UserHandle initiatingUser, 783 int videoState) throws Exception { 784 startOutgoingPhoneCallWaitForBroadcaster(number,phoneAccountHandle, 785 connectionServiceFixture, initiatingUser, videoState, false /*isEmergency*/); 786 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 787 788 verifyAndProcessOutgoingCallBroadcast(phoneAccountHandle); 789 return mInCallServiceFixtureX.mLatestCallId; 790 } 791 verifyAndProcessOutgoingCallBroadcast(PhoneAccountHandle phoneAccountHandle)792 protected void verifyAndProcessOutgoingCallBroadcast(PhoneAccountHandle phoneAccountHandle) { 793 ArgumentCaptor<Intent> newOutgoingCallIntent = 794 ArgumentCaptor.forClass(Intent.class); 795 ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver = 796 ArgumentCaptor.forClass(BroadcastReceiver.class); 797 798 if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) { 799 verify(mComponentContextFixture.getTestDouble().getApplicationContext(), 800 times(mNumOutgoingCallsMade)) 801 .sendOrderedBroadcastAsUser( 802 newOutgoingCallIntent.capture(), 803 any(UserHandle.class), 804 anyString(), 805 anyInt(), 806 any(Bundle.class), 807 newOutgoingCallReceiver.capture(), 808 nullable(Handler.class), 809 anyInt(), 810 anyString(), 811 nullable(Bundle.class)); 812 // Pass on the new outgoing call Intent 813 // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive() 814 newOutgoingCallReceiver.getValue().setPendingResult( 815 new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0)); 816 newOutgoingCallReceiver.getValue().setResultData( 817 newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 818 newOutgoingCallReceiver.getValue().onReceive(mComponentContextFixture.getTestDouble(), 819 newOutgoingCallIntent.getValue()); 820 } 821 822 } 823 824 // When Telecom is redialing due to an error, we need to make sure the number of connections 825 // increase, but not the number of Calls in the InCallService. redialingCallCreateConnectionComplete(int startingNumConnections, int startingNumCalls, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)826 protected IdPair redialingCallCreateConnectionComplete(int startingNumConnections, 827 int startingNumCalls, PhoneAccountHandle phoneAccountHandle, 828 ConnectionServiceFixture connectionServiceFixture) throws Exception { 829 830 assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size()); 831 832 verify(connectionServiceFixture.getTestDouble()) 833 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class), 834 eq(false)/*isIncoming*/, anyBoolean(), any()); 835 // Wait for handleCreateConnectionComplete 836 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 837 838 // Make sure the number of registered InCallService Calls stays the same. 839 assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size()); 840 assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size()); 841 842 assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId); 843 844 return new IdPair(connectionServiceFixture.mLatestConnectionId, 845 mInCallServiceFixtureX.mLatestCallId); 846 } 847 outgoingCallCreateConnectionComplete(int startingNumConnections, int startingNumCalls, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)848 protected IdPair outgoingCallCreateConnectionComplete(int startingNumConnections, 849 int startingNumCalls, PhoneAccountHandle phoneAccountHandle, 850 ConnectionServiceFixture connectionServiceFixture) throws Exception { 851 852 // Wait for the focus tracker. 853 waitForHandlerAction(mTelecomSystem.getCallsManager() 854 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT); 855 856 verify(connectionServiceFixture.getTestDouble()) 857 .createConnection(eq(phoneAccountHandle), anyString(), any(ConnectionRequest.class), 858 eq(false)/*isIncoming*/, anyBoolean(), any()); 859 // Wait for handleCreateConnectionComplete 860 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 861 assertEquals(startingNumConnections + 1, 862 connectionServiceFixture.mConnectionById.size()); 863 864 // Wait for the callback in ConnectionService#onAdapterAttached to execute. 865 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 866 867 // Ensure callback to CS on successful creation happened. 868 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT)) 869 .createConnectionComplete(anyString(), any()); 870 871 if (phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle()) { 872 assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size()); 873 assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size()); 874 } else { 875 assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size()); 876 assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size()); 877 } 878 879 assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId); 880 881 return new IdPair(connectionServiceFixture.mLatestConnectionId, 882 mInCallServiceFixtureX.mLatestCallId); 883 } 884 startIncomingPhoneCall( String number, PhoneAccountHandle phoneAccountHandle, final ConnectionServiceFixture connectionServiceFixture)885 protected IdPair startIncomingPhoneCall( 886 String number, 887 PhoneAccountHandle phoneAccountHandle, 888 final ConnectionServiceFixture connectionServiceFixture) throws Exception { 889 return startIncomingPhoneCall(number, phoneAccountHandle, VideoProfile.STATE_AUDIO_ONLY, 890 connectionServiceFixture); 891 } 892 startIncomingPhoneCall( String number, PhoneAccountHandle phoneAccountHandle, int videoState, final ConnectionServiceFixture connectionServiceFixture)893 protected IdPair startIncomingPhoneCall( 894 String number, 895 PhoneAccountHandle phoneAccountHandle, 896 int videoState, 897 final ConnectionServiceFixture connectionServiceFixture) throws Exception { 898 reset(connectionServiceFixture.getTestDouble(), mInCallServiceFixtureX.getTestDouble(), 899 mInCallServiceFixtureY.getTestDouble()); 900 901 assertEquals(mInCallServiceFixtureX.mCallById.size(), 902 mInCallServiceFixtureY.mCallById.size()); 903 assertEquals((mInCallServiceFixtureX.mInCallAdapter != null), 904 (mInCallServiceFixtureY.mInCallAdapter != null)); 905 final int startingNumConnections = connectionServiceFixture.mConnectionById.size(); 906 final int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 907 boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null; 908 connectionServiceFixture.mConnectionServiceDelegate.mVideoState = videoState; 909 CountDownLatch incomingCallAddedLatch = new CountDownLatch(1); 910 IncomingCallAddedListener callAddedListener = 911 new IncomingCallAddedListener(incomingCallAddedLatch); 912 mTelecomSystem.getCallsManager().addListener(callAddedListener); 913 914 Bundle extras = new Bundle(); 915 extras.putParcelable( 916 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 917 Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null)); 918 mTelecomSystem.getTelecomServiceImpl().getBinder() 919 .addNewIncomingCall(phoneAccountHandle, extras); 920 921 verify(connectionServiceFixture.getTestDouble()) 922 .createConnection(any(PhoneAccountHandle.class), anyString(), 923 any(ConnectionRequest.class), eq(true), eq(false), any()); 924 925 // Wait for the handler to start the CallerInfo lookup 926 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 927 928 // Ensure callback to CS on successful creation happened. 929 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT)) 930 .createConnectionComplete(anyString(), any()); 931 932 // Process the CallerInfo lookup reply 933 mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach( 934 CallerInfoAsyncQueryFactoryFixture.Request::reply); 935 936 //Wait for/Verify call blocking happened asynchronously 937 incomingCallAddedLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 938 939 // For the case of incoming calls, Telecom connecting the InCall services and adding the 940 // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call 941 // is added, future interactions as triggered by the ConnectionService, through the various 942 // test fixtures, will be synchronous. 943 944 if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) { 945 if (!hasInCallAdapter) { 946 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 947 .setInCallAdapter(any(IInCallAdapter.class)); 948 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 949 .setInCallAdapter(any(IInCallAdapter.class)); 950 951 // Give the InCallService time to respond 952 assertTrueWithTimeout(new Predicate<Void>() { 953 @Override 954 public boolean apply(Void v) { 955 return mInCallServiceFixtureX.mInCallAdapter != null; 956 } 957 }); 958 959 assertTrueWithTimeout(new Predicate<Void>() { 960 @Override 961 public boolean apply(Void v) { 962 return mInCallServiceFixtureY.mInCallAdapter != null; 963 } 964 }); 965 966 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 967 .addCall(any(ParcelableCall.class)); 968 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 969 .addCall(any(ParcelableCall.class)); 970 971 // Give the InCallService time to respond 972 } 973 974 assertTrueWithTimeout(new Predicate<Void>() { 975 @Override 976 public boolean apply(Void v) { 977 return startingNumConnections + 1 == 978 connectionServiceFixture.mConnectionById.size(); 979 } 980 }); 981 982 mInCallServiceFixtureX.waitUntilNumCalls(startingNumCalls + 1); 983 mInCallServiceFixtureY.waitUntilNumCalls(startingNumCalls + 1); 984 assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size()); 985 assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size()); 986 987 assertEquals(mInCallServiceFixtureX.mLatestCallId, 988 mInCallServiceFixtureY.mLatestCallId); 989 } 990 991 return new IdPair(connectionServiceFixture.mLatestConnectionId, 992 mInCallServiceFixtureX.mLatestCallId); 993 } 994 startAndMakeActiveOutgoingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)995 protected IdPair startAndMakeActiveOutgoingCall( 996 String number, 997 PhoneAccountHandle phoneAccountHandle, 998 ConnectionServiceFixture connectionServiceFixture) throws Exception { 999 return startAndMakeActiveOutgoingCall(number, phoneAccountHandle, connectionServiceFixture, 1000 VideoProfile.STATE_AUDIO_ONLY); 1001 } 1002 1003 // A simple outgoing call, verifying that the appropriate connection service is contacted, 1004 // the proper lifecycle is followed, and both In-Call Services are updated correctly. startAndMakeActiveOutgoingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, int videoState)1005 protected IdPair startAndMakeActiveOutgoingCall( 1006 String number, 1007 PhoneAccountHandle phoneAccountHandle, 1008 ConnectionServiceFixture connectionServiceFixture, int videoState) throws Exception { 1009 IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture, 1010 Process.myUserHandle(), videoState); 1011 1012 connectionServiceFixture.sendSetDialing(ids.mConnectionId); 1013 if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) { 1014 assertEquals(Call.STATE_DIALING, 1015 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1016 assertEquals(Call.STATE_DIALING, 1017 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 1018 } 1019 1020 connectionServiceFixture.sendSetVideoState(ids.mConnectionId); 1021 1022 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME); 1023 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME); 1024 connectionServiceFixture.sendSetActive(ids.mConnectionId); 1025 if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) { 1026 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1027 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 1028 1029 if ((mInCallServiceFixtureX.getCall(ids.mCallId).getProperties() & 1030 Call.Details.PROPERTY_IS_EXTERNAL_CALL) == 0) { 1031 // Test the PhoneStateBroadcaster functionality if the call is not external. 1032 verify(mContext.getSystemService(TelephonyRegistryManager.class), 1033 timeout(TEST_TIMEOUT).atLeastOnce()) 1034 .notifyCallStateChangedForAllSubscriptions( 1035 eq(TelephonyManager.CALL_STATE_OFFHOOK), 1036 nullable(String.class)); 1037 } 1038 } 1039 return ids; 1040 } 1041 startAndMakeActiveIncomingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1042 protected IdPair startAndMakeActiveIncomingCall( 1043 String number, 1044 PhoneAccountHandle phoneAccountHandle, 1045 ConnectionServiceFixture connectionServiceFixture) throws Exception { 1046 return startAndMakeActiveIncomingCall(number, phoneAccountHandle, connectionServiceFixture, 1047 VideoProfile.STATE_AUDIO_ONLY); 1048 } 1049 1050 // A simple incoming call, similar in scope to the previous test startAndMakeActiveIncomingCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture, int videoState)1051 protected IdPair startAndMakeActiveIncomingCall( 1052 String number, 1053 PhoneAccountHandle phoneAccountHandle, 1054 ConnectionServiceFixture connectionServiceFixture, 1055 int videoState) throws Exception { 1056 IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture); 1057 1058 if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) { 1059 assertEquals(Call.STATE_RINGING, 1060 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1061 assertEquals(Call.STATE_RINGING, 1062 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 1063 1064 mInCallServiceFixtureX.mInCallAdapter 1065 .answerCall(ids.mCallId, videoState); 1066 // Wait on the CS focus manager handler 1067 waitForHandlerAction(mTelecomSystem.getCallsManager() 1068 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT); 1069 1070 if (!VideoProfile.isVideo(videoState)) { 1071 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT)) 1072 .answer(eq(ids.mConnectionId), any()); 1073 } else { 1074 verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT)) 1075 .answerVideo(eq(ids.mConnectionId), eq(videoState), any()); 1076 } 1077 } 1078 1079 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME); 1080 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME); 1081 connectionServiceFixture.sendSetActive(ids.mConnectionId); 1082 1083 if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) { 1084 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1085 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 1086 1087 if ((mInCallServiceFixtureX.getCall(ids.mCallId).getProperties() & 1088 Call.Details.PROPERTY_IS_EXTERNAL_CALL) == 0) { 1089 // Test the PhoneStateBroadcaster functionality if the call is not external. 1090 verify(mContext.getSystemService(TelephonyRegistryManager.class), 1091 timeout(TEST_TIMEOUT).atLeastOnce()) 1092 .notifyCallStateChangedForAllSubscriptions( 1093 eq(TelephonyManager.CALL_STATE_OFFHOOK), 1094 nullable(String.class)); 1095 } 1096 } 1097 return ids; 1098 } 1099 startAndMakeDialingEmergencyCall( String number, PhoneAccountHandle phoneAccountHandle, ConnectionServiceFixture connectionServiceFixture)1100 protected IdPair startAndMakeDialingEmergencyCall( 1101 String number, 1102 PhoneAccountHandle phoneAccountHandle, 1103 ConnectionServiceFixture connectionServiceFixture) throws Exception { 1104 IdPair ids = startOutgoingEmergencyCall(number, phoneAccountHandle, 1105 connectionServiceFixture, Process.myUserHandle(), VideoProfile.STATE_AUDIO_ONLY); 1106 1107 connectionServiceFixture.sendSetDialing(ids.mConnectionId); 1108 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1109 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 1110 1111 return ids; 1112 } 1113 assertTrueWithTimeout(Predicate<Void> predicate)1114 protected static void assertTrueWithTimeout(Predicate<Void> predicate) { 1115 int elapsed = 0; 1116 while (elapsed < TEST_TIMEOUT) { 1117 if (predicate.apply(null)) { 1118 return; 1119 } else { 1120 try { 1121 Thread.sleep(TEST_POLL_INTERVAL); 1122 elapsed += TEST_POLL_INTERVAL; 1123 } catch (InterruptedException e) { 1124 fail(e.toString()); 1125 } 1126 } 1127 } 1128 fail("Timeout in assertTrueWithTimeout"); 1129 } 1130 } 1131