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