BasicCallTests.java revision 874c0f8fa95a5da5a82e67c1fe39697883d753eb
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 static org.mockito.Matchers.any; 20import static org.mockito.Matchers.anyInt; 21import static org.mockito.Matchers.anyString; 22import static org.mockito.Matchers.eq; 23import static org.mockito.Matchers.isNull; 24import static org.mockito.Mockito.never; 25import static org.mockito.Mockito.timeout; 26import static org.mockito.Mockito.verify; 27import static org.mockito.Mockito.verifyZeroInteractions; 28import static org.mockito.Mockito.when; 29 30import android.content.Context; 31import android.content.IContentProvider; 32import android.media.AudioManager; 33import android.net.Uri; 34import android.os.Bundle; 35import android.os.Handler; 36import android.os.Looper; 37import android.os.Process; 38import android.provider.BlockedNumberContract; 39import android.telecom.Call; 40import android.telecom.CallAudioState; 41import android.telecom.Connection; 42import android.telecom.ConnectionRequest; 43import android.telecom.DisconnectCause; 44import android.telecom.ParcelableCall; 45import android.telecom.PhoneAccount; 46import android.telecom.PhoneAccountHandle; 47import android.telecom.TelecomManager; 48import android.telecom.VideoProfile; 49import android.test.suitebuilder.annotation.LargeTest; 50import android.test.suitebuilder.annotation.MediumTest; 51 52import com.android.internal.telecom.IInCallAdapter; 53import com.android.internal.telephony.CallerInfo; 54import com.android.server.telecom.Log; 55 56import com.google.common.base.Predicate; 57 58import org.mockito.invocation.InvocationOnMock; 59import org.mockito.stubbing.Answer; 60 61import java.util.concurrent.BrokenBarrierException; 62import java.util.concurrent.CountDownLatch; 63import java.util.concurrent.CyclicBarrier; 64import java.util.concurrent.TimeUnit; 65 66import org.mockito.ArgumentCaptor; 67 68/** 69 * Performs various basic call tests in Telecom. 70 */ 71public class BasicCallTests extends TelecomSystemTest { 72 private static final String TEST_BUNDLE_KEY = "android.telecom.extra.TEST"; 73 private static final String TEST_EVENT = "android.telecom.event.TEST"; 74 75 @LargeTest 76 public void testSingleOutgoingCallLocalDisconnect() throws Exception { 77 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 78 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 79 80 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 81 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 82 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 83 84 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 85 assertEquals(Call.STATE_DISCONNECTED, 86 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 87 assertEquals(Call.STATE_DISCONNECTED, 88 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 89 verifyNoBlockChecks(); 90 } 91 92 @LargeTest 93 public void testSingleOutgoingCallRemoteDisconnect() throws Exception { 94 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 95 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 96 97 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 98 assertEquals(Call.STATE_DISCONNECTED, 99 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 100 assertEquals(Call.STATE_DISCONNECTED, 101 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 102 verifyNoBlockChecks(); 103 } 104 105 /** 106 * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming 107 * audio-only call. 108 * 109 * @throws Exception 110 */ 111 @LargeTest 112 public void testTelecomManagerAcceptRingingCall() throws Exception { 113 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 114 mConnectionServiceFixtureA); 115 116 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 117 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 118 119 // Use TelecomManager API to answer the ringing call. 120 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 121 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 122 telecomManager.acceptRingingCall(); 123 124 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 125 .answer(ids.mCallId); 126 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 127 128 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 129 } 130 131 /** 132 * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming 133 * video call, which should be answered as video. 134 * 135 * @throws Exception 136 */ 137 @LargeTest 138 public void testTelecomManagerAcceptRingingVideoCall() throws Exception { 139 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 140 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); 141 142 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 143 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 144 145 // Use TelecomManager API to answer the ringing call; the default expected behavior is to 146 // answer using whatever video state the ringing call requests. 147 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 148 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 149 telecomManager.acceptRingingCall(); 150 151 // Answer video API should be called 152 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 153 .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL)); 154 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 155 156 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 157 } 158 159 /** 160 * Tests the {@link TelecomManager#acceptRingingCall(int)} API. Tests answering a video call 161 * as an audio call. 162 * 163 * @throws Exception 164 */ 165 @LargeTest 166 public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception { 167 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 168 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); 169 170 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 171 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 172 173 // Use TelecomManager API to answer the ringing call. 174 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 175 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 176 telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY); 177 178 // The generic answer method on the ConnectionService is used to answer audio-only calls. 179 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 180 .answer(eq(ids.mCallId)); 181 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 182 183 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 184 } 185 186 /** 187 * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming 188 * video call, where an attempt is made to answer with an invalid video state. 189 * 190 * @throws Exception 191 */ 192 @LargeTest 193 public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception { 194 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 195 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA); 196 197 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 198 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 199 200 // Use TelecomManager API to answer the ringing call; the default expected behavior is to 201 // answer using whatever video state the ringing call requests. 202 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 203 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 204 telecomManager.acceptRingingCall(999 /* invalid videostate */); 205 206 // Answer video API should be called 207 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 208 .answerVideo(eq(ids.mCallId), eq(VideoProfile.STATE_BIDIRECTIONAL)); 209 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 210 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 211 } 212 213 @LargeTest 214 public void testSingleIncomingCallLocalDisconnect() throws Exception { 215 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 216 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 217 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 218 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 219 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 220 221 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 222 assertEquals(Call.STATE_DISCONNECTED, 223 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 224 assertEquals(Call.STATE_DISCONNECTED, 225 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 226 } 227 228 @LargeTest 229 public void testSingleIncomingCallRemoteDisconnect() throws Exception { 230 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 231 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 232 233 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 234 assertEquals(Call.STATE_DISCONNECTED, 235 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 236 assertEquals(Call.STATE_DISCONNECTED, 237 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 238 } 239 240 @LargeTest 241 public void testOutgoingCallAndSelectPhoneAccount() throws Exception { 242 // Remove default PhoneAccount so that the Call moves into the correct 243 // SELECT_PHONE_ACCOUNT state. 244 mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount( 245 null, Process.myUserHandle()); 246 int startingNumConnections = mConnectionServiceFixtureA.mConnectionById.size(); 247 int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 248 String callId = startOutgoingPhoneCallWithNoPhoneAccount("650-555-1212", 249 mConnectionServiceFixtureA); 250 assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT, 251 mInCallServiceFixtureX.getCall(callId).getState()); 252 assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT, 253 mInCallServiceFixtureY.getCall(callId).getState()); 254 mInCallServiceFixtureX.mInCallAdapter.phoneAccountSelected(callId, 255 mPhoneAccountA0.getAccountHandle(), false); 256 257 IdPair ids = outgoingCallPhoneAccountSelected(mPhoneAccountA0.getAccountHandle(), 258 startingNumConnections, startingNumCalls, mConnectionServiceFixtureA); 259 260 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 261 assertEquals(Call.STATE_DISCONNECTED, 262 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 263 assertEquals(Call.STATE_DISCONNECTED, 264 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 265 } 266 267 @LargeTest 268 public void testIncomingCallFromContactWithSendToVoicemailIsRejected() throws Exception { 269 Bundle extras = new Bundle(); 270 extras.putParcelable( 271 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 272 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null)); 273 mTelecomSystem.getTelecomServiceImpl().getBinder() 274 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 275 276 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 277 verify(mConnectionServiceFixtureA.getTestDouble()) 278 .createConnection(any(PhoneAccountHandle.class), anyString(), 279 any(ConnectionRequest.class), eq(true), eq(false)); 280 281 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 282 for (CallerInfoAsyncQueryFactoryFixture.Request request : 283 mCallerInfoAsyncQueryFactoryFixture.mRequests) { 284 CallerInfo sendToVoicemailCallerInfo = new CallerInfo(); 285 sendToVoicemailCallerInfo.shouldSendToVoicemail = true; 286 request.replyWithCallerInfo(sendToVoicemailCallerInfo); 287 } 288 289 assertTrueWithTimeout(new Predicate<Void>() { 290 @Override 291 public boolean apply(Void aVoid) { 292 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1; 293 } 294 }); 295 assertTrueWithTimeout(new Predicate<Void>() { 296 @Override 297 public boolean apply(Void aVoid) { 298 return mMissedCallNotifier.missedCallsNotified.size() == 1; 299 } 300 }); 301 302 verify(mInCallServiceFixtureX.getTestDouble(), never()) 303 .setInCallAdapter(any(IInCallAdapter.class)); 304 verify(mInCallServiceFixtureY.getTestDouble(), never()) 305 .setInCallAdapter(any(IInCallAdapter.class)); 306 } 307 308 @LargeTest 309 public void testIncomingCallCallerInfoLookupTimesOutIsAllowed() throws Exception { 310 Bundle extras = new Bundle(); 311 extras.putParcelable( 312 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 313 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null)); 314 mTelecomSystem.getTelecomServiceImpl().getBinder() 315 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 316 317 verify(mConnectionServiceFixtureA.getTestDouble()) 318 .createConnection(any(PhoneAccountHandle.class), anyString(), 319 any(ConnectionRequest.class), eq(true), eq(false)); 320 321 // Never reply to the caller info lookup. 322 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 323 324 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 325 .setInCallAdapter(any(IInCallAdapter.class)); 326 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 327 .setInCallAdapter(any(IInCallAdapter.class)); 328 329 assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size()); 330 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 331 332 assertTrueWithTimeout(new Predicate<Void>() { 333 @Override 334 public boolean apply(Void v) { 335 return mInCallServiceFixtureX.mInCallAdapter != null; 336 } 337 }); 338 339 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 340 .addCall(any(ParcelableCall.class)); 341 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 342 .addCall(any(ParcelableCall.class)); 343 344 disconnectCall(mInCallServiceFixtureX.mLatestCallId, 345 mConnectionServiceFixtureA.mLatestConnectionId); 346 } 347 348 @LargeTest 349 public void testIncomingCallFromBlockedNumberIsRejected() throws Exception { 350 String phoneNumber = "650-555-1212"; 351 blockNumber(phoneNumber); 352 353 Bundle extras = new Bundle(); 354 extras.putParcelable( 355 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 356 Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null)); 357 mTelecomSystem.getTelecomServiceImpl().getBinder() 358 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 359 360 verify(mConnectionServiceFixtureA.getTestDouble()) 361 .createConnection(any(PhoneAccountHandle.class), anyString(), 362 any(ConnectionRequest.class), eq(true), eq(false)); 363 364 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 365 for (CallerInfoAsyncQueryFactoryFixture.Request request : 366 mCallerInfoAsyncQueryFactoryFixture.mRequests) { 367 request.reply(); 368 } 369 370 assertTrueWithTimeout(new Predicate<Void>() { 371 @Override 372 public boolean apply(Void aVoid) { 373 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1; 374 } 375 }); 376 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 377 378 verify(mInCallServiceFixtureX.getTestDouble(), never()) 379 .setInCallAdapter(any(IInCallAdapter.class)); 380 verify(mInCallServiceFixtureY.getTestDouble(), never()) 381 .setInCallAdapter(any(IInCallAdapter.class)); 382 } 383 384 @LargeTest 385 public void testIncomingCallBlockCheckTimesoutIsAllowed() throws Exception { 386 final CountDownLatch latch = new CountDownLatch(1); 387 String phoneNumber = "650-555-1212"; 388 blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() { 389 @Override 390 public Bundle answer(InvocationOnMock invocation) throws Throwable { 391 latch.await(TEST_TIMEOUT * 2, TimeUnit.MILLISECONDS); 392 Bundle bundle = new Bundle(); 393 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true); 394 return bundle; 395 } 396 }); 397 398 IdPair ids = startAndMakeActiveIncomingCall( 399 phoneNumber, mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 400 latch.countDown(); 401 402 assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size()); 403 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 404 disconnectCall(ids.mCallId, ids.mConnectionId); 405 } 406 407 public void do_testDeadlockOnOutgoingCall() throws Exception { 408 final IdPair ids = startOutgoingPhoneCall("650-555-1212", 409 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 410 Process.myUserHandle()); 411 rapidFire( 412 new Runnable() { 413 @Override 414 public void run() { 415 while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) { 416 mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply(); 417 } 418 } 419 }, 420 new Runnable() { 421 @Override 422 public void run() { 423 try { 424 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 425 } catch (Exception e) { 426 Log.e(this, e, ""); 427 } 428 } 429 }); 430 } 431 432 @MediumTest 433 public void testDeadlockOnOutgoingCall() throws Exception { 434 for (int i = 0; i < 100; i++) { 435 BasicCallTests test = new BasicCallTests(); 436 test.setContext(getContext()); 437 test.setTestContext(getTestContext()); 438 test.setName(getName()); 439 test.setUp(); 440 test.do_testDeadlockOnOutgoingCall(); 441 test.tearDown(); 442 } 443 } 444 445 @LargeTest 446 public void testIncomingThenOutgoingCalls() throws Exception { 447 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 448 IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", 449 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 450 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 451 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 452 453 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); 454 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); 455 } 456 457 @LargeTest 458 public void testOutgoingThenIncomingCalls() throws Exception { 459 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 460 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 461 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 462 IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", 463 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 464 verify(mConnectionServiceFixtureA.getTestDouble()) 465 .hold(outgoing.mConnectionId); 466 mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state = 467 Connection.STATE_HOLDING; 468 mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId); 469 assertEquals(Call.STATE_HOLDING, 470 mInCallServiceFixtureX.getCall(outgoing.mCallId).getState()); 471 assertEquals(Call.STATE_HOLDING, 472 mInCallServiceFixtureY.getCall(outgoing.mCallId).getState()); 473 474 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); 475 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); 476 } 477 478 @LargeTest 479 public void testAudioManagerOperations() throws Exception { 480 AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble() 481 .getApplicationContext().getSystemService(Context.AUDIO_SERVICE); 482 483 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 484 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 485 486 verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt()); 487 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 488 .setMode(AudioManager.MODE_IN_CALL); 489 490 mInCallServiceFixtureX.mInCallAdapter.mute(true); 491 verify(mAudioService, timeout(TEST_TIMEOUT)) 492 .setMicrophoneMute(eq(true), any(String.class), any(Integer.class)); 493 mInCallServiceFixtureX.mInCallAdapter.mute(false); 494 verify(mAudioService, timeout(TEST_TIMEOUT)) 495 .setMicrophoneMute(eq(false), any(String.class), any(Integer.class)); 496 497 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER); 498 verify(audioManager, timeout(TEST_TIMEOUT)) 499 .setSpeakerphoneOn(true); 500 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE); 501 verify(audioManager, timeout(TEST_TIMEOUT)) 502 .setSpeakerphoneOn(false); 503 504 mConnectionServiceFixtureA. 505 sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE); 506 507 verify(audioManager, timeout(TEST_TIMEOUT)) 508 .abandonAudioFocusForCall(); 509 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 510 .setMode(AudioManager.MODE_NORMAL); 511 } 512 513 private void rapidFire(Runnable... tasks) { 514 final CyclicBarrier barrier = new CyclicBarrier(tasks.length); 515 final CountDownLatch latch = new CountDownLatch(tasks.length); 516 for (int i = 0; i < tasks.length; i++) { 517 final Runnable task = tasks[i]; 518 new Thread(new Runnable() { 519 @Override 520 public void run() { 521 try { 522 barrier.await(); 523 task.run(); 524 } catch (InterruptedException | BrokenBarrierException e){ 525 Log.e(BasicCallTests.this, e, "Unexpectedly interrupted"); 526 } finally { 527 latch.countDown(); 528 } 529 } 530 }).start(); 531 } 532 try { 533 latch.await(); 534 } catch (InterruptedException e) { 535 Log.e(BasicCallTests.this, e, "Unexpectedly interrupted"); 536 } 537 } 538 539 @MediumTest 540 public void testBasicConferenceCall() throws Exception { 541 makeConferenceCall(); 542 } 543 544 @MediumTest 545 public void testAddCallToConference1() throws Exception { 546 ParcelableCall conferenceCall = makeConferenceCall(); 547 IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", 548 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 549 // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference 550 mInCallServiceFixtureX.getInCallAdapter().conference( 551 conferenceCall.getId(), callId3.mCallId); 552 Thread.sleep(200); 553 554 ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId); 555 ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId()); 556 assertEquals(conferenceCall.getId(), call3.getParentCallId()); 557 assertEquals(3, updatedConference.getChildCallIds().size()); 558 assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId)); 559 } 560 561 @MediumTest 562 public void testAddCallToConference2() throws Exception { 563 ParcelableCall conferenceCall = makeConferenceCall(); 564 IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", 565 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 566 mInCallServiceFixtureX.getInCallAdapter() 567 .conference(callId3.mCallId, conferenceCall.getId()); 568 Thread.sleep(200); 569 570 ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId); 571 ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId()); 572 assertEquals(conferenceCall.getId(), call3.getParentCallId()); 573 assertEquals(3, updatedConference.getChildCallIds().size()); 574 assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId)); 575 } 576 577 /** 578 * Tests the {@link Call#pullExternalCall()} API. Verifies that if a call is not an external 579 * call, no pull call request is made to the connection service. 580 * 581 * @throws Exception 582 */ 583 @MediumTest 584 public void testPullNonExternalCall() throws Exception { 585 // TODO: Revisit this unit test once telecom support for filtering external calls from 586 // InCall services is implemented. 587 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 588 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 589 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 590 591 // Attempt to pull the call and verify the API call makes it through 592 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 593 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT).never()) 594 .pullExternalCall(ids.mCallId); 595 } 596 597 /** 598 * Tests the {@link Connection#sendConnectionEvent(String)} API. 599 * 600 * @throws Exception 601 */ 602 @MediumTest 603 public void testSendConnectionEventNull() throws Exception { 604 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 605 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 606 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 607 mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, null); 608 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 609 .onConnectionEvent(ids.mCallId, TEST_EVENT, null); 610 } 611 612 /** 613 * Tests the {@link Connection#sendConnectionEvent(String)} API. 614 * 615 * @throws Exception 616 */ 617 @MediumTest 618 public void testSendConnectionEventNotNull() throws Exception { 619 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 620 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 621 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 622 623 Bundle testBundle = new Bundle(); 624 testBundle.putString(TEST_BUNDLE_KEY, "TEST"); 625 626 ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class); 627 mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, testBundle); 628 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 629 .onConnectionEvent(eq(ids.mCallId), eq(TEST_EVENT), bundleArgumentCaptor.capture()); 630 assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY)); 631 } 632 633 /** 634 * Tests the {@link Call#sendCallEvent(String, Bundle)} API. 635 * 636 * @throws Exception 637 */ 638 @MediumTest 639 public void testSendCallEventNull() throws Exception { 640 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 641 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 642 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 643 644 mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, null); 645 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 646 .sendCallEvent(ids.mCallId, TEST_EVENT, null); 647 } 648 649 /** 650 * Tests the {@link Call#sendCallEvent(String, Bundle)} API. 651 * 652 * @throws Exception 653 */ 654 @MediumTest 655 public void testSendCallEventNonNull() throws Exception { 656 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 657 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 658 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 659 660 Bundle testBundle = new Bundle(); 661 testBundle.putString(TEST_BUNDLE_KEY, "TEST"); 662 663 ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class); 664 mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 665 testBundle); 666 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 667 .sendCallEvent(eq(ids.mCallId), eq(TEST_EVENT), 668 bundleArgumentCaptor.capture()); 669 assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY)); 670 } 671 672 private void blockNumber(String phoneNumber) throws Exception { 673 blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() { 674 @Override 675 public Bundle answer(InvocationOnMock invocation) throws Throwable { 676 Bundle bundle = new Bundle(); 677 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true); 678 return bundle; 679 } 680 }); 681 } 682 683 private void blockNumberWithAnswer(String phoneNumber, Answer answer) throws Exception { 684 when(getBlockedNumberProvider().call( 685 anyString(), 686 eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER), 687 eq(phoneNumber), 688 isNull(Bundle.class))).thenAnswer(answer); 689 } 690 691 private void verifyNoBlockChecks() { 692 verifyZeroInteractions(getBlockedNumberProvider()); 693 } 694 695 private IContentProvider getBlockedNumberProvider() { 696 return mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY); 697 } 698 699 private void disconnectCall(String callId, String connectionId) throws Exception { 700 mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL); 701 assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState()); 702 assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState()); 703 } 704 705 /** 706 * Tests to make sure that the Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is set on a 707 * Call that is based on a Connection with the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY 708 * property set. 709 */ 710 @MediumTest 711 public void testCdmaEnhancedPrivacyVoiceCall() throws Exception { 712 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 713 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY; 714 715 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 716 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 717 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 718 719 assertTrue(Call.Details.hasProperty( 720 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(), 721 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)); 722 } 723 724 /** 725 * Tests to make sure that Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY is dropped 726 * when the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is removed from the Connection. 727 */ 728 @MediumTest 729 public void testDropCdmaEnhancedPrivacyVoiceCall() throws Exception { 730 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 731 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY; 732 733 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 734 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 735 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 736 mConnectionServiceFixtureA.mLatestConnection.setConnectionProperties(0); 737 738 assertFalse(Call.Details.hasProperty( 739 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(), 740 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)); 741 } 742 743 /** 744 * Tests the {@link Call#pullExternalCall()} API. Ensures that an external call which is 745 * pullable can be pulled. 746 * 747 * @throws Exception 748 */ 749 @LargeTest 750 public void testPullExternalCall() throws Exception { 751 // TODO: Revisit this unit test once telecom support for filtering external calls from 752 // InCall services is implemented. 753 mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 754 Connection.CAPABILITY_CAN_PULL_CALL; 755 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 756 Connection.PROPERTY_IS_EXTERNAL_CALL; 757 758 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 759 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 760 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 761 762 // Attempt to pull the call and verify the API call makes it through 763 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 764 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 765 .pullExternalCall(ids.mCallId); 766 } 767 768 /** 769 * Tests the {@link Call#pullExternalCall()} API. Verifies that if an external call is not 770 * marked as pullable that the connection service does not get an API call to pull the external 771 * call. 772 * 773 * @throws Exception 774 */ 775 @LargeTest 776 public void testPullNonPullableExternalCall() throws Exception { 777 // TODO: Revisit this unit test once telecom support for filtering external calls from 778 // InCall services is implemented. 779 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 780 Connection.PROPERTY_IS_EXTERNAL_CALL; 781 782 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 783 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 784 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 785 786 // Attempt to pull the call and verify the API call makes it through 787 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 788 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT).never()) 789 .pullExternalCall(ids.mCallId); 790 } 791 792 public void testMergeFailedAndNotifyInCallUi() throws Exception { 793 IdPair testCall1 = startAndMakeActiveOutgoingCall( 794 "650-555-1212", 795 mPhoneAccountA0.getAccountHandle(), 796 mConnectionServiceFixtureA); 797 IdPair testCall2 = startAndMakeActiveOutgoingCall( 798 "650-555-1213", 799 mPhoneAccountA0.getAccountHandle(), 800 mConnectionServiceFixtureA); 801 802 assertEquals(Call.STATE_ACTIVE, 803 mInCallServiceFixtureX.getCall(testCall1.mCallId).getState()); 804 assertEquals(Call.STATE_ACTIVE, 805 mInCallServiceFixtureX.getCall(testCall2.mCallId).getState()); 806 assertEquals(Call.STATE_ACTIVE, 807 mInCallServiceFixtureY.getCall(testCall1.mCallId).getState()); 808 assertEquals(Call.STATE_ACTIVE, 809 mInCallServiceFixtureY.getCall(testCall2.mCallId).getState()); 810 811 // Conference will not occur and instead will send setConferenceMergeFailed 812 ((ConnectionServiceFixture.FakeConnection) 813 mConnectionServiceFixtureA.mLatestConnection).setIsConferenceCreated(false); 814 mInCallServiceFixtureX.getInCallAdapter().conference(testCall2.mCallId, testCall1.mCallId); 815 816 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)).onConnectionEvent( 817 eq(testCall2.mCallId), eq(Connection.EVENT_CALL_MERGE_FAILED), any(Bundle.class)); 818 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)).onConnectionEvent( 819 eq(testCall2.mCallId), eq(Connection.EVENT_CALL_MERGE_FAILED), any(Bundle.class)); 820 } 821} 822