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