1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.telecom.tests; 18 19 import static com.android.server.telecom.tests.ConnectionServiceFixture.STATUS_HINTS_EXTRA; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertNull; 25 import static org.junit.Assert.assertTrue; 26 import static org.mockito.ArgumentMatchers.nullable; 27 import static org.mockito.Matchers.any; 28 import static org.mockito.Matchers.anyInt; 29 import static org.mockito.Matchers.anyString; 30 import static org.mockito.Matchers.eq; 31 import static org.mockito.Matchers.isNull; 32 import static org.mockito.Mockito.doReturn; 33 import static org.mockito.Mockito.never; 34 import static org.mockito.Mockito.timeout; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.verifyZeroInteractions; 38 import static org.mockito.Mockito.when; 39 40 import android.content.Context; 41 import android.content.IContentProvider; 42 import android.content.pm.PackageManager; 43 import android.media.AudioDeviceInfo; 44 import android.content.Intent; 45 import android.graphics.drawable.Icon; 46 import android.media.AudioManager; 47 import android.net.Uri; 48 import android.os.Binder; 49 import android.os.Bundle; 50 import android.os.Handler; 51 import android.os.Looper; 52 import android.os.Process; 53 import android.os.UserHandle; 54 import android.provider.BlockedNumberContract; 55 import android.telecom.Call; 56 import android.telecom.CallAudioState; 57 import android.telecom.Connection; 58 import android.telecom.ConnectionRequest; 59 import android.telecom.DisconnectCause; 60 import android.telecom.Log; 61 import android.telecom.ParcelableCall; 62 import android.telecom.PhoneAccount; 63 import android.telecom.PhoneAccountHandle; 64 import android.telecom.StatusHints; 65 import android.telecom.TelecomManager; 66 import android.telecom.VideoProfile; 67 import android.test.suitebuilder.annotation.LargeTest; 68 import android.test.suitebuilder.annotation.MediumTest; 69 70 import androidx.test.filters.FlakyTest; 71 import androidx.test.filters.SmallTest; 72 73 import com.android.internal.telecom.IInCallAdapter; 74 import android.telecom.CallerInfo; 75 76 import com.google.common.base.Predicate; 77 78 import org.junit.After; 79 import org.junit.Before; 80 import org.junit.Ignore; 81 import org.junit.Test; 82 import org.junit.runner.RunWith; 83 import org.junit.runners.JUnit4; 84 import org.mockito.ArgumentCaptor; 85 import org.mockito.invocation.InvocationOnMock; 86 import org.mockito.stubbing.Answer; 87 88 import java.util.List; 89 import java.util.concurrent.BrokenBarrierException; 90 import java.util.concurrent.CountDownLatch; 91 import java.util.concurrent.CyclicBarrier; 92 import java.util.concurrent.TimeUnit; 93 94 /** 95 * Performs various basic call tests in Telecom. 96 */ 97 @RunWith(JUnit4.class) 98 public class BasicCallTests extends TelecomSystemTest { 99 private static final String TEST_BUNDLE_KEY = "android.telecom.extra.TEST"; 100 private static final String TEST_EVENT = "android.telecom.event.TEST"; 101 102 private PackageManager mPackageManager; 103 104 @Override 105 @Before setUp()106 public void setUp() throws Exception { 107 super.setUp(); 108 doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt()); 109 mPackageManager = mContext.getPackageManager(); 110 when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid()); 111 } 112 113 @Override 114 @After tearDown()115 public void tearDown() throws Exception { 116 super.tearDown(); 117 } 118 119 @LargeTest 120 @Test testSingleOutgoingCallLocalDisconnect()121 public void testSingleOutgoingCallLocalDisconnect() throws Exception { 122 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 123 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 124 125 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 126 assertEquals(Call.STATE_DISCONNECTING, 127 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 128 assertEquals(Call.STATE_DISCONNECTING, 129 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 130 131 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME); 132 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME); 133 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 134 assertEquals(Call.STATE_DISCONNECTED, 135 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 136 assertEquals(Call.STATE_DISCONNECTED, 137 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 138 assertEquals(TEST_CONNECT_TIME, 139 mInCallServiceFixtureX.getCall(ids.mCallId).getConnectTimeMillis()); 140 assertEquals(TEST_CONNECT_TIME, 141 mInCallServiceFixtureY.getCall(ids.mCallId).getConnectTimeMillis()); 142 assertEquals(TEST_CREATE_TIME, 143 mInCallServiceFixtureX.getCall(ids.mCallId).getCreationTimeMillis()); 144 assertEquals(TEST_CREATE_TIME, 145 mInCallServiceFixtureY.getCall(ids.mCallId).getCreationTimeMillis()); 146 147 verifyNoBlockChecks(); 148 } 149 150 @LargeTest 151 @Test testSingleOutgoingCallRemoteDisconnect()152 public void testSingleOutgoingCallRemoteDisconnect() throws Exception { 153 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 154 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 155 156 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME); 157 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME); 158 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 159 assertEquals(Call.STATE_DISCONNECTED, 160 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 161 assertEquals(Call.STATE_DISCONNECTED, 162 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 163 verifyNoBlockChecks(); 164 } 165 166 /** 167 * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming 168 * audio-only call. 169 * 170 * @throws Exception 171 */ 172 @LargeTest 173 @Test testTelecomManagerAcceptRingingCall()174 public void testTelecomManagerAcceptRingingCall() throws Exception { 175 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 176 mConnectionServiceFixtureA); 177 178 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 179 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 180 181 // Use TelecomManager API to answer the ringing call. 182 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 183 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 184 telecomManager.acceptRingingCall(); 185 186 waitForHandlerAction(mTelecomSystem.getCallsManager() 187 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT); 188 189 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 190 .answer(eq(ids.mConnectionId), any()); 191 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 192 193 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 194 } 195 196 /** 197 * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming 198 * video call, which should be answered as video. 199 * 200 * @throws Exception 201 */ 202 @LargeTest 203 @Test testTelecomManagerAcceptRingingVideoCall()204 public void testTelecomManagerAcceptRingingVideoCall() throws Exception { 205 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 206 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null); 207 208 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 209 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 210 211 // Use TelecomManager API to answer the ringing call; the default expected behavior is to 212 // answer using whatever video state the ringing call requests. 213 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 214 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 215 telecomManager.acceptRingingCall(); 216 217 // Answer video API should be called 218 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 219 .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any()); 220 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 221 222 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 223 } 224 225 /** 226 * Tests the {@link TelecomManager#acceptRingingCall(int)} API. Tests answering a video call 227 * as an audio call. 228 * 229 * @throws Exception 230 */ 231 @LargeTest 232 @Test testTelecomManagerAcceptRingingVideoCallAsAudio()233 public void testTelecomManagerAcceptRingingVideoCallAsAudio() throws Exception { 234 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 235 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null); 236 237 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 238 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 239 240 // Use TelecomManager API to answer the ringing call. 241 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 242 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 243 telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY); 244 245 waitForHandlerAction(mTelecomSystem.getCallsManager() 246 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT); 247 248 // The generic answer method on the ConnectionService is used to answer audio-only calls. 249 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 250 .answer(eq(ids.mConnectionId), any()); 251 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 252 253 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 254 } 255 256 /** 257 * Tests the {@link TelecomManager#acceptRingingCall()} API. Tests simple case of an incoming 258 * video call, where an attempt is made to answer with an invalid video state. 259 * 260 * @throws Exception 261 */ 262 @LargeTest 263 @Test testTelecomManagerAcceptRingingInvalidVideoState()264 public void testTelecomManagerAcceptRingingInvalidVideoState() throws Exception { 265 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 266 VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA, null); 267 268 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 269 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 270 271 // Use TelecomManager API to answer the ringing call; the default expected behavior is to 272 // answer using whatever video state the ringing call requests. 273 TelecomManager telecomManager = (TelecomManager) mComponentContextFixture.getTestDouble() 274 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE); 275 telecomManager.acceptRingingCall(999 /* invalid videostate */); 276 277 waitForHandlerAction(mTelecomSystem.getCallsManager() 278 .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT); 279 280 // Answer video API should be called 281 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 282 .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any()); 283 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 284 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 285 } 286 287 @LargeTest 288 @Test testSingleIncomingCallLocalDisconnect()289 public void testSingleIncomingCallLocalDisconnect() throws Exception { 290 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 291 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 292 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 293 assertEquals(Call.STATE_DISCONNECTING, 294 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 295 assertEquals(Call.STATE_DISCONNECTING, 296 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 297 298 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME); 299 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME); 300 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 301 302 assertEquals(Call.STATE_DISCONNECTED, 303 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 304 assertEquals(Call.STATE_DISCONNECTED, 305 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 306 } 307 308 @LargeTest 309 @Test testSingleIncomingCallRemoteDisconnect()310 public void testSingleIncomingCallRemoteDisconnect() throws Exception { 311 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 312 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 313 314 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME); 315 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME); 316 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 317 assertEquals(Call.STATE_DISCONNECTED, 318 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 319 assertEquals(Call.STATE_DISCONNECTED, 320 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 321 } 322 323 @LargeTest 324 @Test testIncomingEmergencyCallback()325 public void testIncomingEmergencyCallback() throws Exception { 326 // Make an outgoing emergency call 327 String phoneNumber = "650-555-1212"; 328 IdPair ids = startAndMakeDialingEmergencyCall(phoneNumber, 329 mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA); 330 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 331 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 332 333 // Incoming call should be marked as a potential emergency callback 334 Bundle extras = new Bundle(); 335 extras.putParcelable( 336 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 337 Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null)); 338 mTelecomSystem.getTelecomServiceImpl().getBinder() 339 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 340 341 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 342 TEST_TIMEOUT); 343 ArgumentCaptor<ConnectionRequest> connectionRequestCaptor 344 = ArgumentCaptor.forClass(ConnectionRequest.class); 345 verify(mConnectionServiceFixtureA.getTestDouble()) 346 .createConnection(any(PhoneAccountHandle.class), anyString(), 347 connectionRequestCaptor.capture(), eq(true), eq(false), any()); 348 349 assertTrue(connectionRequestCaptor.getValue().getExtras().containsKey( 350 android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS)); 351 assertTrue(connectionRequestCaptor.getValue().getExtras().getLong( 352 android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS, 0) > 0); 353 assertTrue(connectionRequestCaptor.getValue().getExtras().containsKey( 354 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS)); 355 } 356 357 @LargeTest 358 @Test testOutgoingCallAndSelectPhoneAccount()359 public void testOutgoingCallAndSelectPhoneAccount() throws Exception { 360 // Remove default PhoneAccount so that the Call moves into the correct 361 // SELECT_PHONE_ACCOUNT state. 362 mTelecomSystem.getPhoneAccountRegistrar().setUserSelectedOutgoingPhoneAccount( 363 null, Process.myUserHandle()); 364 int startingNumConnections = mConnectionServiceFixtureA.mConnectionById.size(); 365 int startingNumCalls = mInCallServiceFixtureX.mCallById.size(); 366 String callId = startOutgoingPhoneCallWithNoPhoneAccount("650-555-1212", 367 mConnectionServiceFixtureA); 368 mTelecomSystem.getCallsManager().getLatestPreAccountSelectionFuture().join(); 369 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 370 TEST_TIMEOUT); 371 assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT, 372 mInCallServiceFixtureX.getCall(callId).getState()); 373 assertEquals(Call.STATE_SELECT_PHONE_ACCOUNT, 374 mInCallServiceFixtureY.getCall(callId).getState()); 375 mInCallServiceFixtureX.mInCallAdapter.phoneAccountSelected(callId, 376 mPhoneAccountA0.getAccountHandle(), false); 377 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 378 TEST_TIMEOUT); 379 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 380 TEST_TIMEOUT); 381 verifyAndProcessOutgoingCallBroadcast(mPhoneAccountA0.getAccountHandle()); 382 383 IdPair ids = outgoingCallPhoneAccountSelected(mPhoneAccountA0.getAccountHandle(), 384 startingNumConnections, startingNumCalls, mConnectionServiceFixtureA); 385 386 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME); 387 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME); 388 mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL); 389 assertEquals(Call.STATE_DISCONNECTED, 390 mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 391 assertEquals(Call.STATE_DISCONNECTED, 392 mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 393 } 394 395 @FlakyTest 396 @LargeTest 397 @Test testIncomingCallFromContactWithSendToVoicemailIsRejected()398 public void testIncomingCallFromContactWithSendToVoicemailIsRejected() throws Exception { 399 Bundle extras = new Bundle(); 400 extras.putParcelable( 401 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 402 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null)); 403 mTelecomSystem.getTelecomServiceImpl().getBinder() 404 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 405 406 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 407 TEST_TIMEOUT); 408 verify(mConnectionServiceFixtureA.getTestDouble()) 409 .createConnection(any(PhoneAccountHandle.class), anyString(), 410 any(ConnectionRequest.class), eq(true), eq(false), any()); 411 412 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 413 TEST_TIMEOUT); 414 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 415 416 CallerInfo sendToVoicemailCallerInfo = new CallerInfo(); 417 sendToVoicemailCallerInfo.shouldSendToVoicemail = true; 418 sendToVoicemailCallerInfo.contactExists = true; 419 mCallerInfoAsyncQueryFactoryFixture.setResponse(sendToVoicemailCallerInfo); 420 for (CallerInfoAsyncQueryFactoryFixture.Request request : 421 mCallerInfoAsyncQueryFactoryFixture.mRequests) { 422 request.replyWithCallerInfo(sendToVoicemailCallerInfo); 423 } 424 425 assertTrueWithTimeout(new Predicate<Void>() { 426 @Override 427 public boolean apply(Void aVoid) { 428 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1; 429 } 430 }); 431 assertTrueWithTimeout(new Predicate<Void>() { 432 @Override 433 public boolean apply(Void aVoid) { 434 return mMissedCallNotifier.missedCallsNotified.size() == 1; 435 } 436 }); 437 438 verify(mInCallServiceFixtureX.getTestDouble(), never()) 439 .setInCallAdapter(any(IInCallAdapter.class)); 440 verify(mInCallServiceFixtureY.getTestDouble(), never()) 441 .setInCallAdapter(any(IInCallAdapter.class)); 442 } 443 444 @LargeTest 445 @Test testIncomingCallCallerInfoLookupTimesOutIsAllowed()446 public void testIncomingCallCallerInfoLookupTimesOutIsAllowed() throws Exception { 447 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME); 448 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME); 449 Bundle extras = new Bundle(); 450 extras.putParcelable( 451 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 452 Uri.fromParts(PhoneAccount.SCHEME_TEL, "650-555-1212", null)); 453 mTelecomSystem.getTelecomServiceImpl().getBinder() 454 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 455 456 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 457 TEST_TIMEOUT); 458 verify(mConnectionServiceFixtureA.getTestDouble()) 459 .createConnection(any(PhoneAccountHandle.class), anyString(), 460 any(ConnectionRequest.class), eq(true), eq(false), any()); 461 462 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 463 TEST_TIMEOUT); 464 // Never reply to the caller info lookup. 465 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 466 467 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 468 .setInCallAdapter(any(IInCallAdapter.class)); 469 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 470 .setInCallAdapter(any(IInCallAdapter.class)); 471 472 assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size()); 473 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 474 475 assertTrueWithTimeout(new Predicate<Void>() { 476 @Override 477 public boolean apply(Void v) { 478 return mInCallServiceFixtureX.mInCallAdapter != null; 479 } 480 }); 481 482 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 483 .addCall(any(ParcelableCall.class)); 484 verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT)) 485 .addCall(any(ParcelableCall.class)); 486 487 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME); 488 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME); 489 disconnectCall(mInCallServiceFixtureX.mLatestCallId, 490 mConnectionServiceFixtureA.mLatestConnectionId); 491 } 492 493 @LargeTest 494 @Test 495 @FlakyTest 496 @Ignore("b/189904580") testIncomingCallFromBlockedNumberIsRejected()497 public void testIncomingCallFromBlockedNumberIsRejected() throws Exception { 498 String phoneNumber = "650-555-1212"; 499 blockNumber(phoneNumber); 500 501 Bundle extras = new Bundle(); 502 extras.putParcelable( 503 TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, 504 Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null)); 505 mTelecomSystem.getTelecomServiceImpl().getBinder() 506 .addNewIncomingCall(mPhoneAccountA0.getAccountHandle(), extras); 507 508 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 509 TEST_TIMEOUT); 510 verify(mConnectionServiceFixtureA.getTestDouble()) 511 .createConnection(any(PhoneAccountHandle.class), anyString(), 512 any(ConnectionRequest.class), eq(true), eq(false), any()); 513 514 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 515 TEST_TIMEOUT); 516 517 assertEquals(1, mCallerInfoAsyncQueryFactoryFixture.mRequests.size()); 518 for (CallerInfoAsyncQueryFactoryFixture.Request request : 519 mCallerInfoAsyncQueryFactoryFixture.mRequests) { 520 request.reply(); 521 } 522 523 assertTrueWithTimeout(new Predicate<Void>() { 524 @Override 525 public boolean apply(Void aVoid) { 526 return mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size() == 1; 527 } 528 }); 529 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 530 531 verify(mInCallServiceFixtureX.getTestDouble(), never()) 532 .setInCallAdapter(any(IInCallAdapter.class)); 533 verify(mInCallServiceFixtureY.getTestDouble(), never()) 534 .setInCallAdapter(any(IInCallAdapter.class)); 535 } 536 537 @LargeTest 538 @Test testIncomingCallBlockCheckTimesoutIsAllowed()539 public void testIncomingCallBlockCheckTimesoutIsAllowed() throws Exception { 540 final CountDownLatch latch = new CountDownLatch(1); 541 String phoneNumber = "650-555-1212"; 542 blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() { 543 @Override 544 public Bundle answer(InvocationOnMock invocation) throws Throwable { 545 latch.await(TEST_TIMEOUT * 2, TimeUnit.MILLISECONDS); 546 Bundle bundle = new Bundle(); 547 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, true); 548 return bundle; 549 } 550 }); 551 552 IdPair ids = startAndMakeActiveIncomingCall( 553 phoneNumber, mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 554 latch.countDown(); 555 556 assertEquals(0, mConnectionServiceFixtureA.mConnectionService.rejectedCallIds.size()); 557 assertEquals(0, mMissedCallNotifier.missedCallsNotified.size()); 558 disconnectCall(ids.mCallId, ids.mConnectionId); 559 } 560 do_testDeadlockOnOutgoingCall()561 public void do_testDeadlockOnOutgoingCall() throws Exception { 562 final IdPair ids = startOutgoingPhoneCall("650-555-1212", 563 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, 564 Process.myUserHandle()); 565 rapidFire( 566 new Runnable() { 567 @Override 568 public void run() { 569 while (mCallerInfoAsyncQueryFactoryFixture.mRequests.size() > 0) { 570 mCallerInfoAsyncQueryFactoryFixture.mRequests.remove(0).reply(); 571 } 572 } 573 }, 574 new Runnable() { 575 @Override 576 public void run() { 577 try { 578 mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId); 579 } catch (Exception e) { 580 Log.e(this, e, ""); 581 } 582 } 583 }); 584 } 585 586 @LargeTest 587 @Test testIncomingThenOutgoingCalls()588 public void testIncomingThenOutgoingCalls() throws Exception { 589 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 590 IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", 591 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 592 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 593 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 594 595 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); 596 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); 597 } 598 599 @LargeTest 600 @Test testOutgoingThenIncomingCalls()601 public void testOutgoingThenIncomingCalls() throws Exception { 602 // TODO: We have to use the same PhoneAccount for both; see http://b/18461539 603 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 604 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 605 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 606 TEST_TIMEOUT); 607 IdPair incoming = startAndMakeActiveIncomingCall("650-555-2323", 608 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 609 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 610 TEST_TIMEOUT); 611 verify(mConnectionServiceFixtureA.getTestDouble()) 612 .hold(eq(outgoing.mConnectionId), any()); 613 mConnectionServiceFixtureA.mConnectionById.get(outgoing.mConnectionId).state = 614 Connection.STATE_HOLDING; 615 mConnectionServiceFixtureA.sendSetOnHold(outgoing.mConnectionId); 616 assertEquals(Call.STATE_HOLDING, 617 mInCallServiceFixtureX.getCall(outgoing.mCallId).getState()); 618 assertEquals(Call.STATE_HOLDING, 619 mInCallServiceFixtureY.getCall(outgoing.mCallId).getState()); 620 621 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(incoming.mCallId); 622 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(outgoing.mCallId); 623 } 624 625 @LargeTest 626 @Test testAudioManagerOperations()627 public void testAudioManagerOperations() throws Exception { 628 AudioManager audioManager = (AudioManager) mComponentContextFixture.getTestDouble() 629 .getApplicationContext().getSystemService(Context.AUDIO_SERVICE); 630 631 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1212", 632 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 633 634 verify(audioManager, timeout(TEST_TIMEOUT)).requestAudioFocusForCall(anyInt(), anyInt()); 635 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 636 .setMode(AudioManager.MODE_IN_CALL); 637 638 mInCallServiceFixtureX.mInCallAdapter.mute(true); 639 verify(mAudioService, timeout(TEST_TIMEOUT)) 640 .setMicrophoneMute(eq(true), any(String.class), any(Integer.class), 641 nullable(String.class)); 642 mInCallServiceFixtureX.mInCallAdapter.mute(false); 643 verify(mAudioService, timeout(TEST_TIMEOUT)) 644 .setMicrophoneMute(eq(false), any(String.class), any(Integer.class), 645 nullable(String.class)); 646 647 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_SPEAKER, null); 648 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 649 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); 650 ArgumentCaptor<AudioDeviceInfo> infoArgumentCaptor = 651 ArgumentCaptor.forClass(AudioDeviceInfo.class); 652 verify(audioManager, timeout(TEST_TIMEOUT)).setCommunicationDevice( 653 infoArgumentCaptor.capture()); 654 assertEquals(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, infoArgumentCaptor.getValue().getType()); 655 mInCallServiceFixtureX.mInCallAdapter.setAudioRoute(CallAudioState.ROUTE_EARPIECE, null); 656 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 657 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); 658 // setSpeakerPhoneOn(false) gets called once during the call initiation phase 659 verify(audioManager, timeout(TEST_TIMEOUT).atLeast(1)) 660 .clearCommunicationDevice(); 661 662 mConnectionServiceFixtureA. 663 sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE); 664 665 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 666 .getCallAudioModeStateMachine().getHandler(), TEST_TIMEOUT); 667 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 668 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); 669 verify(audioManager, timeout(TEST_TIMEOUT)) 670 .abandonAudioFocusForCall(); 671 verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce()) 672 .setMode(AudioManager.MODE_NORMAL); 673 } 674 rapidFire(Runnable... tasks)675 private void rapidFire(Runnable... tasks) { 676 final CyclicBarrier barrier = new CyclicBarrier(tasks.length); 677 final CountDownLatch latch = new CountDownLatch(tasks.length); 678 for (int i = 0; i < tasks.length; i++) { 679 final Runnable task = tasks[i]; 680 new Thread(new Runnable() { 681 @Override 682 public void run() { 683 try { 684 barrier.await(); 685 task.run(); 686 } catch (InterruptedException | BrokenBarrierException e){ 687 Log.e(BasicCallTests.this, e, "Unexpectedly interrupted"); 688 } finally { 689 latch.countDown(); 690 } 691 } 692 }).start(); 693 } 694 try { 695 latch.await(); 696 } catch (InterruptedException e) { 697 Log.e(BasicCallTests.this, e, "Unexpectedly interrupted"); 698 } 699 } 700 701 @MediumTest 702 @Test testBasicConferenceCall()703 public void testBasicConferenceCall() throws Exception { 704 makeConferenceCall(null, null); 705 } 706 707 @MediumTest 708 @Test testAddCallToConference1()709 public void testAddCallToConference1() throws Exception { 710 ParcelableCall conferenceCall = makeConferenceCall(null, null); 711 IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", 712 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 713 // testAddCallToConference{1,2} differ in the order of arguments to InCallAdapter#conference 714 mInCallServiceFixtureX.getInCallAdapter().conference( 715 conferenceCall.getId(), callId3.mCallId); 716 Thread.sleep(200); 717 718 ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId); 719 ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId()); 720 assertEquals(conferenceCall.getId(), call3.getParentCallId()); 721 assertEquals(3, updatedConference.getChildCallIds().size()); 722 assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId)); 723 } 724 725 @MediumTest 726 @Test testAddCallToConference2()727 public void testAddCallToConference2() throws Exception { 728 ParcelableCall conferenceCall = makeConferenceCall(null, null); 729 IdPair callId3 = startAndMakeActiveOutgoingCall("650-555-1214", 730 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 731 mInCallServiceFixtureX.getInCallAdapter() 732 .conference(callId3.mCallId, conferenceCall.getId()); 733 Thread.sleep(200); 734 735 ParcelableCall call3 = mInCallServiceFixtureX.getCall(callId3.mCallId); 736 ParcelableCall updatedConference = mInCallServiceFixtureX.getCall(conferenceCall.getId()); 737 assertEquals(conferenceCall.getId(), call3.getParentCallId()); 738 assertEquals(3, updatedConference.getChildCallIds().size()); 739 assertTrue(updatedConference.getChildCallIds().contains(callId3.mCallId)); 740 } 741 742 /** 743 * Tests the {@link Call#pullExternalCall()} API. Verifies that if a call is not an external 744 * call, no pull call request is made to the connection service. 745 * 746 * @throws Exception 747 */ 748 @MediumTest 749 @Test testPullNonExternalCall()750 public void testPullNonExternalCall() throws Exception { 751 // TODO: Revisit this unit test once telecom support for filtering external calls from 752 // InCall services is implemented. 753 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 754 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 755 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 756 757 // Attempt to pull the call and verify the API call makes it through 758 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 759 Thread.sleep(TEST_TIMEOUT); 760 verify(mConnectionServiceFixtureA.getTestDouble(), never()) 761 .pullExternalCall(eq(ids.mCallId), any()); 762 } 763 764 /** 765 * Tests the {@link Connection#sendConnectionEvent(String, Bundle)} API. 766 * 767 * @throws Exception 768 */ 769 @MediumTest 770 @Test testSendConnectionEventNull()771 public void testSendConnectionEventNull() throws Exception { 772 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 773 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 774 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 775 mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, null); 776 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 777 .onConnectionEvent(ids.mCallId, TEST_EVENT, null); 778 } 779 780 /** 781 * Tests the {@link Connection#sendConnectionEvent(String, Bundle)} API. 782 * 783 * @throws Exception 784 */ 785 @MediumTest 786 @Test testSendConnectionEventNotNull()787 public void testSendConnectionEventNotNull() throws Exception { 788 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 789 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 790 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 791 792 Bundle testBundle = new Bundle(); 793 testBundle.putString(TEST_BUNDLE_KEY, "TEST"); 794 795 ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class); 796 mConnectionServiceFixtureA.sendConnectionEvent(ids.mConnectionId, TEST_EVENT, testBundle); 797 verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT)) 798 .onConnectionEvent(eq(ids.mCallId), eq(TEST_EVENT), bundleArgumentCaptor.capture()); 799 assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY)); 800 } 801 802 /** 803 * Tests the {@link Call#sendCallEvent(String, Bundle)} API. 804 * 805 * @throws Exception 806 */ 807 @MediumTest 808 @Test testSendCallEventNull()809 public void testSendCallEventNull() throws Exception { 810 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 811 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 812 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 813 814 mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 26, null); 815 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 816 .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT), isNull(Bundle.class), any()); 817 } 818 819 /** 820 * Tests the {@link Call#sendCallEvent(String, Bundle)} API. 821 * 822 * @throws Exception 823 */ 824 @MediumTest 825 @Test testSendCallEventNonNull()826 public void testSendCallEventNonNull() throws Exception { 827 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 828 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 829 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 830 831 Bundle testBundle = new Bundle(); 832 testBundle.putString(TEST_BUNDLE_KEY, "TEST"); 833 834 ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class); 835 mInCallServiceFixtureX.mInCallAdapter.sendCallEvent(ids.mCallId, TEST_EVENT, 26, 836 testBundle); 837 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 838 .sendCallEvent(eq(ids.mConnectionId), eq(TEST_EVENT), 839 bundleArgumentCaptor.capture(), any()); 840 assert (bundleArgumentCaptor.getValue().containsKey(TEST_BUNDLE_KEY)); 841 } 842 blockNumber(String phoneNumber)843 private void blockNumber(String phoneNumber) throws Exception { 844 blockNumberWithAnswer(phoneNumber, new Answer<Bundle>() { 845 @Override 846 public Bundle answer(InvocationOnMock invocation) throws Throwable { 847 Bundle bundle = new Bundle(); 848 bundle.putInt(BlockedNumberContract.RES_BLOCK_STATUS, 849 BlockedNumberContract.STATUS_BLOCKED_IN_LIST); 850 return bundle; 851 } 852 }); 853 } 854 blockNumberWithAnswer(String phoneNumber, Answer answer)855 private void blockNumberWithAnswer(String phoneNumber, Answer answer) throws Exception { 856 when(getBlockedNumberProvider().call( 857 any(), 858 anyString(), 859 eq(BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER), 860 eq(phoneNumber), 861 nullable(Bundle.class))).thenAnswer(answer); 862 } 863 verifyNoBlockChecks()864 private void verifyNoBlockChecks() { 865 verifyZeroInteractions(getBlockedNumberProvider()); 866 } 867 getBlockedNumberProvider()868 private IContentProvider getBlockedNumberProvider() { 869 return mSpyContext.getContentResolver().acquireProvider(BlockedNumberContract.AUTHORITY); 870 } 871 disconnectCall(String callId, String connectionId)872 private void disconnectCall(String callId, String connectionId) throws Exception { 873 when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME); 874 when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME); 875 mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL); 876 assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState()); 877 assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState()); 878 assertEquals(TEST_CREATE_TIME, 879 mInCallServiceFixtureX.getCall(callId).getCreationTimeMillis()); 880 assertEquals(TEST_CREATE_TIME, 881 mInCallServiceFixtureY.getCall(callId).getCreationTimeMillis()); 882 } 883 884 /** 885 * Tests to make sure that the Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is set on a 886 * Call that is based on a Connection with the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY 887 * property set. 888 */ 889 @MediumTest 890 @Test testCdmaEnhancedPrivacyVoiceCall()891 public void testCdmaEnhancedPrivacyVoiceCall() throws Exception { 892 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 893 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY; 894 895 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 896 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 897 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 898 899 assertTrue(Call.Details.hasProperty( 900 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(), 901 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)); 902 } 903 904 /** 905 * Tests to make sure that Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY is dropped 906 * when the Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY property is removed from the Connection. 907 */ 908 @MediumTest 909 @Test testDropCdmaEnhancedPrivacyVoiceCall()910 public void testDropCdmaEnhancedPrivacyVoiceCall() throws Exception { 911 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 912 Connection.PROPERTY_HAS_CDMA_VOICE_PRIVACY; 913 914 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", 915 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 916 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 917 mConnectionServiceFixtureA.mLatestConnection.setConnectionProperties(0); 918 919 assertFalse(Call.Details.hasProperty( 920 mInCallServiceFixtureX.getCall(ids.mCallId).getProperties(), 921 Call.Details.PROPERTY_HAS_CDMA_VOICE_PRIVACY)); 922 } 923 924 /** 925 * Tests the {@link Call#pullExternalCall()} API. Ensures that an external call which is 926 * pullable can be pulled. 927 * 928 * @throws Exception 929 */ 930 @LargeTest 931 @Test testPullExternalCall()932 public void testPullExternalCall() throws Exception { 933 // TODO: Revisit this unit test once telecom support for filtering external calls from 934 // InCall services is implemented. 935 mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 936 Connection.CAPABILITY_CAN_PULL_CALL; 937 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 938 Connection.PROPERTY_IS_EXTERNAL_CALL; 939 940 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 941 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 942 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 943 944 // Attempt to pull the call and verify the API call makes it through 945 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 946 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 947 .pullExternalCall(eq(ids.mConnectionId), any()); 948 } 949 950 /** 951 * Tests the {@link Call#pullExternalCall()} API. Verifies that if an external call is not 952 * marked as pullable that the connection service does not get an API call to pull the external 953 * call. 954 * 955 * @throws Exception 956 */ 957 @LargeTest 958 @Test testPullNonPullableExternalCall()959 public void testPullNonPullableExternalCall() throws Exception { 960 // TODO: Revisit this unit test once telecom support for filtering external calls from 961 // InCall services is implemented. 962 mConnectionServiceFixtureA.mConnectionServiceDelegate.mProperties = 963 Connection.PROPERTY_IS_EXTERNAL_CALL; 964 965 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 966 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 967 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 968 969 // Attempt to pull the call and verify the API call makes it through 970 mInCallServiceFixtureX.mInCallAdapter.pullExternalCall(ids.mCallId); 971 Thread.sleep(TEST_TIMEOUT); 972 verify(mConnectionServiceFixtureA.getTestDouble(), never()) 973 .pullExternalCall(eq(ids.mConnectionId), any()); 974 } 975 976 /** 977 * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and 978 * then subsequently selects a PhoneAccount which supports video calling. 979 * @throws Exception 980 */ 981 @LargeTest 982 @Test testOutgoingCallSelectPhoneAccountVideo()983 public void testOutgoingCallSelectPhoneAccountVideo() throws Exception { 984 startOutgoingPhoneCallPendingCreateConnection("650-555-1212", 985 null, mConnectionServiceFixtureA, 986 Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null); 987 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 988 .iterator().next(); 989 assert(call.isVideoCallingSupportedByPhoneAccount()); 990 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 991 992 // Change the phone account to one which supports video calling. 993 call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle()); 994 assert(call.isVideoCallingSupportedByPhoneAccount()); 995 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 996 } 997 998 /** 999 * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and 1000 * then subsequently selects a PhoneAccount which does not support video calling. 1001 * @throws Exception 1002 */ 1003 @FlakyTest 1004 @LargeTest 1005 @Test testOutgoingCallSelectPhoneAccountNoVideo()1006 public void testOutgoingCallSelectPhoneAccountNoVideo() throws Exception { 1007 startOutgoingPhoneCallPendingCreateConnection("650-555-1212", 1008 null, mConnectionServiceFixtureA, 1009 Process.myUserHandle(), VideoProfile.STATE_BIDIRECTIONAL, null); 1010 com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls() 1011 .iterator().next(); 1012 assert(call.isVideoCallingSupportedByPhoneAccount()); 1013 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 1014 1015 // Change the phone account to one which does not support video calling. 1016 call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle()); 1017 assert(!call.isVideoCallingSupportedByPhoneAccount()); 1018 assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState()); 1019 } 1020 1021 /** 1022 * Basic test to ensure that a self-managed ConnectionService can place a call. 1023 * @throws Exception 1024 */ 1025 @LargeTest 1026 @Test testSelfManagedOutgoing()1027 public void testSelfManagedOutgoing() throws Exception { 1028 PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle(); 1029 IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", phoneAccountHandle, 1030 mConnectionServiceFixtureA); 1031 1032 // The InCallService should not know about the call since its self-managed. 1033 assertNull(mInCallServiceFixtureX.getCall(ids.mCallId)); 1034 } 1035 1036 /** 1037 * Basic test to ensure that a self-managed ConnectionService can add an incoming call. 1038 * @throws Exception 1039 */ 1040 @LargeTest 1041 @Test testSelfManagedIncoming()1042 public void testSelfManagedIncoming() throws Exception { 1043 PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle(); 1044 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle, 1045 mConnectionServiceFixtureA); 1046 1047 // The InCallService should not know about the call since its self-managed. 1048 assertNull(mInCallServiceFixtureX.getCall(ids.mCallId)); 1049 } 1050 1051 /** 1052 * Basic test to ensure that when there are no calls, we permit outgoing calls by a self managed 1053 * CS. 1054 * @throws Exception 1055 */ 1056 @LargeTest 1057 @Test testIsOutgoingCallPermitted()1058 public void testIsOutgoingCallPermitted() throws Exception { 1059 assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() 1060 .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle(), 1061 mPhoneAccountSelfManaged.getAccountHandle().getComponentName() 1062 .getPackageName())); 1063 } 1064 1065 /** 1066 * Ensure if there is a holdable call ongoing we'll be able to place another call. 1067 * @throws Exception 1068 */ 1069 @LargeTest 1070 @Test testIsOutgoingCallPermittedOngoingHoldable()1071 public void testIsOutgoingCallPermittedOngoingHoldable() throws Exception { 1072 // Start a regular call; the self-managed CS can make a call now since ongoing call can be 1073 // held 1074 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 1075 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 1076 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1077 1078 assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() 1079 .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle(), 1080 mPhoneAccountSelfManaged.getAccountHandle().getComponentName() 1081 .getPackageName())); 1082 } 1083 1084 /** 1085 * Ensure if there is an unholdable call we can't place another call. 1086 * @throws Exception 1087 */ 1088 @LargeTest 1089 @Test testIsOutgoingCallPermittedOngoingUnHoldable()1090 public void testIsOutgoingCallPermittedOngoingUnHoldable() throws Exception { 1091 // Start a regular call; the self-managed CS can't make a call now because the ongoing call 1092 // can't be held. 1093 mConnectionServiceFixtureA.mConnectionServiceDelegate.mCapabilities = 0; 1094 IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", 1095 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 1096 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1097 1098 assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder() 1099 .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle(), 1100 mPhoneAccountSelfManaged.getAccountHandle().getComponentName() 1101 .getPackageName())); 1102 } 1103 1104 /** 1105 * Basic to verify audio route gets reset to baseline when emergency call placed while a 1106 * self-managed call is underway. 1107 * @throws Exception 1108 */ 1109 @LargeTest 1110 @Test 1111 @FlakyTest testDisconnectSelfManaged()1112 public void testDisconnectSelfManaged() throws Exception { 1113 // Add a self-managed call. 1114 PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle(); 1115 startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle, 1116 mConnectionServiceFixtureA); 1117 Connection connection = mConnectionServiceFixtureA.mLatestConnection; 1118 1119 // Route self-managed call to speaker. 1120 connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER); 1121 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 1122 TEST_TIMEOUT); 1123 1124 // Place an emergency call. 1125 startAndMakeDialingEmergencyCall("650-555-1212", mPhoneAccountE0.getAccountHandle(), 1126 mConnectionServiceFixtureA); 1127 1128 // Should have reverted back to earpiece. 1129 assertTrueWithTimeout(new Predicate<Void>() { 1130 @Override 1131 public boolean apply(Void aVoid) { 1132 return mInCallServiceFixtureX.mCallAudioState.getRoute() 1133 == CallAudioState.ROUTE_EARPIECE; 1134 } 1135 }); 1136 } 1137 1138 /** 1139 * Tests the {@link Call#deflect} API. Verifies that if a call is incoming, 1140 * and deflect API is called, then request is made to the connection service. 1141 * 1142 * @throws Exception 1143 */ 1144 @LargeTest 1145 @Test testDeflectCallWhenIncoming()1146 public void testDeflectCallWhenIncoming() throws Exception { 1147 Uri deflectAddress = Uri.parse("tel:650-555-1214"); 1148 IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 1149 mConnectionServiceFixtureA); 1150 1151 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState()); 1152 assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState()); 1153 // Attempt to deflect the call and verify the API call makes it through 1154 mInCallServiceFixtureX.mInCallAdapter.deflectCall(ids.mCallId, deflectAddress); 1155 verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT)) 1156 .deflect(eq(ids.mConnectionId), eq(deflectAddress), any()); 1157 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 1158 } 1159 1160 /** 1161 * Tests the {@link Call#deflect} API. Verifies that if a call is outgoing, 1162 * and deflect API is called, then request is not made to the connection service. 1163 * Ideally, deflect option should be displayed only if call is incoming/waiting. 1164 * 1165 * @throws Exception 1166 */ 1167 @LargeTest 1168 @Test testDeflectCallWhenOutgoing()1169 public void testDeflectCallWhenOutgoing() throws Exception { 1170 Uri deflectAddress = Uri.parse("tel:650-555-1214"); 1171 IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(), 1172 mConnectionServiceFixtureA, Process.myUserHandle()); 1173 // Attempt to deflect the call and verify the API call does not make it through 1174 mInCallServiceFixtureX.mInCallAdapter.deflectCall(ids.mCallId, deflectAddress); 1175 verify(mConnectionServiceFixtureA.getTestDouble(), never()) 1176 .deflect(eq(ids.mConnectionId), eq(deflectAddress), any()); 1177 mInCallServiceFixtureX.mInCallAdapter.disconnectCall(ids.mCallId); 1178 } 1179 1180 /** 1181 * Test to make sure to unmute automatically when making an emergency call and keep unmute 1182 * during the emergency call. 1183 * @throws Exception 1184 */ 1185 @LargeTest 1186 @Test 1187 @FlakyTest testUnmuteDuringEmergencyCall()1188 public void testUnmuteDuringEmergencyCall() throws Exception { 1189 // Make an outgoing call and turn ON mute. 1190 IdPair outgoingCall = startAndMakeActiveOutgoingCall("650-555-1212", 1191 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 1192 assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(outgoingCall.mCallId) 1193 .getState()); 1194 mInCallServiceFixtureX.mInCallAdapter.mute(true); 1195 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 1196 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); 1197 assertTrue(mTelecomSystem.getCallsManager().getAudioState().isMuted()); 1198 1199 // Make an emergency call. 1200 IdPair emergencyCall = startAndMakeDialingEmergencyCall("650-555-1213", 1201 mPhoneAccountE0.getAccountHandle(), mConnectionServiceFixtureA); 1202 assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(emergencyCall.mCallId) 1203 .getState()); 1204 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 1205 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); 1206 // Should be unmute automatically. 1207 assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted()); 1208 1209 // Toggle mute during an emergency call. 1210 mTelecomSystem.getCallsManager().getCallAudioManager().toggleMute(); 1211 waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager() 1212 .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT); 1213 // Should keep unmute. 1214 assertFalse(mTelecomSystem.getCallsManager().getAudioState().isMuted()); 1215 1216 ArgumentCaptor<Boolean> muteValueCaptor = ArgumentCaptor.forClass(Boolean.class); 1217 verify(mAudioService, times(2)).setMicrophoneMute(muteValueCaptor.capture(), 1218 any(String.class), any(Integer.class), nullable(String.class)); 1219 List<Boolean> muteValues = muteValueCaptor.getAllValues(); 1220 // Check mute status was changed twice with true and false. 1221 assertTrue(muteValues.get(0)); 1222 assertFalse(muteValues.get(1)); 1223 } 1224 1225 /** 1226 * Verifies that StatusHints image is validated in ConnectionServiceWrapper#addConferenceCall 1227 * when the image doesn't belong to the calling user. Simulates a scenario where an app 1228 * could manipulate the contents of the bundle and send it via the binder to upload an image 1229 * from another user. 1230 * 1231 * @throws Exception 1232 */ 1233 @SmallTest 1234 @Test testValidateStatusHintsImage_addConferenceCall()1235 public void testValidateStatusHintsImage_addConferenceCall() throws Exception { 1236 Intent callIntent1 = new Intent(); 1237 // Stub intent for call2 1238 Intent callIntent2 = new Intent(); 1239 Bundle callExtras1 = new Bundle(); 1240 Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); 1241 // Load StatusHints extra into TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS to be processed 1242 // as the call extras. This will be leveraged in ConnectionServiceFixture to set the 1243 // StatusHints for the given connection. 1244 StatusHints statusHints = new StatusHints(icon); 1245 assertNotNull(statusHints.getIcon()); 1246 callExtras1.putParcelable(STATUS_HINTS_EXTRA, statusHints); 1247 callIntent1.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras1); 1248 1249 // Start conference call to invoke ConnectionServiceWrapper#addConferenceCall. 1250 // Note that the calling user would be User 0. 1251 ParcelableCall conferenceCall = makeConferenceCall(callIntent1, callIntent2); 1252 1253 // Ensure that StatusHints was set. 1254 assertNotNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId) 1255 .getStatusHints()); 1256 // Ensure that the StatusHints image icon was disregarded. 1257 assertNull(mInCallServiceFixtureX.getCall(mInCallServiceFixtureX.mLatestCallId) 1258 .getStatusHints().getIcon()); 1259 } 1260 1261 /** 1262 * Verifies that StatusHints image is validated in 1263 * ConnectionServiceWrapper#handleCreateConnectionComplete when the image doesn't belong to the 1264 * calling user. Simulates a scenario where an app could manipulate the contents of the 1265 * bundle and send it via the binder to upload an image from another user. 1266 * 1267 * @throws Exception 1268 */ 1269 @SmallTest 1270 @Test testValidateStatusHintsImage_handleCreateConnectionComplete()1271 public void testValidateStatusHintsImage_handleCreateConnectionComplete() throws Exception { 1272 Bundle extras = new Bundle(); 1273 Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); 1274 // Load the bundle with the test extra in order to simulate an app directly invoking the 1275 // binder on ConnectionServiceWrapper#handleCreateConnectionComplete. 1276 StatusHints statusHints = new StatusHints(icon); 1277 assertNotNull(statusHints.getIcon()); 1278 extras.putParcelable(STATUS_HINTS_EXTRA, statusHints); 1279 1280 // Start incoming call with StatusHints extras 1281 // Note that the calling user in ConnectionServiceWrapper#handleCreateConnectionComplete 1282 // would be User 0. 1283 IdPair ids = startIncomingPhoneCallWithExtras("650-555-1212", 1284 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA, extras); 1285 1286 // Ensure that StatusHints was set. 1287 assertNotNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints()); 1288 // Ensure that the StatusHints image icon was disregarded. 1289 assertNull(mInCallServiceFixtureX.getCall(ids.mCallId).getStatusHints().getIcon()); 1290 } 1291 1292 /** 1293 * Verifies that StatusHints image is validated in ConnectionServiceWrapper#setStatusHints 1294 * when the image doesn't belong to the calling user. Simulates a scenario where an app 1295 * could manipulate the contents of the bundle and send it via the binder to upload an image 1296 * from another user. 1297 * 1298 * @throws Exception 1299 */ 1300 @SmallTest 1301 @Test testValidateStatusHintsImage_setStatusHints()1302 public void testValidateStatusHintsImage_setStatusHints() throws Exception { 1303 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214", 1304 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 1305 1306 // Modify existing connection with StatusHints image exploit 1307 Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); 1308 StatusHints statusHints = new StatusHints(icon); 1309 assertNotNull(statusHints.getIcon()); 1310 ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA 1311 .mConnectionById.get(outgoing.mConnectionId); 1312 connectionInfo.statusHints = statusHints; 1313 1314 // Invoke ConnectionServiceWrapper#setStatusHints. 1315 // Note that the calling user would be User 0. 1316 mConnectionServiceFixtureA.sendSetStatusHints(outgoing.mConnectionId); 1317 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 1318 TEST_TIMEOUT); 1319 1320 // Ensure that StatusHints was set. 1321 assertNotNull(mInCallServiceFixtureX.getCall(outgoing.mCallId).getStatusHints()); 1322 // Ensure that the StatusHints image icon was disregarded. 1323 assertNull(mInCallServiceFixtureX.getCall(outgoing.mCallId) 1324 .getStatusHints().getIcon()); 1325 } 1326 1327 /** 1328 * Verifies that StatusHints image is validated in 1329 * ConnectionServiceWrapper#addExistingConnection when the image doesn't belong to the calling 1330 * user. Simulates a scenario where an app could manipulate the contents of the bundle and 1331 * send it via the binder to upload an image from another user. 1332 * 1333 * @throws Exception 1334 */ 1335 @SmallTest 1336 @Test testValidateStatusHintsImage_addExistingConnection()1337 public void testValidateStatusHintsImage_addExistingConnection() throws Exception { 1338 IdPair outgoing = startAndMakeActiveOutgoingCall("650-555-1214", 1339 mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA); 1340 Connection existingConnection = mConnectionServiceFixtureA.mLatestConnection; 1341 1342 // Modify existing connection with StatusHints image exploit 1343 Icon icon = Icon.createWithContentUri("content://10@media/external/images/media/"); 1344 StatusHints modifiedStatusHints = new StatusHints(icon); 1345 assertNotNull(modifiedStatusHints.getIcon()); 1346 ConnectionServiceFixture.ConnectionInfo connectionInfo = mConnectionServiceFixtureA 1347 .mConnectionById.get(outgoing.mConnectionId); 1348 connectionInfo.statusHints = modifiedStatusHints; 1349 1350 // Invoke ConnectionServiceWrapper#addExistingConnection. 1351 // Note that the calling user would be User 0. 1352 mConnectionServiceFixtureA.sendAddExistingConnection(outgoing.mConnectionId); 1353 waitForHandlerAction(mConnectionServiceFixtureA.mConnectionServiceDelegate.getHandler(), 1354 TEST_TIMEOUT); 1355 1356 // Ensure that StatusHints was set. Due to test setup, the ParcelableConnection object that 1357 // is passed into sendAddExistingConnection is instantiated on invocation. The call's 1358 // StatusHints are not updated at the time of completion, so instead, we can verify that 1359 // the ParcelableConnection object was modified. 1360 assertNotNull(mConnectionServiceFixtureA.mLatestParcelableConnection.getStatusHints()); 1361 // Ensure that the StatusHints image icon was disregarded. 1362 assertNull(mConnectionServiceFixtureA.mLatestParcelableConnection 1363 .getStatusHints().getIcon()); 1364 } 1365 } 1366