BasicCallTests.java revision 3037ac6f171b6a3627494bb10042ab7adb34366a
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.mConnectionId); 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.mConnectionId), 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.mConnectionId)); 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.mConnectionId), 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 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 282 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 283 for (CallerInfoAsyncQueryFactoryFixture.Request request : 284 mCallerInfoAsyncQueryFactoryFixture.mRequests) { 285 CallerInfo sendToVoicemailCallerInfo = new CallerInfo(); 286 sendToVoicemailCallerInfo.shouldSendToVoicemail = true; 287 request.replyWithCallerInfo(sendToVoicemailCallerInfo); 288 } 289 290 assertTrueWithTimeout(new Predicate<Void>() { 291 @Override 292 public boolean apply(Void aVoid) { 293 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1; 294 } 295 }); 296 assertTrueWithTimeout(new Predicate<Void>() { 297 @Override 298 public boolean apply(Void aVoid) { 299 return mMissedCallNotifier.missedCallsNotified.size() == 1; 300 } 301 }); 302 303 verify(mInCallServiceFixtureX.getTestDouble(), never()) 304 .setInCallAdapter(any(IInCallAdapter.class)); 305 verify(mInCallServiceFixtureY.getTestDouble(), never()) 306 .setInCallAdapter(any(IInCallAdapter.class)); 307 } 308 309 @LargeTest 310 public void testIncomingCallCallerInfoLookupTimesOutIsAllowed() throws Exception { 311 Bundle extras = new Bundle(); 312 extras.putParcelable( 313 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 314 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null)); 315 mTelecomSystem.getTelecomServiceImpl().getBinder() 316 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 317 318 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 319 verify(mConnectionServiceFixtureA.getTestDouble()) 320 .createConnection(any(PhoneAccountHandle.class), anyString(), 321 any(ConnectionRequest.class), eq(true), eq(false)); 322 323 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 324 // Never reply to the caller info lookup. 325 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 326 327 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 328 .setInCallAdapter(any(IInCallAdapter.class)); 329 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 330 .setInCallAdapter(any(IInCallAdapter.class)); 331 332 assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size()); 333 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 334 335 assertTrueWithTimeout(new Predicate<Void>() { 336 @Override 337 public boolean apply(Void v) { 338 return mInCallServiceFixtureX.mInCallAdapter != null; 339 } 340 }); 341 342 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 343 .addCall(any(ParcelableCall.class)); 344 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 345 .addCall(any(ParcelableCall.class)); 346 347 disconnectCall(mInCallServiceFixtureX.mLatestCallId, 348 mConnectionServiceFixtureA.mLatestConnectionId); 349 } 350 351 @LargeTest 352 public void testIncomingCallFromBlockedNumberIsRejected() throws Exception { 353 String phoneNumber = "650-555-1212"; 354 blockNumber(phoneNumber); 355 356 Bundle extras = new Bundle(); 357 extras.putParcelable( 358 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 359 Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null)); 360 mTelecomSystem.getTelecomServiceImpl().getBinder() 361 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 362 363 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 364 verify(mConnectionServiceFixtureA.getTestDouble()) 365 .createConnection(any(PhoneAccountHandle.class), anyString(), 366 any(ConnectionRequest.class), eq(true), eq(false)); 367 368 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 369 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 370 for (CallerInfoAsyncQueryFactoryFixture.Request request : 371 mCallerInfoAsyncQueryFactoryFixture.mRequests) { 372 request.reply(); 373 } 374 375 assertTrueWithTimeout(new Predicate<Void>() { 376 @Override 377 public boolean apply(Void aVoid) { 378 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1; 379 } 380 }); 381 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 382 383 verify(mInCallServiceFixtureX.getTestDouble(), never()) 384 .setInCallAdapter(any(IInCallAdapter.class)); 385 verify(mInCallServiceFixtureY.getTestDouble(), never()) 386 .setInCallAdapter(any(IInCallAdapter.class)); 387 } 388 389 @LargeTest 390 public void testIncomingCallBlockCheckTimesoutIsAllowed() throws Exception { 391 final CountDownLatch latch = new CountDownLatch(1); 392 String phoneNumber = "650-555-1212"; 393 blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() { 394 @Override 395 public Bundle answer(InvocationOnMock invocation) throws Throwable { 396 latch.await(TEST_TIMEOUT * 2, TimeUnit.MILLISECONDS); 397 Bundle bundle = new Bundle(); 398 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true); 399 return bundle; 400 } 401 }); 402 403 IdPair ids = startAndMakeActiveIncomingCall( 404 phoneNumber, mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 405 latch.countDown(); 406 407 assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size()); 408 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 409 disconnectCall(ids.mCallId, ids.mConnectionId); 410 } 411 412 public void do_testDeadlockOnOutgoingCall() throws Exception { 413 final IdPair ids = startOutgoingPhoneCall("650-555-1212", 414 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 415 Process.myUserHandle()); 416 rapidFire( 417 new Runnable() { 418 @Override 419 public void run() { 420 while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) { 421 mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply(); 422 } 423 } 424 }, 425 new Runnable() { 426 @Override 427 public void run() { 428 try { 429 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 430 } catch (Exception e) { 431 Log.e(this, e, ""); 432 } 433 } 434 }); 435 } 436 437 @MediumTest 438 public void testDeadlockOnOutgoingCall() throws Exception { 439 for (int i = 0; i < 100; i++) { 440 BasicCallTests test = new BasicCallTests(); 441 test.setContext(getContext()); 442 test.setTestContext(getTestContext()); 443 test.setName(getName()); 444 test.setUp(); 445 test.do_testDeadlockOnOutgoingCall(); 446 test.tearDown(); 447 } 448 } 449 450 @LargeTest 451 public void testIncomingThenOutgoingCalls() throws Exception { 452 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 453 IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", 454 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 455 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 456 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 457 458 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); 459 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); 460 } 461 462 @LargeTest 463 public void testOutgoingThenIncomingCalls() throws Exception { 464 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 465 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 466 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 467 IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", 468 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 469 verify(mConnectionServiceFixtureA.getTestDouble()) 470 .hold(outgoing.mConnectionId); 471 mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state = 472 Connection.STATE_HOLDING; 473 mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId); 474 assertEquals(Call.STATE_HOLDING, 475 mInCallServiceFixtureX.getCall(outgoing.mCallId).getState()); 476 assertEquals(Call.STATE_HOLDING, 477 mInCallServiceFixtureY.getCall(outgoing.mCallId).getState()); 478 479 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); 480 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); 481 } 482 483 @LargeTest 484 public void testAudioManagerOperations() throws Exception { 485 AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble() 486 .getApplicationContext().getSystemService(Context.AUDIO_SERVICE); 487 488 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 489 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 490 491 verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt()); 492 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 493 .setMode(AudioManager.MODE_IN_CALL); 494 495 mInCallServiceFixtureX.mInCallAdapter.mute(true); 496 verify(mAudioService, timeout(TEST_TIMEOUT)) 497 .setMicrophoneMute(eq(true), any(String.class), any(Integer.class)); 498 mInCallServiceFixtureX.mInCallAdapter.mute(false); 499 verify(mAudioService, timeout(TEST_TIMEOUT)) 500 .setMicrophoneMute(eq(false), any(String.class), any(Integer.class)); 501 502 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER); 503 verify(audioManager, timeout(TEST_TIMEOUT)) 504 .setSpeakerphoneOn(true); 505 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE); 506 verify(audioManager, timeout(TEST_TIMEOUT)) 507 .setSpeakerphoneOn(false); 508 509 mConnectionServiceFixtureA. 510 sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE); 511 512 verify(audioManager, timeout(TEST_TIMEOUT)) 513 .abandonAudioFocusForCall(); 514 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 515 .setMode(AudioManager.MODE_NORMAL); 516 } 517 518 private void rapidFire(Runnable... tasks) { 519 final CyclicBarrier barrier = new CyclicBarrier(tasks.length); 520 final CountDownLatch latch = new CountDownLatch(tasks.length); 521 for (int i = 0; i < tasks.length; i++) { 522 final Runnable task = tasks[i]; 523 new Thread(new Runnable() { 524 @Override 525 public void run() { 526 try { 527 barrier.await(); 528 task.run(); 529 } catch (InterruptedException | BrokenBarrierException e){ 530 Log.e(BasicCallTests.this, e, "Unexpectedly interrupted"); 531 } finally { 532 latch.countDown(); 533 } 534 } 535 }).start(); 536 } 537 try { 538 latch.await(); 539 } catch (InterruptedException e) { 540 Log.e(BasicCallTests.this, e, "Unexpectedly interrupted"); 541 } 542 } 543 544 @MediumTest 545 public void testBasicConferenceCall() throws Exception { 546 makeConferenceCall(); 547 } 548 549 @MediumTest 550 public void testAddCallToConference1() throws Exception { 551 ParcelableCall conferenceCall = makeConferenceCall(); 552 IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", 553 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 554 // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference 555 mInCallServiceFixtureX.getInCallAdapter().conference( 556 conferenceCall.getId(), callId3.mCallId); 557 Thread.sleep(200); 558 559 ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId); 560 ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId()); 561 assertEquals(conferenceCall.getId(), call3.getParentCallId()); 562 assertEquals(3, updatedConference.getChildCallIds().size()); 563 assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId)); 564 } 565 566 @MediumTest 567 public void testAddCallToConference2() throws Exception { 568 ParcelableCall conferenceCall = makeConferenceCall(); 569 IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", 570 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 571 mInCallServiceFixtureX.getInCallAdapter() 572 .conference(callId3.mCallId, conferenceCall.getId()); 573 Thread.sleep(200); 574 575 ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId); 576 ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId()); 577 assertEquals(conferenceCall.getId(), call3.getParentCallId()); 578 assertEquals(3, updatedConference.getChildCallIds().size()); 579 assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId)); 580 } 581 582 /** 583 * Tests the {@link Call#pullExternalCall()} API. Verifies that if a call is not an external 584 * call, no pull call request is made to the connection service. 585 * 586 * @throws Exception 587 */ 588 @MediumTest 589 public void testPullNonExternalCall() throws Exception { 590 // TODO: Revisit this unit test once telecom support for filtering external calls from 591 // InCall services is implemented. 592 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 593 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 594 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 595 596 // Attempt to pull the call and verify the API call makes it through 597 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 598 Thread.sleep(TEST_TIMEOUT); 599 verify(mConnectionServiceFixtureA.getTestDouble(), never()) 600 .pullExternalCall(ids.mCallId); 601 } 602 603 /** 604 * Tests the {@link Connection#sendConnectionEvent(String)} API. 605 * 606 * @throws Exception 607 */ 608 @MediumTest 609 public void testSendConnectionEventNull() throws Exception { 610 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 611 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 612 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 613 mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, null); 614 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 615 .onConnectionEvent(ids.mCallId, TEST_EVENT, null); 616 } 617 618 /** 619 * Tests the {@link Connection#sendConnectionEvent(String)} API. 620 * 621 * @throws Exception 622 */ 623 @MediumTest 624 public void testSendConnectionEventNotNull() throws Exception { 625 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 626 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 627 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 628 629 Bundle testBundle = new Bundle(); 630 testBundle.putString(TEST_BUNDLE_KEY, "TEST"); 631 632 ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class); 633 mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, testBundle); 634 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 635 .onConnectionEvent(eq(ids.mCallId), eq(TEST_EVENT), bundleArgumentCaptor.capture()); 636 assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY)); 637 } 638 639 /** 640 * Tests the {@link Call#sendCallEvent(String, Bundle)} API. 641 * 642 * @throws Exception 643 */ 644 @MediumTest 645 public void testSendCallEventNull() throws Exception { 646 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 647 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 648 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 649 650 mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, null); 651 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 652 .sendCallEvent(ids.mConnectionId, TEST_EVENT, null); 653 } 654 655 /** 656 * Tests the {@link Call#sendCallEvent(String, Bundle)} API. 657 * 658 * @throws Exception 659 */ 660 @MediumTest 661 public void testSendCallEventNonNull() throws Exception { 662 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 663 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 664 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 665 666 Bundle testBundle = new Bundle(); 667 testBundle.putString(TEST_BUNDLE_KEY, "TEST"); 668 669 ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class); 670 mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 671 testBundle); 672 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 673 .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT), 674 bundleArgumentCaptor.capture()); 675 assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY)); 676 } 677 678 private void blockNumber(String phoneNumber) throws Exception { 679 blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() { 680 @Override 681 public Bundle answer(InvocationOnMock invocation) throws Throwable { 682 Bundle bundle = new Bundle(); 683 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true); 684 return bundle; 685 } 686 }); 687 } 688 689 private void blockNumberWithAnswer(String phoneNumber, Answer answer) throws Exception { 690 when(getBlockedNumberProvider().call( 691 anyString(), 692 eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER), 693 eq(phoneNumber), 694 isNull(Bundle.class))).thenAnswer(answer); 695 } 696 697 private void verifyNoBlockChecks() { 698 verifyZeroInteractions(getBlockedNumberProvider()); 699 } 700 701 private IContentProvider getBlockedNumberProvider() { 702 return mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY); 703 } 704 705 private void disconnectCall(String callId, String connectionId) throws Exception { 706 mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL); 707 assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState()); 708 assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState()); 709 } 710 711 /** 712 * Tests to make sure that the Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is set on a 713 * Call that is based on a Connection with the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY 714 * property set. 715 */ 716 @MediumTest 717 public void testCdmaEnhancedPrivacyVoiceCall() throws Exception { 718 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 719 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY; 720 721 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 722 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 723 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 724 725 assertTrue(Call.Details.hasProperty( 726 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(), 727 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)); 728 } 729 730 /** 731 * Tests to make sure that Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY is dropped 732 * when the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is removed from the Connection. 733 */ 734 @MediumTest 735 public void testDropCdmaEnhancedPrivacyVoiceCall() throws Exception { 736 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 737 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY; 738 739 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 740 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 741 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 742 mConnectionServiceFixtureA.mLatestConnection.setConnectionProperties(0); 743 744 assertFalse(Call.Details.hasProperty( 745 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(), 746 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)); 747 } 748 749 /** 750 * Tests the {@link Call#pullExternalCall()} API. Ensures that an external call which is 751 * pullable can be pulled. 752 * 753 * @throws Exception 754 */ 755 @LargeTest 756 public void testPullExternalCall() throws Exception { 757 // TODO: Revisit this unit test once telecom support for filtering external calls from 758 // InCall services is implemented. 759 mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 760 Connection.CAPABILITY_CAN_PULL_CALL; 761 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 762 Connection.PROPERTY_IS_EXTERNAL_CALL; 763 764 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 765 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 766 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 767 768 // Attempt to pull the call and verify the API call makes it through 769 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 770 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 771 .pullExternalCall(ids.mConnectionId); 772 } 773 774 /** 775 * Tests the {@link Call#pullExternalCall()} API. Verifies that if an external call is not 776 * marked as pullable that the connection service does not get an API call to pull the external 777 * call. 778 * 779 * @throws Exception 780 */ 781 @LargeTest 782 public void testPullNonPullableExternalCall() throws Exception { 783 // TODO: Revisit this unit test once telecom support for filtering external calls from 784 // InCall services is implemented. 785 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 786 Connection.PROPERTY_IS_EXTERNAL_CALL; 787 788 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 789 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 790 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 791 792 // Attempt to pull the call and verify the API call makes it through 793 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 794 Thread.sleep(TEST_TIMEOUT); 795 verify(mConnectionServiceFixtureA.getTestDouble(), never()) 796 .pullExternalCall(ids.mConnectionId); 797 } 798 799 public void testMergeFailedAndNotifyInCallUi() throws Exception { 800 IdPair testCall1 = startAndMakeActiveOutgoingCall( 801 "650-555-1212", 802 mPhoneAccountA0.getAccountHandle(), 803 mConnectionServiceFixtureA); 804 IdPair testCall2 = startAndMakeActiveOutgoingCall( 805 "650-555-1213", 806 mPhoneAccountA0.getAccountHandle(), 807 mConnectionServiceFixtureA); 808 809 assertEquals(Call.STATE_ACTIVE, 810 mInCallServiceFixtureX.getCall(testCall1.mCallId).getState()); 811 assertEquals(Call.STATE_ACTIVE, 812 mInCallServiceFixtureX.getCall(testCall2.mCallId).getState()); 813 assertEquals(Call.STATE_ACTIVE, 814 mInCallServiceFixtureY.getCall(testCall1.mCallId).getState()); 815 assertEquals(Call.STATE_ACTIVE, 816 mInCallServiceFixtureY.getCall(testCall2.mCallId).getState()); 817 818 // Conference will not occur and instead will send setConferenceMergeFailed 819 ((ConnectionServiceFixture.FakeConnection) 820 mConnectionServiceFixtureA.mLatestConnection).setIsConferenceCreated(false); 821 mInCallServiceFixtureX.getInCallAdapter().conference(testCall2.mCallId, testCall1.mCallId); 822 823 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)).onConnectionEvent( 824 eq(testCall2.mCallId), eq(Connection.EVENT_CALL_MERGE_FAILED), any(Bundle.class)); 825 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)).onConnectionEvent( 826 eq(testCall2.mCallId), eq(Connection.EVENT_CALL_MERGE_FAILED), any(Bundle.class)); 827 } 828 829 @LargeTest 830 public void testEmergencyCallFailMoveToSecondSim() throws Exception { 831 IdPair ids = startAndMakeDialingEmergencyCall("650-555-1212", 832 mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA); 833 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 834 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 835 836 // The Emergency Call has failed on the default SIM with an ERROR Disconnect Cause. Retry 837 // with the other SIM PhoneAccount 838 IdPair newIds = triggerEmergencyRedial(mPhoneAccountE1.getAccountHandle(), 839 mConnectionServiceFixtureA, ids); 840 841 // Call should be active on the E1 PhoneAccount 842 mConnectionServiceFixtureA.sendSetActive(newIds.mConnectionId); 843 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(newIds.mCallId).getState()); 844 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(newIds.mCallId).getState()); 845 assertEquals(mInCallServiceFixtureX.getCall(ids.mCallId).getAccountHandle(), 846 mPhoneAccountE1.getAccountHandle()); 847 } 848} 849