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