TelecomSystemTest.java revision 1d903ddbf915a4aef4925a0e90042e76151c97a9
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 17package com.android.server.telecom.tests; 18 19import com.google.common.base.Predicate; 20 21import static org.mockito.Matchers.any; 22import static org.mockito.Matchers.anyBoolean; 23import static org.mockito.Matchers.anyInt; 24import static org.mockito.Matchers.anyString; 25import static org.mockito.Matchers.eq; 26import static org.mockito.Mockito.mock; 27import static org.mockito.Mockito.reset; 28import static org.mockito.Mockito.timeout; 29import static org.mockito.Mockito.verify; 30import static org.mockito.Mockito.when; 31 32import android.content.BroadcastReceiver; 33import android.content.ComponentName; 34import android.content.Context; 35import android.content.Intent; 36import android.media.AudioManager; 37import android.net.Uri; 38import android.os.Bundle; 39import android.os.Handler; 40import android.os.UserHandle; 41import android.telecom.Call; 42import android.telecom.CallAudioState; 43import android.telecom.Connection; 44import android.telecom.ConnectionRequest; 45import android.telecom.DisconnectCause; 46import android.telecom.ParcelableCall; 47import android.telecom.PhoneAccount; 48import android.telecom.PhoneAccountHandle; 49import android.telecom.TelecomManager; 50import android.telecom.VideoProfile; 51import android.telephony.TelephonyManager; 52 53import com.android.internal.telecom.IInCallAdapter; 54import com.android.server.telecom.CallsManager; 55import com.android.server.telecom.HeadsetMediaButton; 56import com.android.server.telecom.HeadsetMediaButtonFactory; 57import com.android.server.telecom.InCallWakeLockController; 58import com.android.server.telecom.InCallWakeLockControllerFactory; 59import com.android.server.telecom.Log; 60import com.android.server.telecom.MissedCallNotifier; 61import com.android.server.telecom.ProximitySensorManager; 62import com.android.server.telecom.ProximitySensorManagerFactory; 63import com.android.server.telecom.TelecomSystem; 64 65import org.mockito.ArgumentCaptor; 66import org.mockito.Mock; 67 68import java.util.concurrent.BrokenBarrierException; 69import java.util.concurrent.CountDownLatch; 70import java.util.concurrent.CyclicBarrier; 71 72public class TelecomSystemTest extends TelecomTestCase { 73 74 static final int TEST_POLL_INTERVAL = 10; // milliseconds 75 static final int TEST_TIMEOUT = 1000; // milliseconds 76 77 @Mock MissedCallNotifier mMissedCallNotifier; 78 @Mock HeadsetMediaButton mHeadsetMediaButton; 79 @Mock ProximitySensorManager mProximitySensorManager; 80 @Mock InCallWakeLockController mInCallWakeLockController; 81 82 final ComponentName mInCallServiceComponentNameX = 83 new ComponentName( 84 "incall-service-package-X", 85 "incall-service-class-X"); 86 final ComponentName mInCallServiceComponentNameY = 87 new ComponentName( 88 "incall-service-package-Y", 89 "incall-service-class-Y"); 90 91 InCallServiceFixture mInCallServiceFixtureX; 92 InCallServiceFixture mInCallServiceFixtureY; 93 94 final ComponentName mConnectionServiceComponentNameA = 95 new ComponentName( 96 "connection-service-package-A", 97 "connection-service-class-A"); 98 final ComponentName mConnectionServiceComponentNameB = 99 new ComponentName( 100 "connection-service-package-B", 101 "connection-service-class-B"); 102 103 final PhoneAccount mPhoneAccountA0 = 104 PhoneAccount.builder( 105 new PhoneAccountHandle( 106 mConnectionServiceComponentNameA, 107 "id A 0"), 108 "Phone account service A ID 0") 109 .addSupportedUriScheme("tel") 110 .setCapabilities( 111 PhoneAccount.CAPABILITY_CALL_PROVIDER | 112 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 113 .build(); 114 final PhoneAccount mPhoneAccountA1 = 115 PhoneAccount.builder( 116 new PhoneAccountHandle( 117 mConnectionServiceComponentNameA, 118 "id A 1"), 119 "Phone account service A ID 1") 120 .addSupportedUriScheme("tel") 121 .setCapabilities( 122 PhoneAccount.CAPABILITY_CALL_PROVIDER | 123 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 124 .build(); 125 final PhoneAccount mPhoneAccountB0 = 126 PhoneAccount.builder( 127 new PhoneAccountHandle( 128 mConnectionServiceComponentNameB, 129 "id B 0"), 130 "Phone account service B ID 0") 131 .addSupportedUriScheme("tel") 132 .setCapabilities( 133 PhoneAccount.CAPABILITY_CALL_PROVIDER | 134 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 135 .build(); 136 137 ConnectionServiceFixture mConnectionServiceFixtureA; 138 ConnectionServiceFixture mConnectionServiceFixtureB; 139 140 CallerInfoAsyncQueryFactoryFixture mCallerInfoAsyncQueryFactoryFixture; 141 142 TelecomSystem mTelecomSystem; 143 144 class IdPair { 145 final String mConnectionId; 146 final String mCallId; 147 148 public IdPair(String connectionId, String callId) { 149 this.mConnectionId = connectionId; 150 this.mCallId = callId; 151 } 152 } 153 154 @Override 155 public void setUp() throws Exception { 156 super.setUp(); 157 158 // First set up information about the In-Call services in the mock Context, since 159 // Telecom will search for these as soon as it is instantiated 160 setupInCallServices(); 161 162 // Next, create the TelecomSystem, our system under test 163 setupTelecomSystem(); 164 165 // Finally, register the ConnectionServices with the PhoneAccountRegistrar of the 166 // now-running TelecomSystem 167 setupConnectionServices(); 168 } 169 170 @Override 171 public void tearDown() throws Exception { 172 mTelecomSystem = null; 173 super.tearDown(); 174 } 175 176 private void setupTelecomSystem() throws Exception { 177 HeadsetMediaButtonFactory headsetMediaButtonFactory = 178 mock(HeadsetMediaButtonFactory.class); 179 ProximitySensorManagerFactory proximitySensorManagerFactory = 180 mock(ProximitySensorManagerFactory.class); 181 InCallWakeLockControllerFactory inCallWakeLockControllerFactory = 182 mock(InCallWakeLockControllerFactory.class); 183 184 mCallerInfoAsyncQueryFactoryFixture = new CallerInfoAsyncQueryFactoryFixture(); 185 186 when(headsetMediaButtonFactory.create( 187 any(Context.class), 188 any(CallsManager.class), 189 any(TelecomSystem.SyncRoot.class))) 190 .thenReturn(mHeadsetMediaButton); 191 when(proximitySensorManagerFactory.create( 192 any(Context.class), 193 any(CallsManager.class))) 194 .thenReturn(mProximitySensorManager); 195 when(inCallWakeLockControllerFactory.create( 196 any(Context.class), 197 any(CallsManager.class))) 198 .thenReturn(mInCallWakeLockController); 199 200 mTelecomSystem = new TelecomSystem( 201 mComponentContextFixture.getTestDouble(), 202 mMissedCallNotifier, 203 mCallerInfoAsyncQueryFactoryFixture.getTestDouble(), 204 headsetMediaButtonFactory, 205 proximitySensorManagerFactory, 206 inCallWakeLockControllerFactory); 207 208 mComponentContextFixture.setTelecomManager(new TelecomManager( 209 mComponentContextFixture.getTestDouble(), 210 mTelecomSystem.getTelecomServiceImpl().getBinder())); 211 212 verify(headsetMediaButtonFactory).create( 213 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 214 any(CallsManager.class), 215 any(TelecomSystem.SyncRoot.class)); 216 verify(proximitySensorManagerFactory).create( 217 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 218 any(CallsManager.class)); 219 verify(inCallWakeLockControllerFactory).create( 220 eq(mComponentContextFixture.getTestDouble().getApplicationContext()), 221 any(CallsManager.class)); 222 } 223 224 private void setupConnectionServices() throws Exception { 225 mConnectionServiceFixtureA = new ConnectionServiceFixture(); 226 mConnectionServiceFixtureB = new ConnectionServiceFixture(); 227 228 mComponentContextFixture.addConnectionService( 229 mConnectionServiceComponentNameA, 230 mConnectionServiceFixtureA.getTestDouble()); 231 mComponentContextFixture.addConnectionService( 232 mConnectionServiceComponentNameB, 233 mConnectionServiceFixtureB.getTestDouble()); 234 235 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0); 236 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1); 237 mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0); 238 239 mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount( 240 mPhoneAccountA0.getAccountHandle()); 241 } 242 243 private void setupInCallServices() throws Exception { 244 mComponentContextFixture.putResource( 245 com.android.server.telecom.R.string.ui_default_package, 246 mInCallServiceComponentNameX.getPackageName()); 247 mComponentContextFixture.putResource( 248 com.android.server.telecom.R.string.incall_default_class, 249 mInCallServiceComponentNameX.getClassName()); 250 251 mInCallServiceFixtureX = new InCallServiceFixture(); 252 mInCallServiceFixtureY = new InCallServiceFixture(); 253 254 mComponentContextFixture.addInCallService( 255 mInCallServiceComponentNameX, 256 mInCallServiceFixtureX.getTestDouble()); 257 mComponentContextFixture.addInCallService( 258 mInCallServiceComponentNameY, 259 mInCallServiceFixtureY.getTestDouble()); 260 } 261 262 private IdPair startOutgoingPhoneCall( 263 String number, 264 PhoneAccountHandle phoneAccountHandle, 265 ConnectionServiceFixture connectionServiceFixture) throws Exception { 266 reset( 267 connectionServiceFixture.getTestDouble(), 268 mInCallServiceFixtureX.getTestDouble(), 269 mInCallServiceFixtureY.getTestDouble()); 270 271 assertEquals( 272 mInCallServiceFixtureX.mCallById.size(), 273 mInCallServiceFixtureY.mCallById.size()); 274 assertEquals( 275 (mInCallServiceFixtureX.mInCallAdapter != null), 276 (mInCallServiceFixtureY.mInCallAdapter != null)); 277 278 int startingNumConnections = connectionServiceFixture.mConnectionById.size(); 279 int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 280 boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null; 281 282 Intent actionCallIntent = new Intent(); 283 actionCallIntent.setData(Uri.parse("tel:" + number)); 284 actionCallIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); 285 actionCallIntent.setAction(Intent.ACTION_CALL); 286 if (phoneAccountHandle != null) { 287 actionCallIntent.putExtra( 288 TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, 289 phoneAccountHandle); 290 } 291 292 mTelecomSystem.getCallIntentProcessor().processIntent(actionCallIntent); 293 294 if (!hasInCallAdapter) { 295 verify(mInCallServiceFixtureX.getTestDouble()) 296 .setInCallAdapter( 297 any(IInCallAdapter.class)); 298 verify(mInCallServiceFixtureY.getTestDouble()) 299 .setInCallAdapter( 300 any(IInCallAdapter.class)); 301 } 302 303 ArgumentCaptor<Intent> newOutgoingCallIntent = 304 ArgumentCaptor.forClass(Intent.class); 305 ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver = 306 ArgumentCaptor.forClass(BroadcastReceiver.class); 307 308 verify(mComponentContextFixture.getTestDouble().getApplicationContext()) 309 .sendOrderedBroadcastAsUser( 310 newOutgoingCallIntent.capture(), 311 any(UserHandle.class), 312 anyString(), 313 anyInt(), 314 newOutgoingCallReceiver.capture(), 315 any(Handler.class), 316 anyInt(), 317 anyString(), 318 any(Bundle.class)); 319 320 // Pass on the new outgoing call Intent 321 // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive() 322 newOutgoingCallReceiver.getValue().setPendingResult( 323 new BroadcastReceiver.PendingResult(0, "", null, 0, true, false, null, 0, 0)); 324 newOutgoingCallReceiver.getValue().setResultData( 325 newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER)); 326 newOutgoingCallReceiver.getValue().onReceive( 327 mComponentContextFixture.getTestDouble(), 328 newOutgoingCallIntent.getValue()); 329 330 assertEquals(startingNumConnections + 1, connectionServiceFixture.mConnectionById.size()); 331 332 verify(connectionServiceFixture.getTestDouble()).createConnection( 333 eq(phoneAccountHandle), 334 anyString(), 335 any(ConnectionRequest.class), 336 anyBoolean(), 337 anyBoolean()); 338 339 connectionServiceFixture.sendHandleCreateConnectionComplete( 340 connectionServiceFixture.mLatestConnectionId); 341 342 assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size()); 343 assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size()); 344 345 assertEquals( 346 mInCallServiceFixtureX.mLatestCallId, 347 mInCallServiceFixtureY.mLatestCallId); 348 349 return new IdPair( 350 connectionServiceFixture.mLatestConnectionId, 351 mInCallServiceFixtureX.mLatestCallId); 352 } 353 354 private IdPair startIncomingPhoneCall( 355 String number, 356 PhoneAccountHandle phoneAccountHandle, 357 final ConnectionServiceFixture connectionServiceFixture) throws Exception { 358 reset( 359 connectionServiceFixture.getTestDouble(), 360 mInCallServiceFixtureX.getTestDouble(), 361 mInCallServiceFixtureY.getTestDouble()); 362 363 assertEquals( 364 mInCallServiceFixtureX.mCallById.size(), 365 mInCallServiceFixtureY.mCallById.size()); 366 assertEquals( 367 (mInCallServiceFixtureX.mInCallAdapter != null), 368 (mInCallServiceFixtureY.mInCallAdapter != null)); 369 370 final int startingNumConnections = connectionServiceFixture.mConnectionById.size(); 371 final int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 372 boolean hasInCallAdapter = mInCallServiceFixtureX.mInCallAdapter != null; 373 374 Bundle extras = new Bundle(); 375 extras.putParcelable( 376 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 377 Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null)); 378 mTelecomSystem.getTelecomServiceImpl().getBinder() 379 .addNewIncomingCall(phoneAccountHandle, extras); 380 381 verify(connectionServiceFixture.getTestDouble()).createConnection( 382 any(PhoneAccountHandle.class), 383 anyString(), 384 any(ConnectionRequest.class), 385 eq(true), 386 eq(false)); 387 388 connectionServiceFixture.sendHandleCreateConnectionComplete( 389 connectionServiceFixture.mLatestConnectionId); 390 connectionServiceFixture.sendSetRinging( 391 connectionServiceFixture.mLatestConnectionId); 392 393 // For the case of incoming calls, Telecom connecting the InCall services and adding the 394 // Call is triggered by the async completion of the CallerInfoAsyncQuery. Once the Call 395 // is added, future interactions as triggered by the ConnectionService, through the various 396 // test fixtures, will be synchronous. 397 398 if (!hasInCallAdapter) { 399 verify( 400 mInCallServiceFixtureX.getTestDouble(), 401 timeout(TEST_TIMEOUT)) 402 .setInCallAdapter( 403 any(IInCallAdapter.class)); 404 verify( 405 mInCallServiceFixtureY.getTestDouble(), 406 timeout(TEST_TIMEOUT)) 407 .setInCallAdapter( 408 any(IInCallAdapter.class)); 409 } 410 411 // Give the InCallService time to respond 412 413 assertTrueWithTimeout(new Predicate<Void>() { 414 @Override 415 public boolean apply(Void v) { 416 return mInCallServiceFixtureX.mInCallAdapter != null; 417 } 418 }); 419 420 assertTrueWithTimeout(new Predicate<Void>() { 421 @Override 422 public boolean apply(Void v) { 423 return mInCallServiceFixtureY.mInCallAdapter != null; 424 } 425 }); 426 427 verify( 428 mInCallServiceFixtureX.getTestDouble(), 429 timeout(TEST_TIMEOUT)) 430 .addCall( 431 any(ParcelableCall.class)); 432 verify( 433 mInCallServiceFixtureY.getTestDouble(), 434 timeout(TEST_TIMEOUT)) 435 .addCall( 436 any(ParcelableCall.class)); 437 438 // Give the InCallService time to respond 439 440 assertTrueWithTimeout(new Predicate<Void>() { 441 @Override 442 public boolean apply(Void v) { 443 return startingNumConnections + 1 == 444 connectionServiceFixture.mConnectionById.size(); 445 } 446 }); 447 assertTrueWithTimeout(new Predicate<Void>() { 448 @Override 449 public boolean apply(Void v) { 450 return startingNumCalls + 1 == mInCallServiceFixtureX.mCallById.size(); 451 } 452 }); 453 assertTrueWithTimeout(new Predicate<Void>() { 454 @Override 455 public boolean apply(Void v) { 456 return startingNumCalls + 1 == mInCallServiceFixtureY.mCallById.size(); 457 } 458 }); 459 460 assertEquals( 461 mInCallServiceFixtureX.mLatestCallId, 462 mInCallServiceFixtureY.mLatestCallId); 463 464 return new IdPair( 465 connectionServiceFixture.mLatestConnectionId, 466 mInCallServiceFixtureX.mLatestCallId); 467 } 468 469 private void rapidFire(Runnable... tasks) { 470 final CyclicBarrier barrier = new CyclicBarrier(tasks.length); 471 final CountDownLatch latch = new CountDownLatch(tasks.length); 472 for (int i = 0; i < tasks.length; i++) { 473 final Runnable task = tasks[i]; 474 new Thread(new Runnable() { 475 @Override 476 public void run() { 477 try { 478 barrier.await(); 479 task.run(); 480 } catch (InterruptedException | BrokenBarrierException e){ 481 Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted"); 482 } finally { 483 latch.countDown(); 484 } 485 } 486 }).start(); 487 } 488 try { 489 latch.await(); 490 } catch (InterruptedException e) { 491 Log.e(TelecomSystemTest.this, e, "Unexpectedly interrupted"); 492 } 493 } 494 495 // A simple outgoing call, verifying that the appropriate connection service is contacted, 496 // the proper lifecycle is followed, and both In-Call Services are updated correctly. 497 private IdPair startAndMakeActiveOutgoingCall( 498 String number, 499 PhoneAccountHandle phoneAccountHandle, 500 ConnectionServiceFixture connectionServiceFixture) throws Exception { 501 IdPair ids = startOutgoingPhoneCall(number, phoneAccountHandle, connectionServiceFixture); 502 503 connectionServiceFixture.sendSetDialing(ids.mConnectionId); 504 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 505 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 506 507 connectionServiceFixture.sendSetActive(ids.mConnectionId); 508 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 509 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 510 511 return ids; 512 } 513 514 public void testSingleOutgoingCallLocalDisconnect() throws Exception { 515 IdPair ids = startAndMakeActiveOutgoingCall( 516 "650-555-1212", 517 mPhoneAccountA0.getAccountHandle(), 518 mConnectionServiceFixtureA); 519 520 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 521 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 522 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 523 524 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 525 assertEquals(Call.STATE_DISCONNECTED, 526 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 527 assertEquals(Call.STATE_DISCONNECTED, 528 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 529 } 530 531 public void testSingleOutgoingCallRemoteDisconnect() throws Exception { 532 IdPair ids = startAndMakeActiveOutgoingCall( 533 "650-555-1212", 534 mPhoneAccountA0.getAccountHandle(), 535 mConnectionServiceFixtureA); 536 537 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 538 assertEquals(Call.STATE_DISCONNECTED, 539 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 540 assertEquals(Call.STATE_DISCONNECTED, 541 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 542 } 543 544 // A simple incoming call, similar in scope to the previous test 545 private IdPair startAndMakeActiveIncomingCall( 546 String number, 547 PhoneAccountHandle phoneAccountHandle, 548 ConnectionServiceFixture connectionServiceFixture) throws Exception { 549 IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture); 550 551 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 552 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 553 554 mInCallServiceFixtureX.mInCallAdapter 555 .answerCall(ids.mCallId, VideoProfile.STATE_AUDIO_ONLY); 556 557 verify(connectionServiceFixture.getTestDouble()) 558 .answer(ids.mConnectionId); 559 560 connectionServiceFixture.sendSetActive(ids.mConnectionId); 561 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 562 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 563 564 return ids; 565 } 566 567 public void testSingleIncomingCallLocalDisconnect() throws Exception { 568 IdPair ids = startAndMakeActiveIncomingCall( 569 "650-555-1212", 570 mPhoneAccountA0.getAccountHandle(), 571 mConnectionServiceFixtureA); 572 573 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 574 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 575 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 576 577 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 578 assertEquals(Call.STATE_DISCONNECTED, 579 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 580 assertEquals(Call.STATE_DISCONNECTED, 581 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 582 } 583 584 public void testSingleIncomingCallRemoteDisconnect() throws Exception { 585 IdPair ids = startAndMakeActiveIncomingCall( 586 "650-555-1212", 587 mPhoneAccountA0.getAccountHandle(), 588 mConnectionServiceFixtureA); 589 590 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 591 assertEquals(Call.STATE_DISCONNECTED, 592 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 593 assertEquals(Call.STATE_DISCONNECTED, 594 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 595 } 596 597 public void do_testDeadlockOnOutgoingCall() throws Exception { 598 final IdPair ids = startOutgoingPhoneCall( 599 "650-555-1212", 600 mPhoneAccountA0.getAccountHandle(), 601 mConnectionServiceFixtureA); 602 rapidFire( 603 new Runnable() { 604 @Override 605 public void run() { 606 while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) { 607 mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply(); 608 } 609 } 610 }, 611 new Runnable() { 612 @Override 613 public void run() { 614 try { 615 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 616 } catch (Exception e) { 617 Log.e(this, e, ""); 618 } 619 } 620 }); 621 } 622 623 public void testDeadlockOnOutgoingCall() throws Exception { 624 for (int i = 0; i < 100; i++) { 625 TelecomSystemTest test = new TelecomSystemTest(); 626 test.setContext(getContext()); 627 test.setTestContext(getTestContext()); 628 test.setName(getName()); 629 test.setUp(); 630 test.do_testDeadlockOnOutgoingCall(); 631 test.tearDown(); 632 } 633 } 634 635 public void testIncomingThenOutgoingCalls() throws Exception { 636 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 637 IdPair incoming = startAndMakeActiveIncomingCall( 638 "650-555-2323", 639 mPhoneAccountA0.getAccountHandle(), 640 mConnectionServiceFixtureA); 641 IdPair outgoing = startAndMakeActiveOutgoingCall( 642 "650-555-1212", 643 mPhoneAccountA0.getAccountHandle(), 644 mConnectionServiceFixtureA); 645 } 646 647 public void testOutgoingThenIncomingCalls() throws Exception { 648 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 649 IdPair outgoing = startAndMakeActiveOutgoingCall( 650 "650-555-1212", 651 mPhoneAccountA0.getAccountHandle(), 652 mConnectionServiceFixtureA); 653 IdPair incoming = startAndMakeActiveIncomingCall( 654 "650-555-2323", 655 mPhoneAccountA0.getAccountHandle(), 656 mConnectionServiceFixtureA); 657 verify(mConnectionServiceFixtureA.getTestDouble()) 658 .hold(outgoing.mConnectionId); 659 mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state = 660 Connection.STATE_HOLDING; 661 mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId); 662 assertEquals( 663 Call.STATE_HOLDING, 664 mInCallServiceFixtureX.getCall(outgoing.mCallId).getState()); 665 assertEquals( 666 Call.STATE_HOLDING, 667 mInCallServiceFixtureY.getCall(outgoing.mCallId).getState()); 668 } 669 670 public void testAudioManagerOperations() throws Exception { 671 AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble() 672 .getApplicationContext().getSystemService(Context.AUDIO_SERVICE); 673 674 IdPair outgoing = startAndMakeActiveOutgoingCall( 675 "650-555-1212", 676 mPhoneAccountA0.getAccountHandle(), 677 mConnectionServiceFixtureA); 678 679 verify(audioManager, timeout(TEST_TIMEOUT)) 680 .requestAudioFocusForCall(anyInt(), anyInt()); 681 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 682 .setMode(AudioManager.MODE_IN_CALL); 683 684 mInCallServiceFixtureX.mInCallAdapter.mute(true); 685 verify(audioManager, timeout(TEST_TIMEOUT)) 686 .setMicrophoneMute(true); 687 mInCallServiceFixtureX.mInCallAdapter.mute(false); 688 verify(audioManager, timeout(TEST_TIMEOUT)) 689 .setMicrophoneMute(false); 690 691 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER); 692 verify(audioManager, timeout(TEST_TIMEOUT)) 693 .setSpeakerphoneOn(true); 694 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE); 695 verify(audioManager, timeout(TEST_TIMEOUT)) 696 .setSpeakerphoneOn(false); 697 698 mConnectionServiceFixtureA. 699 sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE); 700 701 verify(audioManager, timeout(TEST_TIMEOUT)) 702 .abandonAudioFocusForCall(); 703 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 704 .setMode(AudioManager.MODE_NORMAL); 705 } 706 707 protected static void assertTrueWithTimeout(Predicate<Void> predicate) { 708 int elapsed = 0; 709 while (elapsed < TEST_TIMEOUT) { 710 if (predicate.apply(null)) { 711 return; 712 } else { 713 try { 714 Thread.sleep(TEST_POLL_INTERVAL); 715 elapsed += TEST_POLL_INTERVAL; 716 } catch (InterruptedException e) { 717 fail(e.toString()); 718 } 719 } 720 } 721 fail("Timeout in assertTrueWithTimeout"); 722 } 723} 724