BluetoothPhoneServiceTest.java revision a35090657297f5f0f20c2bb31cdf1eb7d6da6419
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.server.telecom.tests; 18 19import android.bluetooth.BluetoothAdapter; 20import android.content.ComponentName; 21import android.content.Intent; 22import android.graphics.drawable.Icon; 23import android.net.Uri; 24import android.os.Binder; 25import android.os.Debug; 26import android.telecom.Connection; 27import android.telecom.GatewayInfo; 28import android.telecom.PhoneAccount; 29import android.telecom.PhoneAccountHandle; 30import android.telecom.TelecomManager; 31import android.telephony.PhoneNumberUtils; 32import android.telephony.TelephonyManager; 33import android.test.suitebuilder.annotation.MediumTest; 34import android.test.suitebuilder.annotation.SmallTest; 35 36import com.android.server.telecom.BluetoothHeadsetProxy; 37import com.android.server.telecom.BluetoothPhoneServiceImpl; 38import com.android.server.telecom.Call; 39import com.android.server.telecom.CallState; 40import com.android.server.telecom.CallsManager; 41import com.android.server.telecom.PhoneAccountRegistrar; 42import com.android.server.telecom.TelecomSystem; 43 44import org.mockito.Mock; 45import org.mockito.MockitoAnnotations; 46 47import java.util.ArrayList; 48import java.util.LinkedList; 49 50import static org.mockito.Matchers.any; 51import static org.mockito.Matchers.anyBoolean; 52import static org.mockito.Matchers.anyChar; 53import static org.mockito.Matchers.anyInt; 54import static org.mockito.Matchers.anyString; 55import static org.mockito.Matchers.eq; 56import static org.mockito.Matchers.isNull; 57import static org.mockito.Mockito.doNothing; 58import static org.mockito.Mockito.doReturn; 59import static org.mockito.Mockito.mock; 60import static org.mockito.Mockito.never; 61import static org.mockito.Mockito.times; 62import static org.mockito.Mockito.when; 63import static org.mockito.Mockito.verify; 64 65public class BluetoothPhoneServiceTest extends TelecomTestCase { 66 67 private static final int TEST_DTMF_TONE = 0; 68 private static final String TEST_ACCOUNT_ADDRESS = "//foo.com/"; 69 private static final int TEST_ACCOUNT_INDEX = 0; 70 71 // match up with BluetoothPhoneServiceImpl 72 private static final int CALL_STATE_ACTIVE = 0; 73 private static final int CALL_STATE_HELD = 1; 74 private static final int CALL_STATE_DIALING = 2; 75 private static final int CALL_STATE_ALERTING = 3; 76 private static final int CALL_STATE_INCOMING = 4; 77 private static final int CALL_STATE_WAITING = 5; 78 private static final int CALL_STATE_IDLE = 6; 79 // Terminate all held or set UDUB("busy") to a waiting call 80 private static final int CHLD_TYPE_RELEASEHELD = 0; 81 // Terminate all active calls and accepts a waiting/held call 82 private static final int CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD = 1; 83 // Hold all active calls and accepts a waiting/held call 84 private static final int CHLD_TYPE_HOLDACTIVE_ACCEPTHELD = 2; 85 // Add all held calls to a conference 86 private static final int CHLD_TYPE_ADDHELDTOCONF = 3; 87 88 private BluetoothPhoneServiceImpl mBluetoothPhoneService; 89 private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { 90 }; 91 92 @Mock CallsManager mMockCallsManager; 93 @Mock PhoneAccountRegistrar mMockPhoneAccountRegistrar; 94 @Mock BluetoothHeadsetProxy mMockBluetoothHeadset; 95 96 @Override 97 public void setUp() throws Exception { 98 super.setUp(); 99 MockitoAnnotations.initMocks(this); 100 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 101 102 // Ensure initialization does not actually try to access any of the CallsManager fields. 103 // This also works to return null if it is not overwritten later in the test. 104 doNothing().when(mMockCallsManager).addListener(any( 105 CallsManager.CallsManagerListener.class)); 106 doReturn(null).when(mMockCallsManager).getActiveCall(); 107 doReturn(null).when(mMockCallsManager).getRingingCall(); 108 doReturn(null).when(mMockCallsManager).getHeldCall(); 109 doReturn(null).when(mMockCallsManager).getOutgoingCall(); 110 doReturn(0).when(mMockCallsManager).getNumHeldCalls(); 111 mBluetoothPhoneService = new BluetoothPhoneServiceImpl(mContext, mLock, mMockCallsManager, 112 mMockPhoneAccountRegistrar); 113 114 // Bring in test Bluetooth Headset 115 mBluetoothPhoneService.setBluetoothHeadset(mMockBluetoothHeadset); 116 } 117 118 @Override 119 public void tearDown() throws Exception { 120 121 mBluetoothPhoneService = null; 122 super.tearDown(); 123 } 124 125 @SmallTest 126 public void testHeadsetAnswerCall() throws Exception { 127 Call mockCall = createRingingCall(); 128 129 boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall(); 130 131 verify(mMockCallsManager).answerCall(eq(mockCall), any(int.class)); 132 assertEquals(callAnswered, true); 133 } 134 135 @SmallTest 136 public void testHeadsetAnswerCallNull() throws Exception { 137 when(mMockCallsManager.getRingingCall()).thenReturn(null); 138 139 boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall(); 140 141 verify(mMockCallsManager,never()).answerCall(any(Call.class), any(int.class)); 142 assertEquals(callAnswered, false); 143 } 144 145 @SmallTest 146 public void testHeadsetHangupCall() throws Exception { 147 Call mockCall = createForegroundCall(); 148 149 boolean callHungup = mBluetoothPhoneService.mBinder.hangupCall(); 150 151 verify(mMockCallsManager).disconnectCall(eq(mockCall)); 152 assertEquals(callHungup, true); 153 } 154 155 @SmallTest 156 public void testHeadsetHangupCallNull() throws Exception { 157 when(mMockCallsManager.getForegroundCall()).thenReturn(null); 158 159 boolean callHungup = mBluetoothPhoneService.mBinder.hangupCall(); 160 161 verify(mMockCallsManager,never()).disconnectCall(any(Call.class)); 162 assertEquals(callHungup, false); 163 } 164 165 @SmallTest 166 public void testHeadsetSendDTMF() throws Exception { 167 Call mockCall = createForegroundCall(); 168 169 boolean sentDtmf = mBluetoothPhoneService.mBinder.sendDtmf(TEST_DTMF_TONE); 170 171 verify(mMockCallsManager).playDtmfTone(eq(mockCall), eq((char) TEST_DTMF_TONE)); 172 verify(mMockCallsManager).stopDtmfTone(eq(mockCall)); 173 assertEquals(sentDtmf, true); 174 } 175 176 @SmallTest 177 public void testHeadsetSendDTMFNull() throws Exception { 178 when(mMockCallsManager.getForegroundCall()).thenReturn(null); 179 180 boolean sentDtmf = mBluetoothPhoneService.mBinder.sendDtmf(TEST_DTMF_TONE); 181 182 verify(mMockCallsManager,never()).playDtmfTone(any(Call.class), anyChar()); 183 verify(mMockCallsManager,never()).stopDtmfTone(any(Call.class)); 184 assertEquals(sentDtmf, false); 185 } 186 187 @SmallTest 188 public void testGetNetworkOperator() throws Exception { 189 Call mockCall = createForegroundCall(); 190 PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX); 191 when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser( 192 any(PhoneAccountHandle.class))).thenReturn(fakePhoneAccount); 193 194 String networkOperator = mBluetoothPhoneService.mBinder.getNetworkOperator(); 195 196 assertEquals(networkOperator, "label0"); 197 } 198 199 @SmallTest 200 public void testGetNetworkOperatorNoPhoneAccount() throws Exception { 201 when(mMockCallsManager.getForegroundCall()).thenReturn(null); 202 203 String networkOperator = mBluetoothPhoneService.mBinder.getNetworkOperator(); 204 205 assertEquals(networkOperator, "label1"); 206 } 207 208 @SmallTest 209 public void testGetSubscriberNumber() throws Exception { 210 Call mockCall = createForegroundCall(); 211 PhoneAccount fakePhoneAccount = makeQuickAccount("id0", TEST_ACCOUNT_INDEX); 212 when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser( 213 any(PhoneAccountHandle.class))).thenReturn(fakePhoneAccount); 214 215 String subscriberNumber = mBluetoothPhoneService.mBinder.getSubscriberNumber(); 216 217 assertEquals(subscriberNumber, TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX); 218 } 219 220 @SmallTest 221 public void testGetSubscriberNumberFallbackToTelephony() throws Exception { 222 Call mockCall = createForegroundCall(); 223 String fakeNumber = "8675309"; 224 when(mMockPhoneAccountRegistrar.getPhoneAccountOfCurrentUser( 225 any(PhoneAccountHandle.class))).thenReturn(null); 226 when(mMockPhoneAccountRegistrar.getPhoneAccountUnchecked( 227 any(PhoneAccountHandle.class))).thenReturn(null); 228 when(TelephonyManager.from(mContext).getLine1Number()).thenReturn(fakeNumber); 229 230 String subscriberNumber = mBluetoothPhoneService.mBinder.getSubscriberNumber(); 231 232 assertEquals(subscriberNumber, fakeNumber); 233 } 234 235 @MediumTest 236 public void testListCurrentCallsOneCall() throws Exception { 237 ArrayList<Call> calls = new ArrayList<>(); 238 Call activeCall = createActiveCall(); 239 when(activeCall.getState()).thenReturn(CallState.ACTIVE); 240 calls.add(activeCall); 241 when(activeCall.isConference()).thenReturn(false); 242 when(activeCall.getHandle()).thenReturn(Uri.parse("tel:555-000")); 243 when(mMockCallsManager.getCalls()).thenReturn(calls); 244 245 mBluetoothPhoneService.mBinder.listCurrentCalls(); 246 247 verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(0), eq(0), eq(false), 248 eq("555-000"), eq(PhoneNumberUtils.TOA_Unknown)); 249 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 250 } 251 252 @MediumTest 253 public void testConferenceInProgressCDMA() throws Exception { 254 // If two calls are being conferenced and updateHeadsetWithCallState runs while this is 255 // still occuring, it will look like there is an active and held call still while we are 256 // transitioning into a conference. 257 // Call has been put into a CDMA "conference" with one call on hold. 258 ArrayList<Call> calls = new ArrayList<>(); 259 Call parentCall = createActiveCall(); 260 final Call confCall1 = mock(Call.class); 261 final Call confCall2 = createHeldCall(); 262 calls.add(parentCall); 263 calls.add(confCall1); 264 calls.add(confCall2); 265 when(mMockCallsManager.getCalls()).thenReturn(calls); 266 when(confCall1.getState()).thenReturn(CallState.ACTIVE); 267 when(confCall2.getState()).thenReturn(CallState.ACTIVE); 268 when(confCall1.isIncoming()).thenReturn(false); 269 when(confCall2.isIncoming()).thenReturn(true); 270 when(confCall1.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 271 Uri.parse("tel:555-0000"))); 272 when(confCall2.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 273 Uri.parse("tel:555-0001"))); 274 addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); 275 addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); 276 removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 277 when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1); 278 when(parentCall.isConference()).thenReturn(true); 279 when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{ 280 add(confCall1); 281 add(confCall2); 282 }}); 283 //Add links from child calls to parent 284 when(confCall1.getParentCall()).thenReturn(parentCall); 285 when(confCall2.getParentCall()).thenReturn(parentCall); 286 287 mBluetoothPhoneService.mBinder.queryPhoneState(); 288 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), 289 eq(""), eq(128)); 290 when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true); 291 mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall); 292 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), 293 eq(""), eq(128)); 294 when(mMockCallsManager.getHeldCall()).thenReturn(null); 295 // Spurious call to onIsConferencedChanged. 296 mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall); 297 // Make sure the call has only occurred collectively 2 times (not on the third) 298 verify(mMockBluetoothHeadset, times(2)).phoneStateChanged(any(int.class), 299 any(int.class), any(int.class), any(String.class), any(int.class)); 300 } 301 302 @MediumTest 303 public void testListCurrentCallsCdmaHold() throws Exception { 304 // Call has been put into a CDMA "conference" with one call on hold. 305 ArrayList<Call> calls = new ArrayList<>(); 306 Call parentCall = createActiveCall(); 307 final Call foregroundCall = mock(Call.class); 308 final Call heldCall = createHeldCall(); 309 calls.add(parentCall); 310 calls.add(foregroundCall); 311 calls.add(heldCall); 312 when(mMockCallsManager.getCalls()).thenReturn(calls); 313 when(foregroundCall.getState()).thenReturn(CallState.ACTIVE); 314 when(heldCall.getState()).thenReturn(CallState.ACTIVE); 315 when(foregroundCall.isIncoming()).thenReturn(false); 316 when(heldCall.isIncoming()).thenReturn(true); 317 when(foregroundCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 318 Uri.parse("tel:555-0000"))); 319 when(heldCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 320 Uri.parse("tel:555-0001"))); 321 addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); 322 addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); 323 removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 324 when(parentCall.getConferenceLevelActiveCall()).thenReturn(foregroundCall); 325 when(parentCall.isConference()).thenReturn(true); 326 when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{ 327 add(foregroundCall); 328 add(heldCall); 329 }}); 330 //Add links from child calls to parent 331 when(foregroundCall.getParentCall()).thenReturn(parentCall); 332 when(heldCall.getParentCall()).thenReturn(parentCall); 333 334 mBluetoothPhoneService.mBinder.listCurrentCalls(); 335 336 verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0), 337 eq(false), eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown)); 338 verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_HELD), eq(0), 339 eq(false), eq("555-0001"), eq(PhoneNumberUtils.TOA_Unknown)); 340 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 341 } 342 343 @MediumTest 344 public void testListCurrentCallsCdmaConference() throws Exception { 345 // Call is in a true CDMA conference 346 ArrayList<Call> calls = new ArrayList<>(); 347 Call parentCall = createActiveCall(); 348 final Call confCall1 = mock(Call.class); 349 final Call confCall2 = createHeldCall(); 350 calls.add(parentCall); 351 calls.add(confCall1); 352 calls.add(confCall2); 353 when(mMockCallsManager.getCalls()).thenReturn(calls); 354 when(confCall1.getState()).thenReturn(CallState.ACTIVE); 355 when(confCall2.getState()).thenReturn(CallState.ACTIVE); 356 when(confCall1.isIncoming()).thenReturn(false); 357 when(confCall2.isIncoming()).thenReturn(true); 358 when(confCall1.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 359 Uri.parse("tel:555-0000"))); 360 when(confCall2.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 361 Uri.parse("tel:555-0001"))); 362 removeCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); 363 removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 364 when(parentCall.wasConferencePreviouslyMerged()).thenReturn(true); 365 when(parentCall.getConferenceLevelActiveCall()).thenReturn(confCall1); 366 when(parentCall.isConference()).thenReturn(true); 367 when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{ 368 add(confCall1); 369 add(confCall2); 370 }}); 371 //Add links from child calls to parent 372 when(confCall1.getParentCall()).thenReturn(parentCall); 373 when(confCall2.getParentCall()).thenReturn(parentCall); 374 375 mBluetoothPhoneService.mBinder.listCurrentCalls(); 376 377 verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(0), eq(CALL_STATE_ACTIVE), eq(0), 378 eq(true), eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown)); 379 verify(mMockBluetoothHeadset).clccResponse(eq(2), eq(1), eq(CALL_STATE_ACTIVE), eq(0), 380 eq(true), eq("555-0001"), eq(PhoneNumberUtils.TOA_Unknown)); 381 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 382 } 383 384 @MediumTest 385 public void testWaitingCallClccResponse() throws Exception { 386 ArrayList<Call> calls = new ArrayList<>(); 387 when(mMockCallsManager.getCalls()).thenReturn(calls); 388 // This test does not define a value for getForegroundCall(), so this ringing call will 389 // be treated as if it is a waiting call when listCurrentCalls() is invoked. 390 Call waitingCall = createRingingCall(); 391 calls.add(waitingCall); 392 when(waitingCall.isIncoming()).thenReturn(true); 393 when(waitingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 394 Uri.parse("tel:555-0000"))); 395 when(waitingCall.getState()).thenReturn(CallState.RINGING); 396 when(waitingCall.isConference()).thenReturn(false); 397 398 mBluetoothPhoneService.mBinder.listCurrentCalls(); 399 verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_WAITING, 0, false, 400 "555-0000", PhoneNumberUtils.TOA_Unknown); 401 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 402 verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(), 403 anyInt(), anyInt(), anyInt(), anyBoolean(), anyString(), anyInt()); 404 } 405 406 @MediumTest 407 public void testNewCallClccResponse() throws Exception { 408 ArrayList<Call> calls = new ArrayList<>(); 409 when(mMockCallsManager.getCalls()).thenReturn(calls); 410 Call newCall = createForegroundCall(); 411 calls.add(newCall); 412 when(newCall.getState()).thenReturn(CallState.NEW); 413 when(newCall.isConference()).thenReturn(false); 414 415 mBluetoothPhoneService.mBinder.listCurrentCalls(); 416 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 417 verify(mMockBluetoothHeadset, times(1)).clccResponse(anyInt(), 418 anyInt(), anyInt(), anyInt(), anyBoolean(), anyString(), anyInt()); 419 } 420 421 @MediumTest 422 public void testRingingCallClccResponse() throws Exception { 423 ArrayList<Call> calls = new ArrayList<>(); 424 when(mMockCallsManager.getCalls()).thenReturn(calls); 425 Call ringingCall = createForegroundCall(); 426 calls.add(ringingCall); 427 when(ringingCall.getState()).thenReturn(CallState.RINGING); 428 when(ringingCall.isIncoming()).thenReturn(true); 429 when(ringingCall.isConference()).thenReturn(false); 430 when(ringingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 431 Uri.parse("tel:555-0000"))); 432 433 mBluetoothPhoneService.mBinder.listCurrentCalls(); 434 verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false, 435 "555-0000", PhoneNumberUtils.TOA_Unknown); 436 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 437 verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(), 438 anyInt(), anyInt(), anyInt(), anyBoolean(), anyString(), anyInt()); 439 } 440 441 @MediumTest 442 public void testCallClccCache() throws Exception { 443 ArrayList<Call> calls = new ArrayList<>(); 444 when(mMockCallsManager.getCalls()).thenReturn(calls); 445 Call ringingCall = createForegroundCall(); 446 calls.add(ringingCall); 447 when(ringingCall.getState()).thenReturn(CallState.RINGING); 448 when(ringingCall.isIncoming()).thenReturn(true); 449 when(ringingCall.isConference()).thenReturn(false); 450 when(ringingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 451 Uri.parse("tel:555-0000"))); 452 453 mBluetoothPhoneService.mBinder.listCurrentCalls(); 454 verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_INCOMING, 0, false, 455 "555-0000", PhoneNumberUtils.TOA_Unknown); 456 457 // Test Caching of old call indicies in clcc 458 when(ringingCall.getState()).thenReturn(CallState.ACTIVE); 459 Call newHoldingCall = createHeldCall(); 460 calls.add(0, newHoldingCall); 461 when(newHoldingCall.getState()).thenReturn(CallState.ON_HOLD); 462 when(newHoldingCall.isIncoming()).thenReturn(true); 463 when(newHoldingCall.isConference()).thenReturn(false); 464 when(newHoldingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 465 Uri.parse("tel:555-0001"))); 466 467 mBluetoothPhoneService.mBinder.listCurrentCalls(); 468 verify(mMockBluetoothHeadset).clccResponse(1, 1, CALL_STATE_ACTIVE, 0, false, 469 "555-0000", PhoneNumberUtils.TOA_Unknown); 470 verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false, 471 "555-0001", PhoneNumberUtils.TOA_Unknown); 472 verify(mMockBluetoothHeadset, times(2)).clccResponse(0, 0, 0, 0, false, null, 0); 473 } 474 475 @MediumTest 476 public void testAlertingCallClccResponse() throws Exception { 477 ArrayList<Call> calls = new ArrayList<>(); 478 when(mMockCallsManager.getCalls()).thenReturn(calls); 479 Call dialingCall = createForegroundCall(); 480 calls.add(dialingCall); 481 when(dialingCall.getState()).thenReturn(CallState.DIALING); 482 when(dialingCall.isIncoming()).thenReturn(false); 483 when(dialingCall.isConference()).thenReturn(false); 484 when(dialingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 485 Uri.parse("tel:555-0000"))); 486 487 mBluetoothPhoneService.mBinder.listCurrentCalls(); 488 verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false, 489 "555-0000", PhoneNumberUtils.TOA_Unknown); 490 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 491 verify(mMockBluetoothHeadset, times(2)).clccResponse(anyInt(), 492 anyInt(), anyInt(), anyInt(), anyBoolean(), anyString(), anyInt()); 493 } 494 495 @MediumTest 496 public void testHoldingCallClccResponse() throws Exception { 497 ArrayList<Call> calls = new ArrayList<>(); 498 when(mMockCallsManager.getCalls()).thenReturn(calls); 499 Call dialingCall = createForegroundCall(); 500 calls.add(dialingCall); 501 when(dialingCall.getState()).thenReturn(CallState.DIALING); 502 when(dialingCall.isIncoming()).thenReturn(false); 503 when(dialingCall.isConference()).thenReturn(false); 504 when(dialingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 505 Uri.parse("tel:555-0000"))); 506 Call holdingCall = createHeldCall(); 507 calls.add(holdingCall); 508 when(holdingCall.getState()).thenReturn(CallState.ON_HOLD); 509 when(holdingCall.isIncoming()).thenReturn(true); 510 when(holdingCall.isConference()).thenReturn(false); 511 when(holdingCall.getGatewayInfo()).thenReturn(new GatewayInfo(null, null, 512 Uri.parse("tel:555-0001"))); 513 514 mBluetoothPhoneService.mBinder.listCurrentCalls(); 515 verify(mMockBluetoothHeadset).clccResponse(1, 0, CALL_STATE_ALERTING, 0, false, 516 "555-0000", PhoneNumberUtils.TOA_Unknown); 517 verify(mMockBluetoothHeadset).clccResponse(2, 1, CALL_STATE_HELD, 0, false, 518 "555-0001", PhoneNumberUtils.TOA_Unknown); 519 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 520 verify(mMockBluetoothHeadset, times(3)).clccResponse(anyInt(), 521 anyInt(), anyInt(), anyInt(), anyBoolean(), anyString(), anyInt()); 522 } 523 524 @MediumTest 525 public void testListCurrentCallsImsConference() throws Exception { 526 ArrayList<Call> calls = new ArrayList<>(); 527 Call parentCall = createActiveCall(); 528 calls.add(parentCall); 529 addCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 530 when(parentCall.isConference()).thenReturn(true); 531 when(parentCall.getState()).thenReturn(CallState.ACTIVE); 532 when(parentCall.isIncoming()).thenReturn(true); 533 when(mMockCallsManager.getCalls()).thenReturn(calls); 534 535 mBluetoothPhoneService.mBinder.listCurrentCalls(); 536 537 verify(mMockBluetoothHeadset).clccResponse(eq(1), eq(1), eq(CALL_STATE_ACTIVE), eq(0), 538 eq(true), (String) isNull(), eq(-1)); 539 verify(mMockBluetoothHeadset).clccResponse(0, 0, 0, 0, false, null, 0); 540 } 541 542 @MediumTest 543 public void testQueryPhoneState() throws Exception { 544 Call ringingCall = createRingingCall(); 545 when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); 546 547 mBluetoothPhoneService.mBinder.queryPhoneState(); 548 549 verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), 550 eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown)); 551 } 552 553 @MediumTest 554 public void testCDMAConferenceQueryState() throws Exception { 555 Call parentConfCall = createActiveCall(); 556 final Call confCall1 = mock(Call.class); 557 final Call confCall2 = mock(Call.class); 558 when(parentConfCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); 559 addCallCapability(parentConfCall, Connection.CAPABILITY_SWAP_CONFERENCE); 560 removeCallCapability(parentConfCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 561 when(parentConfCall.wasConferencePreviouslyMerged()).thenReturn(true); 562 when(parentConfCall.isConference()).thenReturn(true); 563 when(parentConfCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{ 564 add(confCall1); 565 add(confCall2); 566 }}); 567 568 mBluetoothPhoneService.mBinder.queryPhoneState(); 569 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), 570 eq(""), eq(128)); 571 } 572 573 @MediumTest 574 public void testProcessChldTypeReleaseHeldRinging() throws Exception { 575 Call ringingCall = createRingingCall(); 576 577 boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_RELEASEHELD); 578 579 verify(mMockCallsManager).rejectCall(eq(ringingCall), eq(false), any(String.class)); 580 assertEquals(didProcess, true); 581 } 582 583 @MediumTest 584 public void testProcessChldTypeReleaseHeldHold() throws Exception { 585 Call onHoldCall = createHeldCall(); 586 587 boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_RELEASEHELD); 588 589 verify(mMockCallsManager).disconnectCall(eq(onHoldCall)); 590 assertEquals(didProcess, true); 591 } 592 593 @MediumTest 594 public void testProcessChldReleaseActiveRinging() throws Exception { 595 Call activeCall = createActiveCall(); 596 Call ringingCall = createRingingCall(); 597 598 boolean didProcess = mBluetoothPhoneService.mBinder.processChld( 599 CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD); 600 601 verify(mMockCallsManager).disconnectCall(eq(activeCall)); 602 verify(mMockCallsManager).answerCall(eq(ringingCall), any(int.class)); 603 assertEquals(didProcess, true); 604 } 605 606 @MediumTest 607 public void testProcessChldReleaseActiveHold() throws Exception { 608 Call activeCall = createActiveCall(); 609 Call heldCall = createHeldCall(); 610 611 boolean didProcess = mBluetoothPhoneService.mBinder.processChld( 612 CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD); 613 614 verify(mMockCallsManager).disconnectCall(eq(activeCall)); 615 verify(mMockCallsManager).unholdCall(eq(heldCall)); 616 assertEquals(didProcess, true); 617 } 618 619 @MediumTest 620 public void testProcessChldHoldActiveRinging() throws Exception { 621 Call ringingCall = createRingingCall(); 622 623 boolean didProcess = mBluetoothPhoneService.mBinder.processChld( 624 CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); 625 626 verify(mMockCallsManager).answerCall(eq(ringingCall), any(int.class)); 627 assertEquals(didProcess, true); 628 } 629 630 @MediumTest 631 public void testProcessChldHoldActiveUnhold() throws Exception { 632 Call heldCall = createHeldCall(); 633 634 boolean didProcess = mBluetoothPhoneService.mBinder.processChld( 635 CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); 636 637 verify(mMockCallsManager).unholdCall(eq(heldCall)); 638 assertEquals(didProcess, true); 639 } 640 641 @MediumTest 642 public void testProcessChldHoldActiveHold() throws Exception { 643 Call activeCall = createActiveCall(); 644 addCallCapability(activeCall, Connection.CAPABILITY_HOLD); 645 646 boolean didProcess = mBluetoothPhoneService.mBinder.processChld( 647 CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); 648 649 verify(mMockCallsManager).holdCall(eq(activeCall)); 650 assertEquals(didProcess, true); 651 } 652 653 @MediumTest 654 public void testProcessChldAddHeldToConfHolding() throws Exception { 655 Call activeCall = createActiveCall(); 656 addCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE); 657 658 boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_ADDHELDTOCONF); 659 660 verify(activeCall).mergeConference(); 661 assertEquals(didProcess, true); 662 } 663 664 @MediumTest 665 public void testProcessChldAddHeldToConf() throws Exception { 666 Call activeCall = createActiveCall(); 667 removeCallCapability(activeCall, Connection.CAPABILITY_MERGE_CONFERENCE); 668 Call conferenceableCall = mock(Call.class); 669 ArrayList<Call> conferenceableCalls = new ArrayList<>(); 670 conferenceableCalls.add(conferenceableCall); 671 when(activeCall.getConferenceableCalls()).thenReturn(conferenceableCalls); 672 673 boolean didProcess = mBluetoothPhoneService.mBinder.processChld(CHLD_TYPE_ADDHELDTOCONF); 674 675 verify(mMockCallsManager).conference(activeCall, conferenceableCall); 676 assertEquals(didProcess, true); 677 } 678 679 @MediumTest 680 public void testProcessChldHoldActiveSwapConference() throws Exception { 681 // Create an active CDMA Call with a call on hold and simulate a swapConference(). 682 Call parentCall = createActiveCall(); 683 final Call foregroundCall = mock(Call.class); 684 final Call heldCall = createHeldCall(); 685 addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); 686 removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 687 when(parentCall.isConference()).thenReturn(true); 688 when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false); 689 when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{ 690 add(foregroundCall); 691 add(heldCall); 692 }}); 693 694 boolean didProcess = mBluetoothPhoneService.mBinder.processChld( 695 CHLD_TYPE_HOLDACTIVE_ACCEPTHELD); 696 697 verify(parentCall).swapConference(); 698 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), eq(""), 699 eq(128)); 700 assertEquals(didProcess, true); 701 } 702 703 // Testing the CallsManager Listener Functionality on Bluetooth 704 @MediumTest 705 public void testOnCallAddedRinging() throws Exception { 706 Call ringingCall = createRingingCall(); 707 when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-000")); 708 709 mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall); 710 711 verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), 712 eq("555-000"), eq(PhoneNumberUtils.TOA_Unknown)); 713 714 } 715 716 @MediumTest 717 public void testOnCallAddedCdmaActiveHold() throws Exception { 718 // Call has been put into a CDMA "conference" with one call on hold. 719 Call parentCall = createActiveCall(); 720 final Call foregroundCall = mock(Call.class); 721 final Call heldCall = createHeldCall(); 722 addCallCapability(parentCall, Connection.CAPABILITY_MERGE_CONFERENCE); 723 removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 724 when(parentCall.isConference()).thenReturn(true); 725 when(parentCall.getChildCalls()).thenReturn(new LinkedList<Call>() {{ 726 add(foregroundCall); 727 add(heldCall); 728 }}); 729 730 mBluetoothPhoneService.mCallsManagerListener.onCallAdded(parentCall); 731 732 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), 733 eq(""), eq(128)); 734 735 } 736 737 @MediumTest 738 public void testOnCallRemoved() throws Exception { 739 Call activeCall = createActiveCall(); 740 mBluetoothPhoneService.mCallsManagerListener.onCallAdded(activeCall); 741 doReturn(null).when(mMockCallsManager).getActiveCall(); 742 mBluetoothPhoneService.mCallsManagerListener.onCallRemoved(activeCall); 743 744 verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE), 745 eq(""), eq(128)); 746 } 747 748 @MediumTest 749 public void testOnCallStateChangedConnectingCall() throws Exception { 750 Call activeCall = mock(Call.class); 751 Call connectingCall = mock(Call.class); 752 when(connectingCall.getState()).thenReturn(CallState.CONNECTING); 753 ArrayList<Call> calls = new ArrayList<>(); 754 calls.add(connectingCall); 755 calls.add(activeCall); 756 when(mMockCallsManager.getCalls()).thenReturn(calls); 757 758 mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall, 759 CallState.ACTIVE, CallState.ON_HOLD); 760 761 verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), 762 anyString(), anyInt()); 763 } 764 765 @MediumTest 766 public void testOnCallStateChangedDialing() throws Exception { 767 Call activeCall = createActiveCall(); 768 769 mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall, 770 CallState.CONNECTING, CallState.DIALING); 771 772 verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), 773 anyString(), anyInt()); 774 } 775 776 @MediumTest 777 public void testOnCallStateChangedAlerting() throws Exception { 778 Call outgoingCall = createOutgoingCall(); 779 780 mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(outgoingCall, 781 CallState.NEW, CallState.DIALING); 782 783 verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_DIALING, "", 128); 784 verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_ALERTING, "", 128); 785 } 786 787 @MediumTest 788 public void testOnCallStateChanged() throws Exception { 789 Call ringingCall = createRingingCall(); 790 when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); 791 mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall); 792 793 verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), 794 eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown)); 795 796 //Switch to active 797 doReturn(null).when(mMockCallsManager).getRingingCall(); 798 when(mMockCallsManager.getActiveCall()).thenReturn(ringingCall); 799 800 mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall, 801 CallState.RINGING, CallState.ACTIVE); 802 803 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE), 804 eq(""), eq(128)); 805 } 806 807 @MediumTest 808 public void testOnCallStateChangedGSMSwap() throws Exception { 809 Call heldCall = createHeldCall(); 810 when(heldCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); 811 doReturn(2).when(mMockCallsManager).getNumHeldCalls(); 812 mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(heldCall, 813 CallState.ACTIVE, CallState.ON_HOLD); 814 815 verify(mMockBluetoothHeadset, never()).phoneStateChanged(eq(0), eq(2), eq(CALL_STATE_HELD), 816 eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown)); 817 } 818 819 @MediumTest 820 public void testOnIsConferencedChanged() throws Exception { 821 // Start with two calls that are being merged into a CDMA conference call. The 822 // onIsConferencedChanged method will be called multiple times during the call. Make sure 823 // that the bluetooth phone state is updated properly. 824 Call parentCall = createActiveCall(); 825 Call activeCall = mock(Call.class); 826 Call heldCall = createHeldCall(); 827 when(activeCall.getParentCall()).thenReturn(parentCall); 828 when(heldCall.getParentCall()).thenReturn(parentCall); 829 ArrayList<Call> calls = new ArrayList<>(); 830 calls.add(activeCall); 831 when(parentCall.getChildCalls()).thenReturn(calls); 832 when(parentCall.isConference()).thenReturn(true); 833 removeCallCapability(parentCall, Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN); 834 addCallCapability(parentCall, Connection.CAPABILITY_SWAP_CONFERENCE); 835 when(parentCall.wasConferencePreviouslyMerged()).thenReturn(false); 836 837 // Be sure that onIsConferencedChanged rejects spurious changes during set up of 838 // CDMA "conference" 839 mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(activeCall); 840 verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), 841 anyString(), anyInt()); 842 mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(heldCall); 843 verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), 844 anyString(), anyInt()); 845 mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall); 846 verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(), 847 anyString(), anyInt()); 848 849 calls.add(heldCall); 850 mBluetoothPhoneService.mCallsManagerListener.onIsConferencedChanged(parentCall); 851 verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(1), eq(CALL_STATE_IDLE), 852 eq(""), eq(128)); 853 } 854 855 @MediumTest 856 public void testBluetoothAdapterReceiver() throws Exception { 857 Call ringingCall = createRingingCall(); 858 when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000")); 859 860 Intent intent = new Intent(); 861 intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON); 862 mBluetoothPhoneService.mBluetoothAdapterReceiver.onReceive(mContext, intent); 863 864 verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING), 865 eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown)); 866 } 867 868 private void addCallCapability(Call call, int capability) { 869 when(call.can(capability)).thenReturn(true); 870 } 871 872 private void removeCallCapability(Call call, int capability) { 873 when(call.can(capability)).thenReturn(false); 874 } 875 876 private Call createActiveCall() { 877 Call call = mock(Call.class); 878 when(mMockCallsManager.getActiveCall()).thenReturn(call); 879 return call; 880 } 881 882 private Call createRingingCall() { 883 Call call = mock(Call.class); 884 when(mMockCallsManager.getRingingCall()).thenReturn(call); 885 return call; 886 } 887 888 private Call createHeldCall() { 889 Call call = mock(Call.class); 890 when(mMockCallsManager.getHeldCall()).thenReturn(call); 891 return call; 892 } 893 894 private Call createOutgoingCall() { 895 Call call = mock(Call.class); 896 when(mMockCallsManager.getOutgoingCall()).thenReturn(call); 897 return call; 898 } 899 900 private Call createForegroundCall() { 901 Call call = mock(Call.class); 902 when(mMockCallsManager.getForegroundCall()).thenReturn(call); 903 return call; 904 } 905 906 private static ComponentName makeQuickConnectionServiceComponentName() { 907 return new ComponentName("com.android.server.telecom.tests", 908 "com.android.server.telecom.tests.MockConnectionService"); 909 } 910 911 private static PhoneAccountHandle makeQuickAccountHandle(String id) { 912 return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, 913 Binder.getCallingUserHandle()); 914 } 915 916 private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) { 917 return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx); 918 } 919 920 private PhoneAccount makeQuickAccount(String id, int idx) { 921 return makeQuickAccountBuilder(id, idx) 922 .setAddress(Uri.parse(TEST_ACCOUNT_ADDRESS + idx)) 923 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx)) 924 .setCapabilities(idx) 925 .setIcon(Icon.createWithResource( 926 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)) 927 .setShortDescription("desc" + idx) 928 .setIsEnabled(true) 929 .build(); 930 } 931} 932