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