1 /* 2 * Copyright (C) 2019 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 org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.anyBoolean; 26 import static org.mockito.ArgumentMatchers.argThat; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.times; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.when; 34 35 import android.content.ComponentName; 36 import android.content.Intent; 37 import android.content.pm.PackageManager; 38 import android.content.res.Resources; 39 import android.graphics.Bitmap; 40 import android.graphics.drawable.ColorDrawable; 41 import android.net.Uri; 42 import android.os.Bundle; 43 import android.os.PersistableBundle; 44 import android.os.UserHandle; 45 import android.telecom.CallAttributes; 46 import android.telecom.CallEndpoint; 47 import android.telecom.CallerInfo; 48 import android.telecom.Connection; 49 import android.telecom.DisconnectCause; 50 import android.telecom.ParcelableConference; 51 import android.telecom.ParcelableConnection; 52 import android.telecom.PhoneAccount; 53 import android.telecom.PhoneAccountHandle; 54 import android.telecom.StatusHints; 55 import android.telecom.TelecomManager; 56 import android.telecom.VideoProfile; 57 import android.telephony.CallQuality; 58 59 import androidx.test.ext.junit.runners.AndroidJUnit4; 60 import androidx.test.filters.SmallTest; 61 62 import com.android.server.telecom.CachedAvailableEndpointsChange; 63 import com.android.server.telecom.CachedCallEventQueue; 64 import com.android.server.telecom.CachedCurrentEndpointChange; 65 import com.android.server.telecom.CachedMuteStateChange; 66 import com.android.server.telecom.Call; 67 import com.android.server.telecom.CallIdMapper; 68 import com.android.server.telecom.CallState; 69 import com.android.server.telecom.CallerInfoLookupHelper; 70 import com.android.server.telecom.CallsManager; 71 import com.android.server.telecom.ClockProxy; 72 import com.android.server.telecom.ConnectionServiceWrapper; 73 import com.android.server.telecom.EmergencyCallHelper; 74 import com.android.server.telecom.PhoneAccountRegistrar; 75 import com.android.server.telecom.PhoneNumberUtilsAdapter; 76 import com.android.server.telecom.TelecomSystem; 77 import com.android.server.telecom.TransactionalServiceWrapper; 78 import com.android.server.telecom.ui.ToastFactory; 79 80 import org.junit.After; 81 import org.junit.Before; 82 import org.junit.Test; 83 import org.junit.runner.RunWith; 84 import org.mockito.ArgumentCaptor; 85 import org.mockito.Mock; 86 import org.mockito.Mockito; 87 88 import java.util.Collections; 89 import java.util.Set; 90 91 @RunWith(AndroidJUnit4.class) 92 public class CallTest extends TelecomTestCase { 93 private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212"); 94 private static final ComponentName COMPONENT_NAME_1 = ComponentName 95 .unflattenFromString("com.foo/.Blah"); 96 private static final ComponentName COMPONENT_NAME_2 = ComponentName 97 .unflattenFromString("com.bar/.Blah"); 98 private static final PhoneAccountHandle SIM_1_HANDLE = new PhoneAccountHandle( 99 COMPONENT_NAME_1, "Sim1"); 100 private static final PhoneAccount SIM_1_ACCOUNT = new PhoneAccount.Builder(SIM_1_HANDLE, "Sim1") 101 .setCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION 102 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 103 .setIsEnabled(true) 104 .build(); 105 private static final long TIMEOUT_MILLIS = 1000; 106 107 @Mock private CallsManager mMockCallsManager; 108 @Mock private CallerInfoLookupHelper mMockCallerInfoLookupHelper; 109 @Mock private PhoneAccountRegistrar mMockPhoneAccountRegistrar; 110 @Mock private ClockProxy mMockClockProxy; 111 @Mock private ToastFactory mMockToastProxy; 112 @Mock private PhoneNumberUtilsAdapter mMockPhoneNumberUtilsAdapter; 113 @Mock private ConnectionServiceWrapper mMockConnectionService; 114 @Mock private TransactionalServiceWrapper mMockTransactionalService; 115 116 private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; 117 118 @Before setUp()119 public void setUp() throws Exception { 120 super.setUp(); 121 doReturn(mMockCallerInfoLookupHelper).when(mMockCallsManager).getCallerInfoLookupHelper(); 122 doReturn(mMockPhoneAccountRegistrar).when(mMockCallsManager).getPhoneAccountRegistrar(); 123 doReturn(0L).when(mMockClockProxy).elapsedRealtime(); 124 doReturn(SIM_1_ACCOUNT).when(mMockPhoneAccountRegistrar).getPhoneAccountUnchecked( 125 eq(SIM_1_HANDLE)); 126 doReturn(new ComponentName(mContext, CallTest.class)) 127 .when(mMockConnectionService).getComponentName(); 128 doReturn(UserHandle.CURRENT).when(mMockCallsManager).getCurrentUserHandle(); 129 Resources mockResources = mContext.getResources(); 130 when(mockResources.getBoolean(R.bool.skip_loading_canned_text_response)) 131 .thenReturn(false); 132 when(mockResources.getString(R.string.skip_incoming_caller_info_account_package)) 133 .thenReturn(""); 134 EmergencyCallHelper helper = mock(EmergencyCallHelper.class); 135 doReturn(helper).when(mMockCallsManager).getEmergencyCallHelper(); 136 } 137 138 @After tearDown()139 public void tearDown() throws Exception { 140 super.tearDown(); 141 } 142 143 @Test 144 @SmallTest testSetHasGoneActive()145 public void testSetHasGoneActive() { 146 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 147 assertFalse(call.hasGoneActiveBefore()); 148 call.setState(CallState.ACTIVE, ""); 149 assertTrue(call.hasGoneActiveBefore()); 150 call.setState(CallState.AUDIO_PROCESSING, ""); 151 assertTrue(call.hasGoneActiveBefore()); 152 } 153 154 /** 155 * Verify that transactional calls remap the [CallAttributes#CallCapability]s to 156 * Connection capabilities. 157 */ 158 @Test 159 @SmallTest testTransactionalCallCapabilityRemapping()160 public void testTransactionalCallCapabilityRemapping() { 161 // ensure when the flag is disabled, the old behavior is unchanged 162 Bundle disabledFlagExtras = new Bundle(); 163 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 164 disabledFlagExtras.putInt(CallAttributes.CALL_CAPABILITIES_KEY, 165 Connection.CAPABILITY_MERGE_CONFERENCE); 166 when(mFeatureFlags.remapTransactionalCapabilities()).thenReturn(false); 167 call.setTransactionalCapabilities(disabledFlagExtras); 168 assertTrue(call.can(Connection.CAPABILITY_MERGE_CONFERENCE)); 169 // enable the bug fix flag and ensure the transactional capabilities are remapped 170 Bundle enabledFlagExtras = new Bundle(); 171 Call call2 = createCall("2", Call.CALL_DIRECTION_INCOMING); 172 enabledFlagExtras.putInt(CallAttributes.CALL_CAPABILITIES_KEY, 173 CallAttributes.SUPPORTS_SET_INACTIVE); 174 when(mFeatureFlags.remapTransactionalCapabilities()).thenReturn(true); 175 call2.setTransactionalCapabilities(enabledFlagExtras); 176 assertTrue(call2.can(Connection.CAPABILITY_HOLD)); 177 assertTrue(call2.can(Connection.CAPABILITY_SUPPORT_HOLD)); 178 } 179 180 /** 181 * Verify Call#setVideoState will only upgrade to video if the PhoneAccount supports video 182 * state capabilities 183 */ 184 @Test 185 @SmallTest testSetVideoStateForTransactionalCalls()186 public void testSetVideoStateForTransactionalCalls() { 187 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 188 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 189 call.setIsTransactionalCall(true); 190 call.setTransactionServiceWrapper(tsw); 191 assertTrue(call.isTransactionalCall()); 192 assertNotNull(call.getTransactionServiceWrapper()); 193 when(mFeatureFlags.transactionalVideoState()).thenReturn(true); 194 195 // VoIP apps using transactional APIs must register a PhoneAccount that supports 196 // video calling capabilities or the video state will be defaulted to audio 197 assertFalse(call.isVideoCallingSupportedByPhoneAccount()); 198 call.setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 199 assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState()); 200 201 call.setVideoCallingSupportedByPhoneAccount(true); 202 assertTrue(call.isVideoCallingSupportedByPhoneAccount()); 203 204 // After the PhoneAccount signals it supports video calling, video state changes can occur 205 call.setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 206 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 207 verify(tsw, times(1)).onVideoStateChanged(call, CallAttributes.VIDEO_CALL); 208 } 209 210 /** 211 * Verify all video state changes are echoed out to the TransactionalServiceWrapper 212 */ 213 @Test 214 @SmallTest testToggleTransactionalVideoState()215 public void testToggleTransactionalVideoState() { 216 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 217 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 218 call.setIsTransactionalCall(true); 219 call.setTransactionServiceWrapper(tsw); 220 call.setVideoCallingSupportedByPhoneAccount(true); 221 assertTrue(call.isTransactionalCall()); 222 assertNotNull(call.getTransactionServiceWrapper()); 223 assertTrue(call.isVideoCallingSupportedByPhoneAccount()); 224 when(mFeatureFlags.transactionalVideoState()).thenReturn(true); 225 226 call.setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 227 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 228 verify(tsw, times(1)).onVideoStateChanged(call, CallAttributes.VIDEO_CALL); 229 230 call.setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 231 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 232 verify(tsw, times(2)).onVideoStateChanged(call, CallAttributes.VIDEO_CALL); 233 234 call.setVideoState(VideoProfile.STATE_AUDIO_ONLY); 235 assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState()); 236 verify(tsw, times(1)).onVideoStateChanged(call, CallAttributes.AUDIO_CALL); 237 238 call.setVideoState(VideoProfile.STATE_BIDIRECTIONAL); 239 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState()); 240 verify(tsw, times(3)).onVideoStateChanged(call, CallAttributes.VIDEO_CALL); 241 } 242 243 @Test testMultipleCachedCallEvents()244 public void testMultipleCachedCallEvents() { 245 when(mFeatureFlags.cacheCallAudioCallbacks()).thenReturn(true); 246 when(mFeatureFlags.cacheCallEvents()).thenReturn(true); 247 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 248 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 249 250 assertNull(call.getTransactionServiceWrapper()); 251 252 String testEvent1 = "test1"; 253 Bundle testBundle1 = new Bundle(); 254 testBundle1.putInt("testKey", 1); 255 call.sendCallEvent(testEvent1, testBundle1); 256 assertEquals(1, 257 call.getCachedServiceCallbacksCopy().get(CachedCallEventQueue.ID).size()); 258 259 String testEvent2 = "test2"; 260 Bundle testBundle2 = new Bundle(); 261 testBundle2.putInt("testKey", 2); 262 call.sendCallEvent(testEvent2, testBundle2); 263 assertEquals(2, 264 call.getCachedServiceCallbacksCopy().get(CachedCallEventQueue.ID).size()); 265 266 String testEvent3 = "test3"; 267 Bundle testBundle3 = new Bundle(); 268 testBundle2.putInt("testKey", 3); 269 call.sendCallEvent(testEvent3, testBundle3); 270 assertEquals(3, 271 call.getCachedServiceCallbacksCopy().get(CachedCallEventQueue.ID).size()); 272 273 verify(tsw, times(0)).sendCallEvent(any(), any(), any()); 274 call.setTransactionServiceWrapper(tsw); 275 verify(tsw, times(1)).sendCallEvent(any(), eq(testEvent1), eq(testBundle1)); 276 verify(tsw, times(1)).sendCallEvent(any(), eq(testEvent2), eq(testBundle2)); 277 verify(tsw, times(1)).sendCallEvent(any(), eq(testEvent3), eq(testBundle3)); 278 assertEquals(0, call.getCachedServiceCallbacksCopy().size()); 279 } 280 281 @Test testMultipleCachedMuteStateChanges()282 public void testMultipleCachedMuteStateChanges() { 283 when(mFeatureFlags.cacheCallAudioCallbacks()).thenReturn(true); 284 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 285 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 286 287 assertNull(call.getTransactionServiceWrapper()); 288 289 call.cacheServiceCallback(new CachedMuteStateChange(true)); 290 assertEquals(1, 291 call.getCachedServiceCallbacksCopy().get(CachedMuteStateChange.ID).size()); 292 293 call.cacheServiceCallback(new CachedMuteStateChange(false)); 294 assertEquals(1, 295 call.getCachedServiceCallbacksCopy().get(CachedMuteStateChange.ID).size()); 296 297 CachedMuteStateChange currentCacheMuteState = (CachedMuteStateChange) call 298 .getCachedServiceCallbacksCopy() 299 .get(CachedMuteStateChange.ID) 300 .getLast(); 301 302 assertFalse(currentCacheMuteState.isMuted()); 303 304 call.setTransactionServiceWrapper(tsw); 305 verify(tsw, times(1)).onMuteStateChanged(any(), eq(false)); 306 assertEquals(0, call.getCachedServiceCallbacksCopy().size()); 307 } 308 309 @Test testCacheAfterServiceSet()310 public void testCacheAfterServiceSet() { 311 when(mFeatureFlags.cacheCallAudioCallbacks()).thenReturn(true); 312 when(mFeatureFlags.cacheCallEvents()).thenReturn(true); 313 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 314 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 315 316 assertNull(call.getTransactionServiceWrapper()); 317 call.setTransactionServiceWrapper(tsw); 318 call.cacheServiceCallback(new CachedMuteStateChange(true)); 319 // Ensure that we do not lose events if for some reason a CachedCallback is cached after 320 // the service is set 321 verify(tsw, times(1)).onMuteStateChanged(any(), eq(true)); 322 assertEquals(0, call.getCachedServiceCallbacksCopy().size()); 323 } 324 325 @Test testMultipleCachedCurrentEndpointChanges()326 public void testMultipleCachedCurrentEndpointChanges() { 327 when(mFeatureFlags.cacheCallAudioCallbacks()).thenReturn(true); 328 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 329 CallEndpoint earpiece = Mockito.mock(CallEndpoint.class); 330 CallEndpoint speaker = Mockito.mock(CallEndpoint.class); 331 when(earpiece.getEndpointType()).thenReturn(CallEndpoint.TYPE_EARPIECE); 332 when(speaker.getEndpointType()).thenReturn(CallEndpoint.TYPE_SPEAKER); 333 334 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 335 336 assertNull(call.getTransactionServiceWrapper()); 337 338 call.cacheServiceCallback(new CachedCurrentEndpointChange(earpiece)); 339 assertEquals(1, 340 call.getCachedServiceCallbacksCopy().get(CachedCurrentEndpointChange.ID).size()); 341 342 call.cacheServiceCallback(new CachedCurrentEndpointChange(speaker)); 343 assertEquals(1, 344 call.getCachedServiceCallbacksCopy().get(CachedCurrentEndpointChange.ID).size()); 345 346 CachedCurrentEndpointChange currentEndpointChange = (CachedCurrentEndpointChange) call 347 .getCachedServiceCallbacksCopy() 348 .get(CachedCurrentEndpointChange.ID) 349 .getLast(); 350 351 assertEquals(CallEndpoint.TYPE_SPEAKER, 352 currentEndpointChange.getCurrentCallEndpoint().getEndpointType()); 353 354 call.setTransactionServiceWrapper(tsw); 355 verify(tsw, times(1)).onCallEndpointChanged(any(), any()); 356 assertEquals(0, call.getCachedServiceCallbacksCopy().size()); 357 } 358 359 @Test testMultipleCachedAvailableEndpointChanges()360 public void testMultipleCachedAvailableEndpointChanges() { 361 when(mFeatureFlags.cacheCallAudioCallbacks()).thenReturn(true); 362 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 363 CallEndpoint earpiece = Mockito.mock(CallEndpoint.class); 364 CallEndpoint bluetooth = Mockito.mock(CallEndpoint.class); 365 Set<CallEndpoint> initialSet = Set.of(earpiece); 366 Set<CallEndpoint> finalSet = Set.of(earpiece, bluetooth); 367 when(earpiece.getEndpointType()).thenReturn(CallEndpoint.TYPE_EARPIECE); 368 when(bluetooth.getEndpointType()).thenReturn(CallEndpoint.TYPE_BLUETOOTH); 369 370 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 371 372 assertNull(call.getTransactionServiceWrapper()); 373 374 call.cacheServiceCallback(new CachedAvailableEndpointsChange(initialSet)); 375 assertEquals(1, 376 call.getCachedServiceCallbacksCopy().get(CachedAvailableEndpointsChange.ID).size()); 377 378 call.cacheServiceCallback(new CachedAvailableEndpointsChange(finalSet)); 379 assertEquals(1, 380 call.getCachedServiceCallbacksCopy().get(CachedAvailableEndpointsChange.ID).size()); 381 382 CachedAvailableEndpointsChange availableEndpoints = (CachedAvailableEndpointsChange) call 383 .getCachedServiceCallbacksCopy() 384 .get(CachedAvailableEndpointsChange.ID) 385 .getLast(); 386 387 assertEquals(2, availableEndpoints.getAvailableEndpoints().size()); 388 389 call.setTransactionServiceWrapper(tsw); 390 verify(tsw, times(1)).onAvailableCallEndpointsChanged(any(), any()); 391 assertEquals(0, call.getCachedServiceCallbacksCopy().size()); 392 } 393 394 /** 395 * verify that if multiple types of cached callbacks are added to the call, the call executes 396 * all the callbacks once the service is set. 397 */ 398 @Test testAllCachedCallbacks()399 public void testAllCachedCallbacks() { 400 when(mFeatureFlags.cacheCallAudioCallbacks()).thenReturn(true); 401 when(mFeatureFlags.cacheCallEvents()).thenReturn(true); 402 TransactionalServiceWrapper tsw = Mockito.mock(TransactionalServiceWrapper.class); 403 CallEndpoint earpiece = Mockito.mock(CallEndpoint.class); 404 CallEndpoint bluetooth = Mockito.mock(CallEndpoint.class); 405 Set<CallEndpoint> availableEndpointsSet = Set.of(earpiece, bluetooth); 406 when(earpiece.getEndpointType()).thenReturn(CallEndpoint.TYPE_EARPIECE); 407 when(bluetooth.getEndpointType()).thenReturn(CallEndpoint.TYPE_BLUETOOTH); 408 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 409 410 // The call should have a null service so that callbacks are cached 411 assertNull(call.getTransactionServiceWrapper()); 412 413 // add cached callbacks 414 call.cacheServiceCallback(new CachedMuteStateChange(false)); 415 assertEquals(1, call.getCachedServiceCallbacksCopy().size()); 416 call.cacheServiceCallback(new CachedCurrentEndpointChange(earpiece)); 417 assertEquals(2, call.getCachedServiceCallbacksCopy().size()); 418 call.cacheServiceCallback(new CachedAvailableEndpointsChange(availableEndpointsSet)); 419 assertEquals(3, call.getCachedServiceCallbacksCopy().size()); 420 String testEvent = "testEvent"; 421 Bundle testBundle = new Bundle(); 422 call.sendCallEvent("testEvent", testBundle); 423 424 // verify the cached callbacks are stored properly within the cache map and the values 425 // can be evaluated 426 CachedMuteStateChange currentCacheMuteState = (CachedMuteStateChange) call 427 .getCachedServiceCallbacksCopy() 428 .get(CachedMuteStateChange.ID) 429 .getLast(); 430 CachedCurrentEndpointChange currentEndpointChange = (CachedCurrentEndpointChange) call 431 .getCachedServiceCallbacksCopy() 432 .get(CachedCurrentEndpointChange.ID) 433 .getLast(); 434 CachedAvailableEndpointsChange availableEndpoints = (CachedAvailableEndpointsChange) call 435 .getCachedServiceCallbacksCopy() 436 .get(CachedAvailableEndpointsChange.ID) 437 .getLast(); 438 assertFalse(currentCacheMuteState.isMuted()); 439 assertEquals(CallEndpoint.TYPE_EARPIECE, 440 currentEndpointChange.getCurrentCallEndpoint().getEndpointType()); 441 assertEquals(2, availableEndpoints.getAvailableEndpoints().size()); 442 443 // set the service to a non-null value 444 call.setTransactionServiceWrapper(tsw); 445 446 // ensure the cached callbacks were executed 447 verify(tsw, times(1)).onMuteStateChanged(any(), anyBoolean()); 448 verify(tsw, times(1)).onCallEndpointChanged(any(), any()); 449 verify(tsw, times(1)).onAvailableCallEndpointsChanged(any(), any()); 450 verify(tsw, times(1)).sendCallEvent(any(), eq(testEvent), eq(testBundle)); 451 452 // the cache map should be cleared 453 assertEquals(0, call.getCachedServiceCallbacksCopy().size()); 454 } 455 456 /** 457 * Basic tests to check which call states are considered transitory. 458 */ 459 @Test 460 @SmallTest testIsCallStateTransitory()461 public void testIsCallStateTransitory() { 462 assertTrue(CallState.isTransitoryState(CallState.NEW)); 463 assertTrue(CallState.isTransitoryState(CallState.CONNECTING)); 464 assertTrue(CallState.isTransitoryState(CallState.DISCONNECTING)); 465 assertTrue(CallState.isTransitoryState(CallState.ANSWERED)); 466 467 assertFalse(CallState.isTransitoryState(CallState.SELECT_PHONE_ACCOUNT)); 468 assertFalse(CallState.isTransitoryState(CallState.DIALING)); 469 assertFalse(CallState.isTransitoryState(CallState.RINGING)); 470 assertFalse(CallState.isTransitoryState(CallState.ACTIVE)); 471 assertFalse(CallState.isTransitoryState(CallState.ON_HOLD)); 472 assertFalse(CallState.isTransitoryState(CallState.DISCONNECTED)); 473 assertFalse(CallState.isTransitoryState(CallState.ABORTED)); 474 assertFalse(CallState.isTransitoryState(CallState.PULLING)); 475 assertFalse(CallState.isTransitoryState(CallState.AUDIO_PROCESSING)); 476 assertFalse(CallState.isTransitoryState(CallState.SIMULATED_RINGING)); 477 } 478 479 /** 480 * Basic tests to check which call states are considered intermediate. 481 */ 482 @Test 483 @SmallTest testIsCallStateIntermediate()484 public void testIsCallStateIntermediate() { 485 assertTrue(CallState.isIntermediateState(CallState.DIALING)); 486 assertTrue(CallState.isIntermediateState(CallState.RINGING)); 487 488 assertFalse(CallState.isIntermediateState(CallState.NEW)); 489 assertFalse(CallState.isIntermediateState(CallState.CONNECTING)); 490 assertFalse(CallState.isIntermediateState(CallState.DISCONNECTING)); 491 assertFalse(CallState.isIntermediateState(CallState.ANSWERED)); 492 assertFalse(CallState.isIntermediateState(CallState.SELECT_PHONE_ACCOUNT)); 493 assertFalse(CallState.isIntermediateState(CallState.ACTIVE)); 494 assertFalse(CallState.isIntermediateState(CallState.ON_HOLD)); 495 assertFalse(CallState.isIntermediateState(CallState.DISCONNECTED)); 496 assertFalse(CallState.isIntermediateState(CallState.ABORTED)); 497 assertFalse(CallState.isIntermediateState(CallState.PULLING)); 498 assertFalse(CallState.isIntermediateState(CallState.AUDIO_PROCESSING)); 499 assertFalse(CallState.isIntermediateState(CallState.SIMULATED_RINGING)); 500 } 501 502 @SmallTest 503 @Test testIsCreateConnectionComplete()504 public void testIsCreateConnectionComplete() { 505 // A new call with basic info. 506 Call call = new Call( 507 "1", /* callId */ 508 mContext, 509 mMockCallsManager, 510 mLock, 511 null /* ConnectionServiceRepository */, 512 mMockPhoneNumberUtilsAdapter, 513 TEST_ADDRESS, 514 null /* GatewayInfo */, 515 null /* connectionManagerPhoneAccountHandle */, 516 SIM_1_HANDLE, 517 Call.CALL_DIRECTION_INCOMING, 518 false /* shouldAttachToExistingConnection*/, 519 false /* isConference */, 520 mMockClockProxy, 521 mMockToastProxy, 522 mFeatureFlags); 523 524 // To start with connection creation isn't complete. 525 assertFalse(call.isCreateConnectionComplete()); 526 527 // Need the bare minimum to get connection creation to complete. 528 ParcelableConnection connection = new ParcelableConnection(null, 0, 0, 0, 0, null, 0, null, 529 0, null, 0, false, false, 0L, 0L, null, null, Collections.emptyList(), null, null, 530 0, 0); 531 call.handleCreateConnectionSuccess(Mockito.mock(CallIdMapper.class), connection); 532 assertTrue(call.isCreateConnectionComplete()); 533 } 534 535 @Test 536 @SmallTest testDisconnectCauseWhenAudioProcessing()537 public void testDisconnectCauseWhenAudioProcessing() { 538 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 539 call.setState(CallState.AUDIO_PROCESSING, ""); 540 call.disconnect(); 541 call.setDisconnectCause(new DisconnectCause(DisconnectCause.LOCAL)); 542 assertEquals(DisconnectCause.REJECTED, call.getDisconnectCause().getCode()); 543 } 544 545 @Test 546 @SmallTest testDisconnectCauseWhenAudioProcessingAfterActive()547 public void testDisconnectCauseWhenAudioProcessingAfterActive() { 548 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 549 call.setState(CallState.AUDIO_PROCESSING, ""); 550 call.setState(CallState.ACTIVE, ""); 551 call.setState(CallState.AUDIO_PROCESSING, ""); 552 call.disconnect(); 553 call.setDisconnectCause(new DisconnectCause(DisconnectCause.LOCAL)); 554 assertEquals(DisconnectCause.LOCAL, call.getDisconnectCause().getCode()); 555 } 556 557 @Test 558 @SmallTest testDisconnectCauseWhenSimulatedRingingAndDisconnect()559 public void testDisconnectCauseWhenSimulatedRingingAndDisconnect() { 560 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 561 call.setState(CallState.SIMULATED_RINGING, ""); 562 call.disconnect(); 563 call.setDisconnectCause(new DisconnectCause(DisconnectCause.LOCAL)); 564 assertEquals(DisconnectCause.MISSED, call.getDisconnectCause().getCode()); 565 } 566 567 @Test 568 @SmallTest testDisconnectCauseWhenSimulatedRingingAndReject()569 public void testDisconnectCauseWhenSimulatedRingingAndReject() { 570 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 571 call.setState(CallState.SIMULATED_RINGING, ""); 572 call.reject(false, ""); 573 call.setDisconnectCause(new DisconnectCause(DisconnectCause.LOCAL)); 574 assertEquals(DisconnectCause.REJECTED, call.getDisconnectCause().getCode()); 575 } 576 577 @Test 578 @SmallTest testCanPullCallRemovedDuringEmergencyCall()579 public void testCanPullCallRemovedDuringEmergencyCall() { 580 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 581 boolean[] hasCalledConnectionCapabilitiesChanged = new boolean[1]; 582 call.addListener(new Call.ListenerBase() { 583 @Override 584 public void onConnectionCapabilitiesChanged(Call call) { 585 hasCalledConnectionCapabilitiesChanged[0] = true; 586 } 587 }); 588 call.setConnectionService(mMockConnectionService); 589 call.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL); 590 call.setConnectionCapabilities(Connection.CAPABILITY_CAN_PULL_CALL); 591 call.setState(CallState.ACTIVE, ""); 592 assertTrue(hasCalledConnectionCapabilitiesChanged[0]); 593 // Capability should be present 594 assertTrue((call.getConnectionCapabilities() | Connection.CAPABILITY_CAN_PULL_CALL) > 0); 595 hasCalledConnectionCapabilitiesChanged[0] = false; 596 // Emergency call in progress 597 call.setIsPullExternalCallSupported(false /*isPullCallSupported*/); 598 assertTrue(hasCalledConnectionCapabilitiesChanged[0]); 599 // Capability should not be present 600 assertEquals(0, call.getConnectionCapabilities() & Connection.CAPABILITY_CAN_PULL_CALL); 601 hasCalledConnectionCapabilitiesChanged[0] = false; 602 // Emergency call complete 603 call.setIsPullExternalCallSupported(true /*isPullCallSupported*/); 604 assertTrue(hasCalledConnectionCapabilitiesChanged[0]); 605 // Capability should be present 606 assertEquals(Connection.CAPABILITY_CAN_PULL_CALL, 607 call.getConnectionCapabilities() & Connection.CAPABILITY_CAN_PULL_CALL); 608 } 609 610 @Test 611 @SmallTest testCanNotPullCallDuringEmergencyCall()612 public void testCanNotPullCallDuringEmergencyCall() { 613 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 614 call.setConnectionService(mMockConnectionService); 615 call.setConnectionProperties(Connection.PROPERTY_IS_EXTERNAL_CALL); 616 call.setConnectionCapabilities(Connection.CAPABILITY_CAN_PULL_CALL); 617 call.setState(CallState.ACTIVE, ""); 618 // Emergency call in progress, this should show a toast and never call pullExternalCall 619 // on the ConnectionService. 620 doReturn(true).when(mMockCallsManager).isInEmergencyCall(); 621 call.pullExternalCall(); 622 verify(mMockConnectionService, never()).pullExternalCall(any()); 623 } 624 625 @Test 626 @SmallTest testCallDirection()627 public void testCallDirection() { 628 Call call = createCall("1"); 629 boolean[] hasCallDirectionChanged = new boolean[1]; 630 call.addListener(new Call.ListenerBase() { 631 @Override 632 public void onCallDirectionChanged(Call call) { 633 hasCallDirectionChanged[0] = true; 634 } 635 }); 636 assertFalse(call.isIncoming()); 637 call.setCallDirection(Call.CALL_DIRECTION_INCOMING); 638 assertTrue(hasCallDirectionChanged[0]); 639 assertTrue(call.isIncoming()); 640 } 641 642 @Test testIsSuppressedByDoNotDisturbExtra()643 public void testIsSuppressedByDoNotDisturbExtra() { 644 Call call = new Call( 645 "1", /* callId */ 646 mContext, 647 mMockCallsManager, 648 mLock, 649 null /* ConnectionServiceRepository */, 650 mMockPhoneNumberUtilsAdapter, 651 TEST_ADDRESS, 652 null /* GatewayInfo */, 653 null /* connectionManagerPhoneAccountHandle */, 654 SIM_1_HANDLE, 655 Call.CALL_DIRECTION_UNDEFINED, 656 false /* shouldAttachToExistingConnection*/, 657 true /* isConference */, 658 mMockClockProxy, 659 mMockToastProxy, 660 mFeatureFlags); 661 662 assertFalse(call.wasDndCheckComputedForCall()); 663 assertFalse(call.isCallSuppressedByDoNotDisturb()); 664 call.setCallIsSuppressedByDoNotDisturb(true); 665 assertTrue(call.wasDndCheckComputedForCall()); 666 assertTrue(call.isCallSuppressedByDoNotDisturb()); 667 } 668 669 @Test testGetConnectionServiceWrapper()670 public void testGetConnectionServiceWrapper() { 671 Call call = new Call( 672 "1", /* callId */ 673 mContext, 674 mMockCallsManager, 675 mLock, 676 null /* ConnectionServiceRepository */, 677 mMockPhoneNumberUtilsAdapter, 678 TEST_ADDRESS, 679 null /* GatewayInfo */, 680 null /* connectionManagerPhoneAccountHandle */, 681 SIM_1_HANDLE, 682 Call.CALL_DIRECTION_UNDEFINED, 683 false /* shouldAttachToExistingConnection*/, 684 true /* isConference */, 685 mMockClockProxy, 686 mMockToastProxy, 687 mFeatureFlags); 688 689 assertNull(call.getConnectionServiceWrapper()); 690 assertFalse(call.isTransactionalCall()); 691 call.setConnectionService(mMockConnectionService); 692 assertEquals(mMockConnectionService, call.getConnectionServiceWrapper()); 693 call.setIsTransactionalCall(true); 694 assertTrue(call.isTransactionalCall()); 695 assertNull(call.getConnectionServiceWrapper()); 696 call.setTransactionServiceWrapper(mMockTransactionalService); 697 assertEquals(mMockTransactionalService, call.getTransactionServiceWrapper()); 698 } 699 700 @Test testCallEventCallbacksWereCalled()701 public void testCallEventCallbacksWereCalled() { 702 Call call = new Call( 703 "1", /* callId */ 704 mContext, 705 mMockCallsManager, 706 mLock, 707 null /* ConnectionServiceRepository */, 708 mMockPhoneNumberUtilsAdapter, 709 TEST_ADDRESS, 710 null /* GatewayInfo */, 711 null /* connectionManagerPhoneAccountHandle */, 712 SIM_1_HANDLE, 713 Call.CALL_DIRECTION_UNDEFINED, 714 false /* shouldAttachToExistingConnection*/, 715 true /* isConference */, 716 mMockClockProxy, 717 mMockToastProxy, 718 mFeatureFlags); 719 720 // setup 721 call.setIsTransactionalCall(true); 722 assertTrue(call.isTransactionalCall()); 723 assertNull(call.getConnectionServiceWrapper()); 724 call.setTransactionServiceWrapper(mMockTransactionalService); 725 assertEquals(mMockTransactionalService, call.getTransactionServiceWrapper()); 726 727 // assert CallEventCallback#onSetInactive is called 728 call.setState(CallState.ACTIVE, "test"); 729 call.hold(); 730 verify(mMockTransactionalService, times(1)).onSetInactive(call); 731 732 // assert CallEventCallback#onSetActive is called 733 call.setState(CallState.ON_HOLD, "test"); 734 call.unhold(); 735 verify(mMockTransactionalService, times(1)).onSetActive(call); 736 737 // assert CallEventCallback#onAnswer is called 738 call.setState(CallState.RINGING, "test"); 739 call.answer(0); 740 verify(mMockTransactionalService, times(1)).onAnswer(call, 0); 741 742 // assert CallEventCallback#onDisconnect is called 743 call.setState(CallState.ACTIVE, "test"); 744 call.disconnect(); 745 verify(mMockTransactionalService, times(1)).onDisconnect(call, 746 call.getDisconnectCause()); 747 } 748 749 @Test 750 @SmallTest testSetConnectionPropertiesRttOnOff()751 public void testSetConnectionPropertiesRttOnOff() { 752 Call call = createCall("1"); 753 call.setConnectionService(mMockConnectionService); 754 755 call.setConnectionProperties(Connection.PROPERTY_IS_RTT); 756 verify(mMockCallsManager).playRttUpgradeToneForCall(any()); 757 assertNotNull(null, call.getInCallToCsRttPipeForCs()); 758 assertNotNull(null, call.getCsToInCallRttPipeForInCall()); 759 760 call.setConnectionProperties(0); 761 assertNull(null, call.getInCallToCsRttPipeForCs()); 762 assertNull(null, call.getCsToInCallRttPipeForInCall()); 763 } 764 765 @Test 766 @SmallTest testGetFromCallerInfo()767 public void testGetFromCallerInfo() { 768 Call call = createCall("1"); 769 770 CallerInfo info = new CallerInfo(); 771 info.setName("name"); 772 info.setPhoneNumber("number"); 773 info.cachedPhoto = new ColorDrawable(); 774 info.cachedPhotoIcon = Bitmap.createBitmap(24, 24, Bitmap.Config.ALPHA_8); 775 776 ArgumentCaptor<CallerInfoLookupHelper.OnQueryCompleteListener> listenerCaptor = 777 ArgumentCaptor.forClass(CallerInfoLookupHelper.OnQueryCompleteListener.class); 778 verify(mMockCallerInfoLookupHelper).startLookup(any(), listenerCaptor.capture()); 779 listenerCaptor.getValue().onCallerInfoQueryComplete(call.getHandle(), info); 780 781 assertEquals(info, call.getCallerInfo()); 782 assertEquals(info.getName(), call.getName()); 783 assertEquals(info.getPhoneNumber(), call.getPhoneNumber()); 784 assertEquals(info.cachedPhoto, call.getPhoto()); 785 assertEquals(info.cachedPhotoIcon, call.getPhotoIcon()); 786 assertEquals(call.getHandle(), call.getContactUri()); 787 } 788 789 @Test 790 @SmallTest testGetFromCallerInfo_skipLookup()791 public void testGetFromCallerInfo_skipLookup() { 792 Resources mockResources = mContext.getResources(); 793 when(mockResources.getString(R.string.skip_incoming_caller_info_account_package)) 794 .thenReturn("com.foo"); 795 796 createCall("1"); 797 798 verify(mMockCallerInfoLookupHelper, never()).startLookup(any(), any()); 799 } 800 801 @Test 802 @SmallTest testOriginalCallIntent()803 public void testOriginalCallIntent() { 804 Call call = createCall("1"); 805 806 Intent i = new Intent(); 807 call.setOriginalCallIntent(i); 808 809 assertEquals(i, call.getOriginalCallIntent()); 810 } 811 812 @Test 813 @SmallTest testHandleCreateConferenceSuccessNotifiesListeners()814 public void testHandleCreateConferenceSuccessNotifiesListeners() { 815 Call.Listener listener = mock(Call.Listener.class); 816 817 Call incomingCall = createCall("1", Call.CALL_DIRECTION_INCOMING); 818 incomingCall.setConnectionService(mMockConnectionService); 819 incomingCall.addListener(listener); 820 Call outgoingCall = createCall("2", Call.CALL_DIRECTION_OUTGOING); 821 outgoingCall.setConnectionService(mMockConnectionService); 822 outgoingCall.addListener(listener); 823 824 StatusHints statusHints = mock(StatusHints.class); 825 Bundle extra = new Bundle(); 826 ParcelableConference conference = 827 new ParcelableConference.Builder(SIM_1_HANDLE, Connection.STATE_NEW) 828 .setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED) 829 .setConnectionCapabilities(123) 830 .setVideoAttributes(null, VideoProfile.STATE_AUDIO_ONLY) 831 .setRingbackRequested(true) 832 .setStatusHints(statusHints) 833 .setExtras(extra) 834 .build(); 835 836 incomingCall.handleCreateConferenceSuccess(null, conference); 837 verify(listener).onSuccessfulIncomingCall(incomingCall); 838 839 outgoingCall.handleCreateConferenceSuccess(null, conference); 840 verify(listener).onSuccessfulOutgoingCall(outgoingCall, CallState.NEW); 841 } 842 843 @Test 844 @SmallTest testHandleCreateConferenceSuccess()845 public void testHandleCreateConferenceSuccess() { 846 Call call = createCall("1", Call.CALL_DIRECTION_INCOMING); 847 call.setConnectionService(mMockConnectionService); 848 849 StatusHints statusHints = mock(StatusHints.class); 850 Bundle extra = new Bundle(); 851 ParcelableConference conference = 852 new ParcelableConference.Builder(SIM_1_HANDLE, Connection.STATE_NEW) 853 .setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED) 854 .setConnectionCapabilities(123) 855 .setVideoAttributes(null, VideoProfile.STATE_AUDIO_ONLY) 856 .setRingbackRequested(true) 857 .setStatusHints(statusHints) 858 .setExtras(extra) 859 .build(); 860 861 call.handleCreateConferenceSuccess(null, conference); 862 863 assertEquals(SIM_1_HANDLE, call.getTargetPhoneAccount()); 864 assertEquals(TEST_ADDRESS, call.getHandle()); 865 assertEquals(123, call.getConnectionCapabilities()); 866 assertNull(call.getVideoProviderProxy()); 867 assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState()); 868 assertTrue(call.isRingbackRequested()); 869 assertEquals(statusHints, call.getStatusHints()); 870 } 871 872 @Test 873 @SmallTest testHandleCreateConferenceFailure()874 public void testHandleCreateConferenceFailure() { 875 Call.Listener listener = mock(Call.Listener.class); 876 877 Call incomingCall = createCall("1", Call.CALL_DIRECTION_INCOMING); 878 incomingCall.setConnectionService(mMockConnectionService); 879 incomingCall.addListener(listener); 880 Call outgoingCall = createCall("2", Call.CALL_DIRECTION_OUTGOING); 881 outgoingCall.setConnectionService(mMockConnectionService); 882 outgoingCall.addListener(listener); 883 884 final DisconnectCause cause = new DisconnectCause(DisconnectCause.REJECTED); 885 886 incomingCall.handleCreateConferenceFailure(cause); 887 assertEquals(cause, incomingCall.getDisconnectCause()); 888 verify(listener).onFailedIncomingCall(incomingCall); 889 890 outgoingCall.handleCreateConferenceFailure(cause); 891 assertEquals(cause, outgoingCall.getDisconnectCause()); 892 verify(listener).onFailedOutgoingCall(outgoingCall, cause); 893 } 894 895 @Test 896 @SmallTest testWasConferencePreviouslyMerged()897 public void testWasConferencePreviouslyMerged() { 898 Call call = createCall("1"); 899 call.setConnectionService(mMockConnectionService); 900 call.setConnectionCapabilities(Connection.CAPABILITY_MERGE_CONFERENCE); 901 902 assertFalse(call.wasConferencePreviouslyMerged()); 903 904 call.mergeConference(); 905 906 assertTrue(call.wasConferencePreviouslyMerged()); 907 } 908 909 @Test 910 @SmallTest testSwapConference()911 public void testSwapConference() { 912 Call.Listener listener = mock(Call.Listener.class); 913 914 Call call = createCall("1"); 915 call.setConnectionService(mMockConnectionService); 916 call.setConnectionCapabilities(Connection.CAPABILITY_SWAP_CONFERENCE); 917 call.addListener(listener); 918 919 call.swapConference(); 920 assertNull(call.getConferenceLevelActiveCall()); 921 922 Call childCall1 = createCall("child1"); 923 childCall1.setChildOf(call); 924 call.swapConference(); 925 assertEquals(childCall1, call.getConferenceLevelActiveCall()); 926 927 Call childCall2 = createCall("child2"); 928 childCall2.setChildOf(call); 929 call.swapConference(); 930 assertEquals(childCall1, call.getConferenceLevelActiveCall()); 931 call.swapConference(); 932 assertEquals(childCall2, call.getConferenceLevelActiveCall()); 933 934 verify(listener, times(4)).onCdmaConferenceSwap(call); 935 } 936 937 @Test 938 @SmallTest testHandleCreateConnectionFailure()939 public void testHandleCreateConnectionFailure() { 940 Call.Listener listener = mock(Call.Listener.class); 941 942 Call incomingCall = createCall("1", Call.CALL_DIRECTION_INCOMING); 943 incomingCall.setConnectionService(mMockConnectionService); 944 incomingCall.addListener(listener); 945 Call outgoingCall = createCall("2", Call.CALL_DIRECTION_OUTGOING); 946 outgoingCall.setConnectionService(mMockConnectionService); 947 outgoingCall.addListener(listener); 948 Call unknownCall = createCall("3", Call.CALL_DIRECTION_UNKNOWN); 949 unknownCall.setConnectionService(mMockConnectionService); 950 unknownCall.addListener(listener); 951 952 final DisconnectCause cause = new DisconnectCause(DisconnectCause.REJECTED); 953 954 incomingCall.handleCreateConnectionFailure(cause); 955 assertEquals(cause, incomingCall.getDisconnectCause()); 956 verify(listener).onFailedIncomingCall(incomingCall); 957 958 outgoingCall.handleCreateConnectionFailure(cause); 959 assertEquals(cause, outgoingCall.getDisconnectCause()); 960 verify(listener).onFailedOutgoingCall(outgoingCall, cause); 961 962 unknownCall.handleCreateConnectionFailure(cause); 963 assertEquals(cause, unknownCall.getDisconnectCause()); 964 verify(listener).onFailedUnknownCall(unknownCall); 965 } 966 967 /** 968 * ensure a Call object does not throw an NPE when the CallingPackageIdentity is not set and 969 * the correct values are returned when set 970 */ 971 @Test 972 @SmallTest testCallingPackageIdentity()973 public void testCallingPackageIdentity() { 974 final int packageUid = 123; 975 final int packagePid = 1; 976 977 Call call = createCall("1"); 978 979 // assert default values for a Calls CallingPackageIdentity are -1 unless set via the setter 980 assertEquals(-1, call.getCallingPackageIdentity().mCallingPackageUid); 981 assertEquals(-1, call.getCallingPackageIdentity().mCallingPackagePid); 982 983 // set the Call objects CallingPackageIdentity via the setter and a bundle 984 Bundle extras = new Bundle(); 985 extras.putInt(CallAttributes.CALLER_UID_KEY, packageUid); 986 extras.putInt(CallAttributes.CALLER_PID_KEY, packagePid); 987 // assert that the setter removed the extras 988 assertEquals(packageUid, extras.getInt(CallAttributes.CALLER_UID_KEY)); 989 assertEquals(packagePid, extras.getInt(CallAttributes.CALLER_PID_KEY)); 990 call.setCallingPackageIdentity(extras); 991 // assert that the setter removed the extras 992 assertEquals(0, extras.getInt(CallAttributes.CALLER_UID_KEY)); 993 assertEquals(0, extras.getInt(CallAttributes.CALLER_PID_KEY)); 994 // assert the properties are fetched correctly 995 assertEquals(packageUid, call.getCallingPackageIdentity().mCallingPackageUid); 996 assertEquals(packagePid, call.getCallingPackageIdentity().mCallingPackagePid); 997 } 998 999 @Test 1000 @SmallTest testOnConnectionEventNotifiesListener()1001 public void testOnConnectionEventNotifiesListener() { 1002 when(mFeatureFlags.enableCallSequencing()).thenReturn(true); 1003 Call.Listener listener = mock(Call.Listener.class); 1004 Call call = createCall("1"); 1005 call.addListener(listener); 1006 1007 call.onConnectionEvent(Connection.EVENT_ON_HOLD_TONE_START, null); 1008 verify(listener).onHoldToneRequested(call); 1009 assertTrue(call.isRemotelyHeld()); 1010 1011 call.onConnectionEvent(Connection.EVENT_ON_HOLD_TONE_END, null); 1012 verify(listener, times(2)).onHoldToneRequested(call); 1013 assertFalse(call.isRemotelyHeld()); 1014 1015 call.onConnectionEvent(Connection.EVENT_CALL_HOLD_FAILED, null); 1016 verify(listener).onCallHoldFailed(call); 1017 1018 call.onConnectionEvent(Connection.EVENT_CALL_SWITCH_FAILED, null); 1019 verify(listener).onCallSwitchFailed(call); 1020 1021 call.onConnectionEvent(Connection.EVENT_CALL_RESUME_FAILED, null); 1022 verify(listener).onCallResumeFailed(call); 1023 1024 final int d2dType = 1; 1025 final int d2dValue = 2; 1026 final Bundle d2dExtras = new Bundle(); 1027 d2dExtras.putInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE, d2dType); 1028 d2dExtras.putInt(Connection.EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE, d2dValue); 1029 call.onConnectionEvent(Connection.EVENT_DEVICE_TO_DEVICE_MESSAGE, d2dExtras); 1030 verify(listener).onReceivedDeviceToDeviceMessage(call, d2dType, d2dValue); 1031 1032 final CallQuality quality = new CallQuality(); 1033 final Bundle callQualityExtras = new Bundle(); 1034 callQualityExtras.putParcelable(Connection.EXTRA_CALL_QUALITY_REPORT, quality); 1035 call.onConnectionEvent(Connection.EVENT_CALL_QUALITY_REPORT, callQualityExtras); 1036 verify(listener).onReceivedCallQualityReport(call, quality); 1037 } 1038 1039 @Test 1040 @SmallTest testDiagnosticMessage()1041 public void testDiagnosticMessage() { 1042 Call.Listener listener = mock(Call.Listener.class); 1043 Call call = createCall("1"); 1044 call.addListener(listener); 1045 1046 final int id = 1; 1047 final String message = "msg"; 1048 1049 call.displayDiagnosticMessage(id, message); 1050 verify(listener).onConnectionEvent( 1051 eq(call), 1052 eq(android.telecom.Call.EVENT_DISPLAY_DIAGNOSTIC_MESSAGE), 1053 argThat(extras -> { 1054 return extras.getInt(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE_ID) == id && 1055 extras.getCharSequence(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE) 1056 .toString().equals(message); 1057 })); 1058 1059 call.clearDiagnosticMessage(id); 1060 verify(listener).onConnectionEvent( 1061 eq(call), 1062 eq(android.telecom.Call.EVENT_CLEAR_DIAGNOSTIC_MESSAGE), 1063 argThat(extras -> { 1064 return extras.getInt(android.telecom.Call.EXTRA_DIAGNOSTIC_MESSAGE_ID) == id; 1065 })); 1066 } 1067 1068 @Test 1069 @SmallTest testExcludesInCallServiceFromDoNotLogCallExtra()1070 public void testExcludesInCallServiceFromDoNotLogCallExtra() { 1071 Call call = createCall("any"); 1072 Bundle extra = new Bundle(); 1073 extra.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); 1074 1075 call.putInCallServiceExtras(extra, "packageName"); 1076 1077 assertFalse(call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)); 1078 } 1079 1080 /** 1081 * Verify that a Call can handle a case where no telephony stack is present to detect emergency 1082 * numbers. 1083 */ 1084 @Test 1085 @SmallTest testNoTelephonyEmergencyBehavior()1086 public void testNoTelephonyEmergencyBehavior() { 1087 when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any())) 1088 .thenReturn(true); 1089 Call testCall = createCall("1", Call.CALL_DIRECTION_OUTGOING, Uri.parse("tel:911")); 1090 assertTrue(testCall.isEmergencyCall()); 1091 1092 when(mComponentContextFixture.getTelephonyManager().isEmergencyNumber(any())) 1093 .thenThrow(new UnsupportedOperationException("Bee-boop")); 1094 Call testCall2 = createCall("2", Call.CALL_DIRECTION_OUTGOING, Uri.parse("tel:911")); 1095 assertTrue(!testCall2.isEmergencyCall()); 1096 } 1097 1098 @Test 1099 @SmallTest testExcludesConnectionServiceWithoutModifyStatePermissionFromDoNotLogCallExtra()1100 public void testExcludesConnectionServiceWithoutModifyStatePermissionFromDoNotLogCallExtra() { 1101 PackageManager packageManager = mContext.getPackageManager(); 1102 Bundle extra = new Bundle(); 1103 extra.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); 1104 String packageName = SIM_1_HANDLE.getComponentName().getPackageName(); 1105 doReturn(PackageManager.PERMISSION_DENIED) 1106 .when(packageManager) 1107 .checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, packageName); 1108 Call call = createCall("any"); 1109 1110 call.putConnectionServiceExtras(extra); 1111 1112 assertFalse(call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)); 1113 } 1114 1115 @Test 1116 @SmallTest testDoesNotExcludeConnectionServiceWithModifyStatePermissionFromDoNotLogCallExtra()1117 public void testDoesNotExcludeConnectionServiceWithModifyStatePermissionFromDoNotLogCallExtra() { 1118 String packageName = SIM_1_HANDLE.getComponentName().getPackageName(); 1119 Bundle extra = new Bundle(); 1120 extra.putBoolean(TelecomManager.EXTRA_DO_NOT_LOG_CALL, true); 1121 PackageManager packageManager = mContext.getPackageManager(); 1122 doReturn(PackageManager.PERMISSION_GRANTED) 1123 .when(packageManager) 1124 .checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, packageName); 1125 Call call = createCall("any"); 1126 1127 call.putConnectionServiceExtras(extra); 1128 1129 assertTrue(call.getExtras().containsKey(TelecomManager.EXTRA_DO_NOT_LOG_CALL)); 1130 } 1131 1132 @Test 1133 @SmallTest testSkipLoadingCannedTextResponse()1134 public void testSkipLoadingCannedTextResponse() { 1135 Call call = createCall("any"); 1136 Resources mockResources = mContext.getResources(); 1137 when(mockResources.getBoolean(R.bool.skip_loading_canned_text_response)) 1138 .thenReturn(true); 1139 1140 1141 assertFalse(call.isRespondViaSmsCapable()); 1142 } 1143 createCall(String id)1144 private Call createCall(String id) { 1145 return createCall(id, Call.CALL_DIRECTION_UNDEFINED); 1146 } 1147 createCall(String id, int callDirection)1148 private Call createCall(String id, int callDirection) { 1149 return createCall(id, callDirection, TEST_ADDRESS); 1150 } 1151 createCall(String id, int callDirection, Uri address)1152 private Call createCall(String id, int callDirection, Uri address) { 1153 return new Call( 1154 id, 1155 mContext, 1156 mMockCallsManager, 1157 mLock, 1158 null, 1159 mMockPhoneNumberUtilsAdapter, 1160 address, 1161 null /* GatewayInfo */, 1162 null, 1163 SIM_1_HANDLE, 1164 callDirection, 1165 false, 1166 false, 1167 mMockClockProxy, 1168 mMockToastProxy, 1169 mFeatureFlags); 1170 } 1171 } 1172